summaryrefslogtreecommitdiffstats
path: root/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp
diff options
context:
space:
mode:
authorMaros Marsalek <mmarsale@cisco.com>2016-11-10 13:31:25 +0100
committerMarek Gradzki <mgradzki@cisco.com>2016-11-19 21:29:39 +0100
commit175197da8ea43335df3daeba4c6296fcd83a057c (patch)
tree110298a990c6191933c2ad65d1a06333bab76cee /v3po/v3po2vpp/src/test/java/io/fd/hc2vpp
parent1813bf59fa53e8eb913d34b212d45b227dead799 (diff)
Post split cleanup
- change groupIds - change packages - update poms Change-Id: I343c5a292a67de1dd50687870ca4ab5b7276e93e Signed-off-by: Maros Marsalek <mmarsale@cisco.com> Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Diffstat (limited to 'v3po/v3po2vpp/src/test/java/io/fd/hc2vpp')
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/DisabledInterfacesManagerTest.java109
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/V3poModuleTest.java96
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/AclCustomizerTest.java156
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/GreCustomizerTest.java197
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceCustomizerTest.java116
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceTypeTestUtils.java40
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/L2CustomizerTest.java150
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/LoopbackCustomizerTest.java105
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ProxyArpCustomizerTest.java97
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/RewriteCustomizerTest.java198
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/RoutingCustomizerTest.java97
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceCustomizerTest.java258
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceL2CustomizerTest.java109
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/TapCustomizerTest.java129
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VhostUserCustomizerTest.java205
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanCustomizerTest.java227
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanGpeCustomizerTest.java218
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/AclWriterTest.java103
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceEthWriterTest.java94
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIp4WriterTest.java189
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIp6WriterTest.java200
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIpAndEthWriterTest.java123
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIpWriterTestUtils.java34
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AclTableContextManagerImplTest.java62
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/PortPairTest.java114
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/EgressIetfAclWriterTest.java151
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/IetfAclCustomizerTest.java114
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/SubInterfaceIetfAclCustomizerTest.java130
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/IetfAclCustomizerTest.java205
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/SubInterfaceAclCustomizerTest.java140
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/SubInterfaceIetfAclCustomizerTest.java155
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/Ipv4AddressCustomizerTest.java338
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/Ipv4NeighbourCustomizerTest.java120
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/SubInterfaceIpv4AddressCustomizerTest.java144
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/subnet/validation/SubnetValidatorTest.java88
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteCustomizerTest.java312
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizerTest.java90
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/GreCustomizerTest.java131
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizerTest.java200
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslatorTest.java55
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/L2CustomizerTest.java145
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizerTest.java114
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizerTest.java129
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2CustomizerTest.java80
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java98
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizerTest.java115
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizerTest.java133
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizerTest.java278
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/acl/ingress/AclCustomizerTest.java99
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/acl/ingress/SubInterfaceAclCustomizerTest.java108
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/Ipv4AddressCustomizerTest.java284
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/Ipv4CustomizerTest.java44
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/SubInterfaceIpv4AddressCustomizerTest.java247
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/pbb/PbbRewriteStateCustomizerTest.java35
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/notification/InterfaceChangeNotificationProducerTest.java112
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/util/SubinterfaceUtilsTest.java32
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/ArpTerminationTableEntryCustomizerTest.java171
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/BridgeDomainCustomizerTest.java276
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/L2FibEntryCustomizerTest.java190
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifySessionReaderTest.java116
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifySessionWriterTest.java179
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifyTableReaderTest.java126
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifyTableWriterTest.java181
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/VppClassifierContextManagerImplTest.java163
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/BridgeDomainCustomizerTest.java47
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/L2FibEntryCustomizerTest.java124
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/VersionCustomizerTest.java60
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/VppStateTest.java326
68 files changed, 9811 insertions, 0 deletions
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/DisabledInterfacesManagerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/DisabledInterfacesManagerTest.java
new file mode 100644
index 000000000..94c95bcf6
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/DisabledInterfacesManagerTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po;
+
+
+
+
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.translate.MappingContext;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.DisabledInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.DisabledInterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.disabled.interfaces.DisabledInterfaceIndex;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.disabled.interfaces.DisabledInterfaceIndexBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.context.rev160909.disabled.interfaces.DisabledInterfaceIndexKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+public class DisabledInterfacesManagerTest {
+
+ private static final InstanceIdentifier<DisabledInterfaces>
+ ROOT_ID = InstanceIdentifier.create(DisabledInterfaces.class);
+ private static final KeyedInstanceIdentifier<DisabledInterfaceIndex, DisabledInterfaceIndexKey> SPECIFIC_ID_1 =
+ ROOT_ID.child(DisabledInterfaceIndex.class, new DisabledInterfaceIndexKey(1));
+ private static final KeyedInstanceIdentifier<DisabledInterfaceIndex, DisabledInterfaceIndexKey> SPECIFIC_ID_4 =
+ ROOT_ID.child(DisabledInterfaceIndex.class, new DisabledInterfaceIndexKey(4));
+
+ @Mock
+ private MappingContext mappingContext;
+ private DisabledInterfacesManager manager;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ manager = new DisabledInterfacesManager();
+ doReturn(Optional.of(new DisabledInterfacesBuilder().setDisabledInterfaceIndex(toIndices(1, 2, 3)).build()))
+ .when(mappingContext)
+ .read(ROOT_ID);
+ doReturn(Optional.of(toIndex(1)))
+ .when(mappingContext)
+ .read(SPECIFIC_ID_1);
+ doReturn(Optional.absent())
+ .when(mappingContext)
+ .read(SPECIFIC_ID_4);
+ }
+
+ @Test
+ public void testGetAll() throws Exception {
+ final List<Integer> disabledInterfaces = manager.getDisabledInterfaces(mappingContext);
+ assertThat(disabledInterfaces, hasItems(1, 2, 3));
+ }
+
+ @Test
+ public void testCheckOne() throws Exception {
+ assertTrue(manager.isInterfaceDisabled(1, mappingContext));
+ assertFalse(manager.isInterfaceDisabled(4, mappingContext));
+ }
+
+ @Test
+ public void testDisable() throws Exception {
+ manager.disableInterface(1, mappingContext);
+ verify(mappingContext).put(SPECIFIC_ID_1, toIndex(1));
+ }
+
+ @Test
+ public void testRemoveDisability() throws Exception {
+ manager.removeDisabledInterface(1, mappingContext);
+ verify(mappingContext).delete(SPECIFIC_ID_1);
+ }
+
+ private List<DisabledInterfaceIndex> toIndices(final int... indices) {
+ return Arrays.stream(indices)
+ .mapToObj(this::toIndex)
+ .collect(Collectors.toList());
+ }
+
+ private DisabledInterfaceIndex toIndex(final int idx) {
+ return new DisabledInterfaceIndexBuilder()
+ .setIndex(idx)
+ .build();
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/V3poModuleTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/V3poModuleTest.java
new file mode 100644
index 000000000..3366af64f
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/V3poModuleTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.Matchers.empty;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import com.google.inject.testing.fieldbinder.Bind;
+import com.google.inject.testing.fieldbinder.BoundFieldModule;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder;
+import io.fd.honeycomb.translate.impl.write.registry.FlatWriterRegistryBuilder;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+
+public class V3poModuleTest {
+
+ @Named("honeycomb-context")
+ @Bind
+ @Mock
+ private MappingContext mappingContext;
+
+ @Named("honeycomb-initializer")
+ @Bind
+ @Mock
+ private DataBroker honeycombInitializer;
+
+ @Named("honeycomb-context")
+ @Bind
+ @Mock
+ private DataBroker honeycombContext;
+
+ @Bind
+ @Mock
+ private FutureJVppCore futureJVppCore;
+
+ @Inject
+ private Set<ReaderFactory> readerFactories = new HashSet<>();
+
+ @Inject
+ private Set<WriterFactory> writerFactories = new HashSet<>();
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ Guice.createInjector(new V3poModule(), BoundFieldModule.of(this)).injectMembers(this);
+ }
+
+ @Test
+ public void testReaderFactories() throws Exception {
+ assertThat(readerFactories, is(not(empty())));
+
+ // Test registration process (all dependencies present, topological order of readers does exist, etc.)
+ final CompositeReaderRegistryBuilder registryBuilder = new CompositeReaderRegistryBuilder();
+ readerFactories.stream().forEach(factory -> factory.init(registryBuilder));
+ assertNotNull(registryBuilder.build());
+ }
+
+ @Test
+ public void testWriterFactories() throws Exception {
+ assertThat(writerFactories, is(not(empty())));
+
+ // Test registration process (all dependencies present, topological order of writers does exist, etc.)
+ final FlatWriterRegistryBuilder registryBuilder = new FlatWriterRegistryBuilder();
+ writerFactories.stream().forEach(factory -> factory.init(registryBuilder));
+ assertNotNull(registryBuilder.build());
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/AclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/AclCustomizerTest.java
new file mode 100644
index 000000000..7f55ae60a
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/AclCustomizerTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.interfaces;
+
+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.v3po.interfaces.acl.ingress.AclCustomizer;
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterfaceReply;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.base.attributes.L2Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.base.attributes.L2AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.acl.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.acl.IngressBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AclCustomizerTest extends WriterCustomizerTest {
+
+ @Mock
+ private VppClassifierContextManager classifyTableContext;
+
+ private AclCustomizer customizer;
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+
+ private static final int ACL_TABLE_INDEX = 0;
+ private static final String ACL_TABLE_NAME = "table0";
+
+ @Override
+ public void setUp() {
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_TEST_INSTANCE);
+ customizer = new AclCustomizer(api, new NamingContext("generatedInterfaceName", IFC_TEST_INSTANCE),
+ classifyTableContext);
+ }
+
+ private InstanceIdentifier<Ingress> getAclId(final String name) {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(name)).augmentation(
+ VppInterfaceAugmentation.class).child(Acl.class).child(Ingress.class);
+ }
+
+ private Ingress generateAcl(final String tableName) {
+ final IngressBuilder builder = new IngressBuilder();
+ final L2Acl l2Acl = new L2AclBuilder().setClassifyTable(tableName).build();
+ builder.setL2Acl(l2Acl);
+ return builder.build();
+ }
+
+ private void whenInputAclSetInterfaceThenSuccess() {
+ doReturn(future(new InputAclSetInterfaceReply())).when(api)
+ .inputAclSetInterface(any(InputAclSetInterface.class));
+ }
+
+ private void whenInputAclSetInterfaceThenFailure() {
+ doReturn(failedFuture()).when(api).inputAclSetInterface(any(InputAclSetInterface.class));
+ }
+
+ private static InputAclSetInterface generateInputAclSetInterface(final byte isAdd, final int ifIndex,
+ final int l2TableIndex) {
+ final InputAclSetInterface request = new InputAclSetInterface();
+ request.isAdd = isAdd;
+ request.l2TableIndex = l2TableIndex;
+ request.ip4TableIndex = ~0;
+ request.ip6TableIndex = ~0;
+ request.swIfIndex = ifIndex;
+ return request;
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ final Ingress acl = generateAcl(ACL_TABLE_NAME);
+ final InstanceIdentifier<Ingress> id = getAclId(IF_NAME);
+
+ whenInputAclSetInterfaceThenSuccess();
+
+ customizer.writeCurrentAttributes(id, acl, writeContext);
+
+ verify(api).inputAclSetInterface(generateInputAclSetInterface((byte) 1, IF_INDEX, ACL_TABLE_INDEX));
+ }
+
+ @Test
+ public void testCreateFailed() throws Exception {
+ final Ingress acl = generateAcl(ACL_TABLE_NAME);
+ final InstanceIdentifier<Ingress> id = getAclId(IF_NAME);
+
+ whenInputAclSetInterfaceThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(id, acl, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).inputAclSetInterface(generateInputAclSetInterface((byte) 1, IF_INDEX, ACL_TABLE_INDEX));
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ final Ingress acl = generateAcl(ACL_TABLE_NAME);
+ final InstanceIdentifier<Ingress> id = getAclId(IF_NAME);
+
+ whenInputAclSetInterfaceThenSuccess();
+
+ customizer.deleteCurrentAttributes(id, acl, writeContext);
+
+ verify(api).inputAclSetInterface(generateInputAclSetInterface((byte) 0, IF_INDEX, ACL_TABLE_INDEX));
+ }
+
+ @Test
+ public void testDeleteFailed() throws Exception {
+ final Ingress acl = generateAcl(ACL_TABLE_NAME);
+ final InstanceIdentifier<Ingress> id = getAclId(IF_NAME);
+
+ whenInputAclSetInterfaceThenFailure();
+
+ try {
+ customizer.deleteCurrentAttributes(id, acl, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).inputAclSetInterface(generateInputAclSetInterface((byte) 0, IF_INDEX, ACL_TABLE_INDEX));
+ return;
+ }
+ fail("WriteFailedException.DeleteFailedException was expected");
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/GreCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/GreCustomizerTest.java
new file mode 100644
index 000000000..da75fa92d
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/GreCustomizerTest.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.interfaces;
+
+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 com.google.common.net.InetAddresses;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+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.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.Gre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.GreBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.GreAddDelTunnel;
+import io.fd.vpp.jvpp.core.dto.GreAddDelTunnelReply;
+
+public class GreCustomizerTest extends WriterCustomizerTest {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ 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 static final byte ADD_GRE = 1;
+ private static final byte DEL_GRE = 0;
+
+ private GreCustomizer customizer;
+
+ @Override
+ public void setUp() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.GreTunnel.class);
+ customizer = new GreCustomizer(api, new NamingContext("generateInterfaceNAme", IFC_TEST_INSTANCE));
+ }
+
+ private void whenGreAddDelTunnelThenSuccess() {
+ final GreAddDelTunnelReply reply = new GreAddDelTunnelReply();
+ reply.swIfIndex = IFACE_ID;
+ doReturn(future(reply)).when(api).greAddDelTunnel(any(GreAddDelTunnel.class));
+ }
+
+ private void whenGreAddDelTunnelThenFailure() {
+ doReturn(failedFuture()).when(api).greAddDelTunnel(any(GreAddDelTunnel.class));
+ }
+
+ private GreAddDelTunnel verifyGreAddDelTunnelWasInvoked(final Gre gre) throws VppInvocationException {
+ ArgumentCaptor<GreAddDelTunnel> argumentCaptor = ArgumentCaptor.forClass(GreAddDelTunnel.class);
+ verify(api).greAddDelTunnel(argumentCaptor.capture());
+ final GreAddDelTunnel actual = argumentCaptor.getValue();
+ assertEquals(0, actual.isIpv6);
+ assertArrayEquals(InetAddresses.forString(gre.getSrc().getIpv4Address().getValue()).getAddress(),
+ actual.srcAddress);
+ assertArrayEquals(InetAddresses.forString(gre.getDst().getIpv4Address().getValue()).getAddress(),
+ actual.dstAddress);
+ assertEquals(gre.getOuterFibId().intValue(), actual.outerFibId);
+ return actual;
+ }
+
+ private void verifyGreAddWasInvoked(final Gre gre) throws VppInvocationException {
+ final GreAddDelTunnel actual = verifyGreAddDelTunnelWasInvoked(gre);
+ assertEquals(ADD_GRE, actual.isAdd);
+ }
+
+ private void verifyGreDeleteWasInvoked(final Gre gre) throws VppInvocationException {
+ final GreAddDelTunnel actual = verifyGreAddDelTunnelWasInvoked(gre);
+ assertEquals(DEL_GRE, actual.isAdd);
+ }
+
+ private static Gre generateGre() {
+ final GreBuilder builder = new GreBuilder();
+ builder.setSrc(new IpAddress(new Ipv4Address("192.168.20.10")));
+ builder.setDst(new IpAddress(new Ipv4Address("192.168.20.11")));
+ builder.setOuterFibId(Long.valueOf(123));
+ return builder.build();
+ }
+
+ @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
+ public void testUpdateCurrentAttributes() throws Exception {
+ try {
+ customizer.updateCurrentAttributes(id, generateGre(), generateGre(), writeContext);
+ } catch (WriteFailedException.UpdateFailedException e) {
+ assertEquals(UnsupportedOperationException.class, e.getCause().getClass());
+ return;
+ }
+ fail("WriteFailedException.UpdateFailedException was expected");
+ }
+
+ @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");
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceCustomizerTest.java
new file mode 100644
index 000000000..c72d43a02
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceCustomizerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfaces;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetFlags;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetFlagsReply;
+
+public class InterfaceCustomizerTest extends WriterCustomizerTest implements ByteDataTranslator {
+ private static final String IFACE_CTX_NAME = "interface-ctx";
+ private static final String IF_NAME = "eth1";
+ private static final int IF_INDEX = 1;
+
+ private InterfaceCustomizer customizer;
+ private InstanceIdentifier<Interface> IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME));
+
+ @Override
+ protected void setUp() throws Exception {
+ customizer = new InterfaceCustomizer(api, new NamingContext("ifacePrefix", IFACE_CTX_NAME));
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFACE_CTX_NAME);
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ final boolean enabled = true;
+ when(api.swInterfaceSetFlags(any())).thenReturn(future(new SwInterfaceSetFlagsReply()));
+ customizer.writeCurrentAttributes(IID, iface(enabled), writeContext);
+ verify(api).swInterfaceSetFlags(expectedRequest(enabled));
+ }
+
+ @Test
+ public void testWriteFailed() {
+ final boolean enabled = false;
+ when(api.swInterfaceSetFlags(any())).thenReturn(failedFuture());
+ try {
+ customizer.writeCurrentAttributes(IID, iface(enabled), writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).swInterfaceSetFlags(expectedRequest(enabled));
+ return;
+ }
+ fail("WriteFailedException expected");
+ }
+
+ @Test
+ public void testUpdate() throws WriteFailedException {
+ when(api.swInterfaceSetFlags(any())).thenReturn(future(new SwInterfaceSetFlagsReply()));
+ customizer.updateCurrentAttributes(IID, iface(false), iface(true), writeContext);
+ verify(api).swInterfaceSetFlags(expectedRequest(true));
+ }
+
+ @Test
+ public void testUpdateFailed() {
+ when(api.swInterfaceSetFlags(any())).thenReturn(failedFuture());
+ try {
+ customizer.updateCurrentAttributes(IID, iface(false), iface(true), writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).swInterfaceSetFlags(expectedRequest(true));
+ return;
+ }
+ fail("WriteFailedException expected");
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ customizer.deleteCurrentAttributes(IID, mock(Interface.class), writeContext);
+ verifyZeroInteractions(api);
+ }
+
+ private Interface iface(final boolean enabled) {
+ return new InterfaceBuilder().setName(IF_NAME).setEnabled(enabled).build();
+ }
+
+ private SwInterfaceSetFlags expectedRequest(final boolean enabled) {
+ final SwInterfaceSetFlags request = new SwInterfaceSetFlags();
+ request.deleted = 0;
+ request.adminUpDown = booleanToByte(enabled);
+ request.linkUpDown = booleanToByte(enabled);
+ request.swIfIndex = IF_INDEX;
+ return request;
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceTypeTestUtils.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceTypeTestUtils.java
new file mode 100644
index 000000000..5bce6aea1
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/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.interfaces;
+
+import static org.mockito.Mockito.doReturn;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.mockito.Matchers;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.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/interfaces/L2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/L2CustomizerTest.java
new file mode 100644
index 000000000..d54bd3392
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/L2CustomizerTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfaces;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.L2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.Interconnection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.interconnection.BridgeBased;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.interconnection.BridgeBasedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.interconnection.XconnectBased;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.interconnection.XconnectBasedBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetL2Bridge;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetL2BridgeReply;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetL2Xconnect;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetL2XconnectReply;
+
+public class L2CustomizerTest extends WriterCustomizerTest implements ByteDataTranslator {
+ private static final String IFACE_CTX_NAME = "interface-ctx";
+ private static final String BD_CTX_NAME = "bd-ctx";
+ private static final String IF1_NAME = "eth1";
+ private static final int IF1_INDEX = 1;
+ private static final String IF2_NAME = "eth2";
+ private static final int IF2_INDEX = 2;
+ private static final InstanceIdentifier<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 setUp() throws Exception {
+ customizer = new L2Customizer(api, new NamingContext("ifacePrefix", IFACE_CTX_NAME),
+ new NamingContext("bdPrefix", BD_CTX_NAME));
+ defineMapping(mappingContext, IF1_NAME, IF1_INDEX, IFACE_CTX_NAME);
+ defineMapping(mappingContext, IF2_NAME, IF2_INDEX, IFACE_CTX_NAME);
+ defineMapping(mappingContext, BD_NAME, BD_INDEX, BD_CTX_NAME);
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ when(api.swInterfaceSetL2Xconnect(any())).thenReturn(future(new SwInterfaceSetL2XconnectReply()));
+ customizer.writeCurrentAttributes(IID, l2(xconnectBased()), writeContext);
+ verify(api).swInterfaceSetL2Xconnect(xconnectRequest(true));
+ }
+
+ @Test
+ public void testWriteFailed() {
+ when(api.swInterfaceSetL2Bridge(any())).thenReturn(failedFuture());
+ try {
+ customizer.writeCurrentAttributes(IID, l2(bridgeBased(false)), writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).swInterfaceSetL2Bridge(bridgeRequest(false, true));
+ return;
+ }
+ fail("WriteFailedException expected");
+ }
+
+ @Test
+ public void testUpdate() throws WriteFailedException {
+ when(api.swInterfaceSetL2Bridge(any())).thenReturn(future(new SwInterfaceSetL2BridgeReply()));
+ customizer.updateCurrentAttributes(IID, l2(bridgeBased(false)), l2(bridgeBased(true)), writeContext);
+ verify(api).swInterfaceSetL2Bridge(bridgeRequest(true, true));
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ when(api.swInterfaceSetL2Xconnect(any())).thenReturn(future(new SwInterfaceSetL2XconnectReply()));
+ customizer.deleteCurrentAttributes(IID, l2(xconnectBased()), writeContext);
+ verify(api).swInterfaceSetL2Xconnect(xconnectRequest(false));
+ }
+
+ @Test
+ public void testDeleteFailed() {
+ when(api.swInterfaceSetL2Bridge(any())).thenReturn(failedFuture());
+ try {
+ customizer.deleteCurrentAttributes(IID, l2(bridgeBased(true)), writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).swInterfaceSetL2Bridge(bridgeRequest(true, false));
+ return;
+ }
+ fail("WriteFailedException expected");
+ }
+
+ private XconnectBased xconnectBased() {
+ return new XconnectBasedBuilder().setXconnectOutgoingInterface(IF2_NAME).build();
+ }
+
+ private SwInterfaceSetL2Xconnect xconnectRequest(final boolean enable) {
+ final SwInterfaceSetL2Xconnect request = new SwInterfaceSetL2Xconnect();
+ request.rxSwIfIndex = IF1_INDEX;
+ request.txSwIfIndex = IF2_INDEX;
+ request.enable = booleanToByte(enable);
+ return request;
+ }
+
+ private BridgeBased bridgeBased(final boolean bvi) {
+ return new BridgeBasedBuilder().setBridgedVirtualInterface(bvi)
+ .setBridgeDomain(BD_NAME).setSplitHorizonGroup((short) 123).build();
+ }
+
+ private SwInterfaceSetL2Bridge bridgeRequest(final boolean bvi, final boolean enable) {
+ final SwInterfaceSetL2Bridge request = new SwInterfaceSetL2Bridge();
+ request.bdId = BD_INDEX;
+ request.rxSwIfIndex = IF1_INDEX;
+ request.bvi = booleanToByte(bvi);
+ request.enable = booleanToByte(enable);
+ request.shg = 123;
+ return request;
+ }
+
+
+ private L2 l2(final Interconnection interconnection) {
+ return new L2Builder().setInterconnection(interconnection).build();
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/LoopbackCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/LoopbackCustomizerTest.java
new file mode 100644
index 000000000..67c90343e
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/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.interfaces;
+
+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.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.core.dto.CreateLoopback;
+import io.fd.vpp.jvpp.core.dto.CreateLoopbackReply;
+import io.fd.vpp.jvpp.core.dto.DeleteLoopback;
+import io.fd.vpp.jvpp.core.dto.DeleteLoopbackReply;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.Loopback;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.LoopbackBuilder;
+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 setUp() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.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();
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ProxyArpCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ProxyArpCustomizerTest.java
new file mode 100644
index 000000000..232d62e9e
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ProxyArpCustomizerTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.interfaces;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.ProxyArp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.ProxyArpBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.ProxyArpAddDel;
+import io.fd.vpp.jvpp.core.dto.ProxyArpAddDelReply;
+
+public class ProxyArpCustomizerTest extends WriterCustomizerTest implements ByteDataTranslator {
+ private static final String IF_NAME = "eth1";
+
+ private ProxyArpCustomizer customizer;
+
+ @Override
+ public void setUp() throws Exception {
+ customizer = new ProxyArpCustomizer(api);
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ when(api.proxyArpAddDel(any())).thenReturn(future(new ProxyArpAddDelReply()));
+ customizer.writeCurrentAttributes(getProxyArpId(IF_NAME), proxyArp(), writeContext);
+ verify(api).proxyArpAddDel(expectedRequest(true));
+ }
+
+ @Test(expected = WriteFailedException.class)
+ public void testWriteFailed() throws WriteFailedException {
+ when(api.proxyArpAddDel(any())).thenReturn(failedFuture());
+ customizer.writeCurrentAttributes(getProxyArpId(IF_NAME), proxyArp(), writeContext);
+ }
+
+ @Test(expected = WriteFailedException.UpdateFailedException.class)
+ public void testUpdate() throws WriteFailedException.UpdateFailedException {
+ customizer.updateCurrentAttributes(getProxyArpId(IF_NAME), proxyArp(), proxyArp(), writeContext);
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ when(api.proxyArpAddDel(any())).thenReturn(future(new ProxyArpAddDelReply()));
+ customizer.deleteCurrentAttributes(getProxyArpId(IF_NAME), proxyArp(), writeContext);
+ verify(api).proxyArpAddDel(expectedRequest(false));
+ }
+
+ @Test(expected = WriteFailedException.DeleteFailedException.class)
+ public void testDeleteFailed() throws WriteFailedException {
+ when(api.proxyArpAddDel(any())).thenReturn(failedFuture());
+ customizer.deleteCurrentAttributes(getProxyArpId(IF_NAME), proxyArp(), writeContext);
+ }
+
+ private ProxyArp proxyArp() {
+ return new ProxyArpBuilder().setVrfId(123L).setHighAddr(new Ipv4AddressNoZone("10.1.1.2"))
+ .setLowAddr(new Ipv4AddressNoZone("10.1.1.1")).build();
+ }
+
+ private ProxyArpAddDel expectedRequest(final boolean isAdd) {
+ final ProxyArpAddDel request = new ProxyArpAddDel();
+ request.isAdd = booleanToByte(isAdd);
+ request.vrfId = 123;
+ request.lowAddress = new byte[]{10,1,1,1};
+ request.hiAddress = new byte[]{10,1,1,2};
+ return request;
+ }
+
+ private InstanceIdentifier<ProxyArp> getProxyArpId(final String eth0) {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(eth0)).augmentation(
+ VppInterfaceAugmentation.class).child(ProxyArp.class);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/RewriteCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/RewriteCustomizerTest.java
new file mode 100644
index 000000000..fa9914233
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/RewriteCustomizerTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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.interfaces;
+
+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.translate.util.NamingContext;
+import io.fd.hc2vpp.common.translate.util.TagRewriteOperation;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.L2InterfaceVlanTagRewrite;
+import io.fd.vpp.jvpp.core.dto.L2InterfaceVlanTagRewriteReply;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214._802dot1q;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.l2.Rewrite;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.l2.RewriteBuilder;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class RewriteCustomizerTest extends WriterCustomizerTest {
+
+ private NamingContext namingContext;
+ private RewriteCustomizer customizer;
+
+ 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 InstanceIdentifier<Rewrite> VLAN_IID;
+
+ @Override
+ public void setUp() 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 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;
+ }
+
+ 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");
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/RoutingCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/RoutingCustomizerTest.java
new file mode 100644
index 000000000..a61cd149b
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/RoutingCustomizerTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.interfaces;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetTable;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetTableReply;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.Routing;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.RoutingBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class RoutingCustomizerTest extends WriterCustomizerTest {
+ private static final String IFACE_CTX_NAME = "interface-ctx";
+ private static final String IF_NAME = "eth1";
+ private static final int IF_INDEX = 1;
+ private static final InstanceIdentifier<Routing> IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(Routing.class);
+
+ private RoutingCustomizer customizer;
+
+ @Override
+ protected void setUp() throws Exception {
+ customizer = new RoutingCustomizer(api, new NamingContext("ifacePrefix", IFACE_CTX_NAME));
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFACE_CTX_NAME);
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ final int vrfId = 123;
+ when(api.swInterfaceSetTable(any())).thenReturn(future(new SwInterfaceSetTableReply()));
+ customizer.writeCurrentAttributes(IID, routing(vrfId), writeContext);
+ verify(api).swInterfaceSetTable(expectedRequest(vrfId));
+ }
+
+ @Test(expected = WriteFailedException.class)
+ public void testWriteFailed() throws WriteFailedException {
+ when(api.swInterfaceSetTable(any())).thenReturn(failedFuture());
+ customizer.writeCurrentAttributes(IID, routing(213), writeContext);
+ }
+
+ @Test(expected = WriteFailedException.class)
+ public void testUpdateFailed() throws WriteFailedException {
+ when(api.swInterfaceSetTable(any())).thenReturn(failedFuture());
+ customizer.updateCurrentAttributes(IID, routing(123L), routing(321L), writeContext);
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ 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(api.swInterfaceSetTable(any())).thenReturn(failedFuture());
+ customizer.deleteCurrentAttributes(IID, routing(123), writeContext);
+ }
+
+ private Routing routing(final long vrfId) {
+ return new RoutingBuilder().setIpv4VrfId(vrfId).build();
+ }
+
+ private SwInterfaceSetTable expectedRequest(final int vrfId) {
+ final SwInterfaceSetTable request = new SwInterfaceSetTable();
+ request.isIpv6 = 0;
+ request.swIfIndex = IF_INDEX;
+ request.vrfId = vrfId;
+ return request;
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceCustomizerTest.java
new file mode 100644
index 000000000..fd71a8015
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceCustomizerTest.java
@@ -0,0 +1,258 @@
+/*
+ * 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.interfaces;
+
+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.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+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.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214._802dot1ad;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.match.attributes.match.type.vlan.tagged.VlanTaggedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.TagsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.tags.Tag;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.tags.TagBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.tags.TagKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.CreateSubif;
+import io.fd.vpp.jvpp.core.dto.CreateSubifReply;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetFlags;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetFlagsReply;
+
+public class SubInterfaceCustomizerTest extends WriterCustomizerTest {
+
+ private NamingContext namingContext;
+ private SubInterfaceCustomizer customizer;
+
+ 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;
+
+ 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));
+ }
+
+ @Override
+ public void setUp() 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 static Tag generateTag(final short index, final Class<? extends Dot1qTagVlanType> tagType,
+ final Dot1qTag.VlanId vlanId) {
+ TagBuilder tag = new TagBuilder();
+ tag.setIndex(index);
+ tag.setKey(new TagKey(index));
+ final Dot1qTagBuilder dtag = new Dot1qTagBuilder();
+ dtag.setTagType(tagType);
+ dtag.setVlanId(vlanId);
+ tag.setDot1qTag(dtag.build());
+ return tag.build();
+ }
+
+ private static Match generateMatch() {
+ final MatchBuilder match = new MatchBuilder();
+ final VlanTaggedBuilder tagged = new VlanTaggedBuilder();
+ tagged.setMatchExactTags(true);
+ match.setMatchType(
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.match.attributes.match.type.VlanTaggedBuilder()
+ .setVlanTagged(tagged.build()).build());
+ return match.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;
+ 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);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceL2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceL2CustomizerTest.java
new file mode 100644
index 000000000..29b1b0d99
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceL2CustomizerTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfaces;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+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.hc2vpp.common.test.write.WriterCustomizerTest;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.interconnection.BridgeBasedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.L2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.L2Builder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetL2Bridge;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetL2BridgeReply;
+
+public class SubInterfaceL2CustomizerTest extends WriterCustomizerTest implements ByteDataTranslator {
+ private static final String IFACE_CTX_NAME = "interface-ctx";
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+ private static final String SUBIF_NAME = "local0.0";
+ private static final int SUBIF_INDEX = 11;
+ private static final long SUBIF_ID = 0;
+
+ private static final InstanceIdentifier<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 setUp() throws Exception {
+ customizer = new SubInterfaceL2Customizer(api, new NamingContext("ifacePrefix", IFACE_CTX_NAME),
+ new NamingContext("bdPrefix", BD_CTX_NAME));
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFACE_CTX_NAME);
+ defineMapping(mappingContext, SUBIF_NAME, SUBIF_INDEX, IFACE_CTX_NAME);
+ defineMapping(mappingContext, BD_NAME, BD_INDEX, BD_CTX_NAME);
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ final boolean bvi = true;
+ when(api.swInterfaceSetL2Bridge(any())).thenReturn(future(new SwInterfaceSetL2BridgeReply()));
+ customizer.writeCurrentAttributes(IID, l2(bvi), writeContext);
+ verify(api).swInterfaceSetL2Bridge(bridgeRequest(bvi, true));
+ }
+
+ @Test
+ public void testUpdate() throws WriteFailedException {
+ final boolean bvi = false;
+ when(api.swInterfaceSetL2Bridge(any())).thenReturn(future(new SwInterfaceSetL2BridgeReply()));
+ customizer.updateCurrentAttributes(IID, l2(true), l2(bvi), writeContext);
+ verify(api).swInterfaceSetL2Bridge(bridgeRequest(bvi, true));
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ final boolean bvi = true;
+ when(api.swInterfaceSetL2Bridge(any())).thenReturn(future(new SwInterfaceSetL2BridgeReply()));
+ customizer.deleteCurrentAttributes(IID, l2(bvi), writeContext);
+ verify(api).swInterfaceSetL2Bridge(bridgeRequest(bvi, false));
+ }
+
+ private L2 l2(final boolean bvi) {
+ return new L2Builder().setInterconnection(new BridgeBasedBuilder().setBridgedVirtualInterface(bvi)
+ .setBridgeDomain(BD_NAME).setSplitHorizonGroup((short) 123).build()).build();
+ }
+
+ private SwInterfaceSetL2Bridge bridgeRequest(final boolean bvi, final boolean enable) {
+ final SwInterfaceSetL2Bridge request = new SwInterfaceSetL2Bridge();
+ request.bdId = BD_INDEX;
+ request.rxSwIfIndex = SUBIF_INDEX;
+ request.bvi = booleanToByte(bvi);
+ request.enable = booleanToByte(enable);
+ request.shg = 123;
+ return request;
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/TapCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/TapCustomizerTest.java
new file mode 100644
index 000000000..f55859ace
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/TapCustomizerTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.interfaces;
+
+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.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.Tap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.TapBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.TapConnect;
+import io.fd.vpp.jvpp.core.dto.TapConnectReply;
+import io.fd.vpp.jvpp.core.dto.TapDelete;
+import io.fd.vpp.jvpp.core.dto.TapDeleteReply;
+import io.fd.vpp.jvpp.core.dto.TapModify;
+import io.fd.vpp.jvpp.core.dto.TapModifyReply;
+
+public class TapCustomizerTest extends WriterCustomizerTest {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private TapCustomizer tapCustomizer;
+
+ @Override
+ public void setUp() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.Tap.class);
+ tapCustomizer = new TapCustomizer(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 TapConnectReply t = new TapConnectReply();
+ t.swIfIndex = idx++;
+ return future(t);
+ }
+ }).when(api).tapConnect(any(TapConnect.class));
+
+ tapCustomizer.writeCurrentAttributes(getTapId("tap"), getTapData("tap", "ff:ff:ff:ff:ff:ff"), writeContext);
+ tapCustomizer.writeCurrentAttributes(getTapId("tap2"), getTapData("tap2", "ff:ff:ff:ff:ff:ff"), writeContext);
+
+ verify(api, times(2)).tapConnect(any(TapConnect.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 testModify() throws Exception {
+ final TapConnectReply t = new TapConnectReply();
+ t.swIfIndex = 0;
+ doReturn(future(t)).when(api).tapConnect(any(TapConnect.class));
+
+ final TapModifyReply tmodif = new TapModifyReply();
+ tmodif.swIfIndex = 0;
+ doReturn(future(tmodif)).when(api).tapModify(any(TapModify.class));
+
+ tapCustomizer.writeCurrentAttributes(getTapId("tap"), getTapData("tap", "ff:ff:ff:ff:ff:ff"), writeContext);
+
+ defineMapping(mappingContext, "tap", 1, IFC_TEST_INSTANCE);
+ tapCustomizer.updateCurrentAttributes(getTapId("tap"), getTapData("tap", "ff:ff:ff:ff:ff:ff"), getTapData("tap", "ff:ff:ff:ff:ff:f1"), writeContext);
+
+ verify(api).tapConnect(any(TapConnect.class));
+ verify(api).tapModify(any(TapModify.class));
+
+ verify(mappingContext).put(eq(mappingIid("tap", IFC_TEST_INSTANCE)), eq(
+ mapping("tap", 0).get()));
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ final TapConnectReply t = new TapConnectReply();
+ t.swIfIndex = 0;
+ doReturn(future(t)).when(api).tapConnect(any(TapConnect.class));
+
+ doReturn(future(new TapDeleteReply())).when(api).tapDelete(any(TapDelete.class));
+
+ tapCustomizer.writeCurrentAttributes(getTapId("tap"), getTapData("tap", "ff:ff:ff:ff:ff:ff"), writeContext);
+ defineMapping(mappingContext, "tap", 1, IFC_TEST_INSTANCE);
+ tapCustomizer.deleteCurrentAttributes(getTapId("tap"), getTapData("tap", "ff:ff:ff:ff:ff:ff"), writeContext);
+
+ verify(api).tapConnect(any(TapConnect.class));
+ verify(api).tapDelete(any(TapDelete.class));
+ verify(mappingContext).delete(eq(mappingIid("tap", IFC_TEST_INSTANCE)));
+ }
+
+ private InstanceIdentifier<Tap> getTapId(final String tap) {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(tap)).augmentation(
+ VppInterfaceAugmentation.class).child(Tap.class);
+ }
+
+ private Tap getTapData(final String tap, final String mac) {
+ return new TapBuilder().setTapName(tap).setMac(new PhysAddress(mac)).build();
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VhostUserCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VhostUserCustomizerTest.java
new file mode 100644
index 000000000..4f8b7a6d4
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/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.interfaces;
+
+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.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VhostUserRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.VhostUser;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.VhostUserBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.CreateVhostUserIf;
+import io.fd.vpp.jvpp.core.dto.CreateVhostUserIfReply;
+import io.fd.vpp.jvpp.core.dto.DeleteVhostUserIf;
+import io.fd.vpp.jvpp.core.dto.DeleteVhostUserIfReply;
+import io.fd.vpp.jvpp.core.dto.ModifyVhostUserIf;
+import io.fd.vpp.jvpp.core.dto.ModifyVhostUserIfReply;
+
+public class VhostUserCustomizerTest extends WriterCustomizerTest implements Ipv4Translator {
+
+ private VhostUserCustomizer customizer;
+ 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);
+
+ @Override
+ public void setUp() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.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;
+ }
+
+ private static VhostUser generateVhostUser(final VhostUserRole role, final String socketName) {
+ VhostUserBuilder builder = new VhostUserBuilder();
+ builder.setRole(role);
+ builder.setSocket(socketName);
+ return builder.build();
+ }
+
+ @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");
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanCustomizerTest.java
new file mode 100644
index 000000000..f5b6873de
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanCustomizerTest.java
@@ -0,0 +1,227 @@
+/*
+ * 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.interfaces;
+
+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 com.google.common.net.InetAddresses;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+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.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanVni;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.Vxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.VxlanBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.VxlanAddDelTunnel;
+import io.fd.vpp.jvpp.core.dto.VxlanAddDelTunnelReply;
+
+public class VxlanCustomizerTest extends WriterCustomizerTest {
+
+ 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;
+
+ @Override
+ public void setUp() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.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(InetAddresses.forString(vxlan.getSrc().getIpv4Address().getValue()).getAddress(),
+ actual.srcAddress);
+ assertArrayEquals(InetAddresses.forString(vxlan.getDst().getIpv4Address().getValue()).getAddress(),
+ actual.dstAddress);
+ assertEquals(vxlan.getEncapVrfId().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);
+ }
+
+ private static Vxlan generateVxlan(long vni) {
+ final VxlanBuilder builder = new VxlanBuilder();
+ builder.setSrc(new IpAddress(new Ipv4Address("192.168.20.10")));
+ builder.setDst(new IpAddress(new Ipv4Address("192.168.20.11")));
+ builder.setEncapVrfId(Long.valueOf(123));
+ builder.setVni(new VxlanVni(Long.valueOf(vni)));
+ return builder.build();
+ }
+
+ private static Vxlan generateVxlan() {
+ return generateVxlan(Long.valueOf(11));
+ }
+
+ @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
+ public void testUpdateCurrentAttributes() throws Exception {
+ try {
+ customizer.updateCurrentAttributes(id, generateVxlan(10), generateVxlan(11), writeContext);
+ } catch (WriteFailedException.UpdateFailedException e) {
+ assertEquals(UnsupportedOperationException.class, e.getCause().getClass());
+ return;
+ }
+ fail("WriteFailedException.UpdateFailedException was expected");
+ }
+
+ @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");
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanGpeCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanGpeCustomizerTest.java
new file mode 100644
index 000000000..7337c16e3
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanGpeCustomizerTest.java
@@ -0,0 +1,218 @@
+/*
+ * 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.interfaces;
+
+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 com.google.common.net.InetAddresses;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+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.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanGpeNextProtocol;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanGpeVni;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.VxlanGpe;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.VxlanGpeBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.VxlanGpeAddDelTunnel;
+import io.fd.vpp.jvpp.core.dto.VxlanGpeAddDelTunnelReply;
+
+public class VxlanGpeCustomizerTest extends WriterCustomizerTest {
+
+ 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;
+
+ @Override
+ public void setUp() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.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(InetAddresses.forString(vxlanGpe.getLocal().getIpv4Address().getValue()).getAddress(),
+ actual.local);
+ assertArrayEquals(InetAddresses.forString(vxlanGpe.getRemote().getIpv4Address().getValue()).getAddress(),
+ 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);
+ }
+
+ private static VxlanGpe generateVxlanGpe(long vni) {
+ final VxlanGpeBuilder builder = new VxlanGpeBuilder();
+ builder.setLocal(new IpAddress(new Ipv4Address("192.168.20.10")));
+ builder.setRemote(new IpAddress(new Ipv4Address("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));
+ }
+
+ @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
+ public void testUpdateCurrentAttributes() throws Exception {
+ try {
+ customizer.updateCurrentAttributes(id, generateVxlanGpe(10), generateVxlanGpe(11), writeContext);
+ } catch (WriteFailedException.UpdateFailedException e) {
+ assertEquals(UnsupportedOperationException.class, e.getCause().getClass());
+ return;
+ }
+ fail("WriteFailedException.UpdateFailedException was expected");
+ }
+
+ @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");
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/AclWriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/AclWriterTest.java
new file mode 100644
index 000000000..7641bd912
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/AclWriterTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.interfaces.acl;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AccessLists;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.EthAcl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.AccessListsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.access.lists.AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.IetfAclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.ietf.acl.IngressBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AclWriterTest extends WriterCustomizerTest {
+
+ private static final String ACL_NAME = "acl1";
+ private static final Class<? extends AclBase> ACL_TYPE = EthAcl.class;
+ private static final InstanceIdentifier<Acl> IID =
+ InstanceIdentifier.create(AccessLists.class).child(Acl.class, new AclKey(ACL_NAME, ACL_TYPE));
+
+ @Mock
+ private Acl acl;
+ private IetfAclWriter customizer;
+
+ @Override
+ public void setUp() {
+ customizer = new IetfAclWriter();
+ when(acl.getAclName()).thenReturn(ACL_NAME);
+ doReturn(ACL_TYPE).when(acl).getAclType();
+ }
+
+ private void defineInterfacesContext(final List<Interface> interfaces) {
+ when(writeContext.readAfter(InstanceIdentifier.create(Interfaces.class))).thenReturn(Optional.of(
+ new InterfacesBuilder().setInterface(interfaces).build()
+ ));
+ }
+
+ @Test
+ public void testWrite() throws Exception {
+ customizer.writeCurrentAttributes(IID, acl, writeContext);
+ }
+
+ @Test
+ public void testUpdate() throws WriteFailedException {
+ defineInterfacesContext(Collections.emptyList());
+ customizer.updateCurrentAttributes(IID, acl, acl, writeContext);
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ defineInterfacesContext(Collections.emptyList());
+ customizer.deleteCurrentAttributes(IID, acl, writeContext);
+ }
+
+ @Test(expected = WriteFailedException.class)
+ public void testDeleteFailed() throws WriteFailedException {
+ final Interface iface = new InterfaceBuilder().addAugmentation(VppInterfaceAugmentation.class,
+ new VppInterfaceAugmentationBuilder().setIetfAcl(
+ new IetfAclBuilder().setIngress(
+ new IngressBuilder().setAccessLists(
+ new AccessListsBuilder().setAcl(
+ Collections.singletonList(new AclBuilder().setName(ACL_NAME).setType(ACL_TYPE).build())
+ ).build()
+ ).build()
+ ).build()
+ ).build()
+ ).build();
+ defineInterfacesContext(Collections.singletonList(iface));
+ customizer.deleteCurrentAttributes(IID, acl, writeContext);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceEthWriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceEthWriterTest.java
new file mode 100644
index 000000000..ec1321670
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceEthWriterTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.interfaces.acl.common;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.DenyBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceEth;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceEthBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.InterfaceMode;
+
+public class AceEthWriterTest {
+
+ private AceEthWriter writer;
+ private PacketHandling action;
+ private AceEth aceEth;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ writer = new AceEthWriter();
+ action = new DenyBuilder().setDeny(true).build();
+ aceEth = new AceEthBuilder()
+ .setDestinationMacAddress(new MacAddress("11:22:33:44:55:66"))
+ .setDestinationMacAddressMask(new MacAddress("ff:ff:ff:ff:ff:ff"))
+ .setSourceMacAddress(new MacAddress("aa:bb:cc:dd:ee:ff"))
+ .setSourceMacAddressMask(new MacAddress("ff:ff:ff:00:00:00"))
+ .build();
+ }
+
+ @Test
+ public void testCreateTable() {
+ final int nextTableIndex = 42;
+ final ClassifyAddDelTable request = writer.createTable(aceEth, InterfaceMode.L2, nextTableIndex, 0);
+
+ assertEquals(1, request.isAdd);
+ assertEquals(-1, request.tableIndex);
+ assertEquals(1, request.nbuckets);
+ assertEquals(nextTableIndex, request.nextTableIndex);
+ assertEquals(0, request.skipNVectors);
+ assertEquals(AceEthWriter.MATCH_N_VECTORS, request.matchNVectors);
+ assertEquals(AceEthWriter.TABLE_MEM_SIZE, request.memorySize);
+
+ byte[] expectedMask = new byte[] {
+ // destination MAC:
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ // source MAC:
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, 0, 0, 0,
+ 0, 0, 0, 0
+ };
+ assertArrayEquals(expectedMask, request.mask);
+ }
+
+ @Test
+ public void testCreateClassifySession() {
+ final int tableIndex = 123;
+ final ClassifyAddDelSession request = writer.createSession(action, aceEth, InterfaceMode.L2, tableIndex, 0).get(0);
+
+ assertEquals(1, request.isAdd);
+ assertEquals(tableIndex, request.tableIndex);
+ assertEquals(0, request.hitNextIndex);
+
+ byte[] expectedMatch = new byte[] {
+ // destination MAC:
+ (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66,
+ // source MAC:
+ (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd, (byte) 0xee, (byte) 0xff,
+ 0, 0, 0, 0
+ };
+ assertArrayEquals(expectedMatch, request.match);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIp4WriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIp4WriterTest.java
new file mode 100644
index 000000000..cb3b246c6
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIp4WriterTest.java
@@ -0,0 +1,189 @@
+/*
+ * 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.interfaces.acl.common;
+
+import static io.fd.hc2vpp.v3po.interfaces.acl.common.AclTranslator.VLAN_TAG_LEN;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.DenyBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Dscp;
+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.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.DestinationPortRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.SourcePortRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.InterfaceMode;
+
+public class AceIp4WriterTest {
+
+ private AceIp4Writer writer;
+ private PacketHandling action;
+ private AceIp aceIp;
+
+ @Before
+ public void setUp() throws Exception {
+ initMocks(this);
+ writer = new AceIp4Writer();
+ action = new DenyBuilder().setDeny(true).build();
+ aceIp = new AceIpBuilder()
+ .setProtocol((short) 132)
+ .setDscp(new Dscp((short) 11))
+ .setAceIpVersion(new AceIpv4Builder()
+ .setSourceIpv4Network(new Ipv4Prefix("1.2.3.4/32"))
+ .setDestinationIpv4Network(new Ipv4Prefix("1.2.4.5/24"))
+ .build())
+ .setSourcePortRange(new SourcePortRangeBuilder().setLowerPort(new PortNumber(0x1111)).build())
+ .setDestinationPortRange(new DestinationPortRangeBuilder().setLowerPort(new PortNumber(0x2222)).build())
+ .build();
+ }
+
+ private static void verifyTableRequest(final ClassifyAddDelTable request, final int nextTableIndex,
+ final int vlanTags, final boolean isL2) {
+ assertEquals(1, request.isAdd);
+ assertEquals(-1, request.tableIndex);
+ assertEquals(1, request.nbuckets);
+ assertEquals(nextTableIndex, request.nextTableIndex);
+ assertEquals(0, request.skipNVectors);
+ assertEquals(AceIp4Writer.MATCH_N_VECTORS, request.matchNVectors);
+ assertEquals(AceIp4Writer.TABLE_MEM_SIZE, request.memorySize);
+
+ byte[] expectedMask = new byte[] {
+ // L2:
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ // dscp:
+ (byte) 0x00, (byte) 0xfc,
+ // protocol:
+ 0, 0, 0, 0, 0, 0, 0, (byte) 0xff, 0, 0,
+ // source address:
+ -1, -1, -1, -1,
+ // destination address:
+ -1, -1, -1, 0,
+ // source and destination port:
+ -1, -1, -1, -1,
+ // padding:
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ if (isL2) {
+ expectedMask[12] = (byte) 0xff;
+ expectedMask[13] = (byte) 0xff;
+ }
+ AceIpWriterTestUtils
+ .assertArrayEqualsWithOffset(expectedMask, expectedMask.length, request.mask, vlanTags * VLAN_TAG_LEN);
+
+ }
+
+ private static void verifySessionRequest(final ClassifyAddDelSession request, final int tableIndex,
+ final int vlanTags, final boolean isL2) {
+ assertEquals(1, request.isAdd);
+ assertEquals(tableIndex, request.tableIndex);
+ assertEquals(0, request.hitNextIndex);
+
+ byte[] expectedMatch = new byte[] {
+ // L2:
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ // dscp:
+ 0, (byte) 0x2c,
+ // protocol (132):
+ 0, 0, 0, 0, 0, 0, 0, (byte) 132, 0, 0,
+ // source address:
+ 1, 2, 3, 4,
+ // destination address:
+ 1, 2, 4, 0,
+ // source and destination port:
+ 0x11, 0x11, 0x22, 0x22,
+ // padding:
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ if (isL2) {
+ expectedMatch[12] = (byte) 0x08;
+ expectedMatch[13] = (byte) 0x00;
+ }
+ AceIpWriterTestUtils.assertArrayEqualsWithOffset(expectedMatch, expectedMatch.length, request.match, vlanTags * VLAN_TAG_LEN);
+
+ }
+
+ @Test
+ public void testCreateTable() throws Exception {
+ final int nextTableIndex = 42;
+ final ClassifyAddDelTable request = writer.createTable(aceIp, InterfaceMode.L3, nextTableIndex, 0);
+ verifyTableRequest(request, nextTableIndex, 0, false);
+ }
+
+ @Test
+ public void testCreateTableForL2Interface() throws Exception {
+ final int nextTableIndex = 42;
+ final ClassifyAddDelTable request = writer.createTable(aceIp, InterfaceMode.L2, nextTableIndex, 0);
+ verifyTableRequest(request, nextTableIndex, 0, true);
+ }
+
+ @Test
+ public void testCreateTable1VlanTag() throws Exception {
+ final int nextTableIndex = 42;
+ final int vlanTags = 1;
+ final ClassifyAddDelTable request = writer.createTable(aceIp, InterfaceMode.L3, nextTableIndex, vlanTags);
+ verifyTableRequest(request, nextTableIndex, vlanTags, false);
+ }
+
+ @Test
+ public void testCreateTable2VlanTags() throws Exception {
+ final int nextTableIndex = 42;
+ final int vlanTags = 2;
+ final ClassifyAddDelTable request = writer.createTable(aceIp, InterfaceMode.L3, nextTableIndex, vlanTags);
+ verifyTableRequest(request, nextTableIndex, vlanTags, false);
+ }
+
+ @Test
+ public void testCreateClassifySession() throws Exception {
+ final int tableIndex = 123;
+ final ClassifyAddDelSession request = writer.createSession(action, aceIp, InterfaceMode.L3, tableIndex, 0).get(0);
+ verifySessionRequest(request, tableIndex, 0, false);
+ }
+
+ @Test
+ public void testCreateClassifySessionForL2Interface() throws Exception {
+ final int tableIndex = 123;
+ final ClassifyAddDelSession request = writer.createSession(action, aceIp, InterfaceMode.L2, tableIndex, 0).get(0);
+ verifySessionRequest(request, tableIndex, 0, true);
+ }
+
+ @Test
+ public void testCreateClassifySession1VlanTag() throws Exception {
+ final int tableIndex = 123;
+ final int vlanTags = 1;
+ final ClassifyAddDelSession request = writer.createSession(action, aceIp, InterfaceMode.L3, tableIndex, vlanTags).get(0);
+ verifySessionRequest(request, tableIndex, vlanTags, false);
+ }
+
+ @Test
+ public void testCreateClassifySession2VlanTags() throws Exception {
+ final int tableIndex = 123;
+ final int vlanTags = 2;
+ final ClassifyAddDelSession request = writer.createSession(action, aceIp, InterfaceMode.L3, tableIndex, vlanTags).get(0);
+
+ verifySessionRequest(request, tableIndex, vlanTags, false);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIp6WriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIp6WriterTest.java
new file mode 100644
index 000000000..30dff951b
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIp6WriterTest.java
@@ -0,0 +1,200 @@
+/*
+ * 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.interfaces.acl.common;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.DenyBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv6Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Dscp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6FlowLabel;
+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.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.DestinationPortRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.SourcePortRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.InterfaceMode;
+
+public class AceIp6WriterTest {
+
+ private AceIp6Writer writer;
+ private PacketHandling action;
+ private AceIp aceIp;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ writer = new AceIp6Writer();
+ action = new DenyBuilder().setDeny(true).build();
+ aceIp = new AceIpBuilder()
+ .setProtocol((short) 132)
+ .setDscp(new Dscp((short) 11))
+ .setAceIpVersion(new AceIpv6Builder()
+ .setFlowLabel(new Ipv6FlowLabel(123L))
+ .setSourceIpv6Network(new Ipv6Prefix("2001:db8:85a3:8d3:1319:8a2e:370:7348/128"))
+ .setDestinationIpv6Network(new Ipv6Prefix("fe80:1234:5678:abcd:ef01::/64"))
+ .build())
+ .setSourcePortRange(new SourcePortRangeBuilder().setLowerPort(new PortNumber(0x1111)).build())
+ .setDestinationPortRange(new DestinationPortRangeBuilder().setLowerPort(new PortNumber(0x2222)).build())
+ .build();
+ }
+
+
+ private static void verifyTableRequest(final ClassifyAddDelTable request, final int nextTableIndex,
+ final int vlanTags, final boolean isL2) {
+ assertEquals(1, request.isAdd);
+ assertEquals(-1, request.tableIndex);
+ assertEquals(1, request.nbuckets);
+ assertEquals(nextTableIndex, request.nextTableIndex);
+ assertEquals(0, request.skipNVectors);
+ assertEquals(vlanTags == 2 ? 5 : 4, request.matchNVectors);
+ assertEquals(AceIp6Writer.TABLE_MEM_SIZE, request.memorySize);
+
+ byte[] expectedMask = new byte[] {
+ // L2:
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ // dscp, flow:
+ (byte) 0x0f, (byte) 0xcf, (byte) 0xff, (byte) 0xff,
+ // protocol:
+ 0, 0, (byte) 0xff, 0,
+ // source address:
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ // destination address:
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ // source and destination port:
+ -1, -1, -1, -1,
+ // padding to multiple of 16B:
+ 0, 0, 0, 0, 0, 0
+ };
+
+ if (isL2) {
+ expectedMask[12] = (byte) 0xff;
+ expectedMask[13] = (byte) 0xff;
+ }
+ AceIpWriterTestUtils.assertArrayEqualsWithOffset(expectedMask, vlanTags == 2 ? 80 : 64, request.mask, vlanTags * AclTranslator.VLAN_TAG_LEN);
+ }
+
+ private static void verifySessionRequest(final ClassifyAddDelSession request, final int tableIndex,
+ final int vlanTags, final boolean isL2) {
+ assertEquals(1, request.isAdd);
+ assertEquals(tableIndex, request.tableIndex);
+ assertEquals(0, request.hitNextIndex);
+
+ byte[] expectedMatch = new byte[] {
+ // L2:
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ // dscp(11), flow(123):
+ (byte) 0x02, (byte) 0xc0, (byte) 0x00, (byte) 0x7b,
+ // protocol (132):
+ 0, 0, (byte) 132, 0,
+ // source address:
+ (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, (byte) 0x85, (byte) 0xa3, (byte) 0x08, (byte) 0xd3,
+ (byte) 0x13, (byte) 0x19, (byte) 0x8a, (byte) 0x2e, (byte) 0x03, (byte) 0x70, (byte) 0x73, (byte) 0x48,
+ // destination address:
+ (byte) 0xfe, (byte) 0x80, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0xab, (byte) 0xcd,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ // source and destination port:
+ 0x11, 0x11, 0x22, 0x22,
+ // padding to multiple of 16B:
+ 0, 0, 0, 0, 0, 0
+ };
+
+ if (isL2) {
+ expectedMatch[12] = (byte) 0x86;
+ expectedMatch[13] = (byte) 0xdd;
+ }
+ AceIpWriterTestUtils.assertArrayEqualsWithOffset(expectedMatch, vlanTags == 2 ? 80 : 64, request.match, vlanTags * AclTranslator.VLAN_TAG_LEN);
+
+ }
+
+ @Test
+ public void testCreateTable() {
+ final int nextTableIndex = 42;
+ final ClassifyAddDelTable request =
+ writer.createTable(aceIp, InterfaceMode.L3, nextTableIndex, 0);
+ verifyTableRequest(request, nextTableIndex, 0, false);
+ }
+
+ @Test
+ public void testCreateTableForL2Interface() {
+ final int nextTableIndex = 42;
+ final ClassifyAddDelTable request =
+ writer.createTable(aceIp, InterfaceMode.L2, nextTableIndex, 0);
+ verifyTableRequest(request, nextTableIndex, 0, true);
+ }
+
+ @Test
+ public void testCreateTable1VlanTag() {
+ final int nextTableIndex = 42;
+ final int vlanTags = 1;
+ final ClassifyAddDelTable request =
+ writer.createTable(aceIp, InterfaceMode.L3, nextTableIndex, vlanTags);
+ verifyTableRequest(request, nextTableIndex, vlanTags, false);
+ }
+
+ @Test
+ public void testCreateTable2VlanTags() {
+ final int nextTableIndex = 42;
+ final int vlanTags = 2;
+ final ClassifyAddDelTable request =
+ writer.createTable(aceIp, InterfaceMode.L3, nextTableIndex, vlanTags);
+ verifyTableRequest(request, nextTableIndex, vlanTags, false);
+ }
+
+ @Test
+ public void testCreateClassifySession() {
+ final int tableIndex = 123;
+ final ClassifyAddDelSession request =
+ writer.createSession(action, aceIp, InterfaceMode.L3, tableIndex, 0).get(0);
+ verifySessionRequest(request, tableIndex, 0, false);
+ }
+
+ @Test
+ public void testCreateClassifySessionForL2Interface() {
+ final int tableIndex = 123;
+ final ClassifyAddDelSession request =
+ writer.createSession(action, aceIp, InterfaceMode.L2, tableIndex, 0).get(0);
+ verifySessionRequest(request, tableIndex, 0, true);
+ }
+
+ @Test
+ public void testCreateClassifySession1VlanTag() {
+ final int tableIndex = 123;
+ final int vlanTags = 1;
+ final ClassifyAddDelSession request =
+ writer.createSession(action, aceIp, InterfaceMode.L3, tableIndex, vlanTags).get(0);
+ verifySessionRequest(request, tableIndex, vlanTags, false);
+ }
+
+ @Test
+ public void testCreateClassifySession2VlanTags() {
+ final int tableIndex = 123;
+ final int vlanTags = 2;
+ final ClassifyAddDelSession request =
+ writer.createSession(action, aceIp, InterfaceMode.L3, tableIndex, vlanTags).get(0);
+ verifySessionRequest(request, tableIndex, vlanTags, false);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIpAndEthWriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIpAndEthWriterTest.java
new file mode 100644
index 000000000..34c7334b8
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIpAndEthWriterTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.interfaces.acl.common;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.DenyBuilder;
+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.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.DestinationPortRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.SourcePortRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.InterfaceMode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpAndEth;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpAndEthBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.and.eth.ace.ip.version.AceIpv4Builder;
+
+public class AceIpAndEthWriterTest {
+
+ private AceIpAndEthWriter writer;
+ private PacketHandling action;
+ private AceIpAndEth ace;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ writer = new AceIpAndEthWriter();
+ action = new DenyBuilder().setDeny(true).build();
+ ace = new AceIpAndEthBuilder()
+ .setDestinationMacAddress(new MacAddress("11:22:33:44:55:66"))
+ .setSourceMacAddress(new MacAddress("aa:bb:cc:dd:ee:ff"))
+ .setAceIpVersion(new AceIpv4Builder()
+ .setSourceIpv4Network(new Ipv4Prefix("1.2.3.4/32")).build())
+ .setSourcePortRange(new SourcePortRangeBuilder().setLowerPort(new PortNumber(0x1111)).build())
+ .setDestinationPortRange(new DestinationPortRangeBuilder().setLowerPort(new PortNumber(0x2222)).build())
+ .build();
+ }
+
+ @Test
+ public void testCreateTable() {
+ final int nextTableIndex = 42;
+ final ClassifyAddDelTable request = writer.createTable(ace, InterfaceMode.L2, nextTableIndex, 0);
+
+ assertEquals(1, request.isAdd);
+ assertEquals(-1, request.tableIndex);
+ assertEquals(1, request.nbuckets);
+ assertEquals(nextTableIndex, request.nextTableIndex);
+ assertEquals(0, request.skipNVectors);
+ assertEquals(3, request.matchNVectors);
+ assertEquals(AceEthWriter.TABLE_MEM_SIZE, request.memorySize);
+
+ byte[] expectedMask = new byte[] {
+ // destination MAC:
+ -1, -1, -1, -1, -1, -1,
+ // source MAC:
+ -1, -1, -1, -1, -1, -1,
+ // ether type:
+ -1, -1,
+ // IP header
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ // source address:
+ -1, -1, -1, -1,
+ // destination address:
+ 0, 0, 0, 0,
+ // source and destination port:
+ -1, -1, -1, -1,
+ // padding:
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ assertArrayEquals(expectedMask, request.mask);
+ }
+
+ @Test
+ public void testCreateClassifySession() {
+ final int tableIndex = 123;
+ final ClassifyAddDelSession request = writer.createSession(action, ace, InterfaceMode.L2, tableIndex, 0).get(0);
+
+ assertEquals(1, request.isAdd);
+ assertEquals(tableIndex, request.tableIndex);
+ assertEquals(0, request.hitNextIndex);
+
+ byte[] expectedMatch = new byte[] {
+ // destination MAC:
+ (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66,
+ // source MAC:
+ (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd, (byte) 0xee, (byte) 0xff,
+ // ether type (IP4):
+ 0x08, 0,
+ // IP header
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ // source address:
+ 1, 2, 3, 4,
+ // destination address:
+ 0, 0, 0, 0,
+ // source and destination port:
+ 0x11, 0x11, 0x22, 0x22,
+ // padding:
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ assertArrayEquals(expectedMatch, request.match);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIpWriterTestUtils.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIpWriterTestUtils.java
new file mode 100644
index 000000000..087d91d26
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AceIpWriterTestUtils.java
@@ -0,0 +1,34 @@
+/*
+ * 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.interfaces.acl.common;
+
+import static org.junit.Assert.assertArrayEquals;
+
+final class AceIpWriterTestUtils {
+
+ private AceIpWriterTestUtils() {
+ throw new UnsupportedOperationException("This utility class cannot be instantiated");
+ }
+
+ protected static void assertArrayEqualsWithOffset(final byte[] baseExpected, final int expectedLength, final byte[] actual,
+ final int offset) {
+ byte[] expected = new byte[expectedLength];
+ System.arraycopy(baseExpected, 0, expected, offset, Math.min(baseExpected.length, expectedLength-offset));
+
+ assertArrayEquals(expected, actual);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AclTableContextManagerImplTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AclTableContextManagerImplTest.java
new file mode 100644
index 000000000..3f106ccce
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/AclTableContextManagerImplTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.interfaces.acl.common;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.honeycomb.translate.MappingContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.context.rev161214.mapping.entry.context.attributes.acl.mapping.entry.context.MappingTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.context.rev161214.mapping.entry.context.attributes.acl.mapping.entry.context.mapping.table.MappingEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.context.rev161214.mapping.entry.context.attributes.acl.mapping.entry.context.mapping.table.MappingEntryBuilder;
+
+public class AclTableContextManagerImplTest {
+
+ private AclTableContextManagerImpl ctx;
+ @Mock
+ private MappingContext mappingContext;
+ private static final int INDEX = 42;
+
+ @Before
+ public void setUp() throws Exception {
+ initMocks(this);
+ ctx = new AclTableContextManagerImpl(MappingTable.Direction.Ingress);
+ }
+
+ @Test
+ public void testAddEntry() throws Exception {
+ final MappingEntry entry =
+ new MappingEntryBuilder().setL2TableId(1).setIp4TableId(2).setIp6TableId(3).setIndex(INDEX).build();
+ ctx.addEntry(entry, mappingContext);
+ verify(mappingContext).put(ctx.getId(INDEX), entry);
+ }
+
+ @Test
+ public void testRemoveEntry() throws Exception {
+ ctx.removeEntry(INDEX, mappingContext);
+ verify(mappingContext).delete(ctx.getId(INDEX));
+ }
+
+ @Test
+ public void testReadEntry() throws Exception {
+ ctx.getEntry(INDEX, mappingContext);
+ verify(mappingContext).read(ctx.getId(INDEX));
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/PortPairTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/PortPairTest.java
new file mode 100644
index 000000000..f5c319fb6
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/common/PortPairTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.interfaces.acl.common;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.hasSize;
+
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.DestinationPortRange;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.DestinationPortRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.SourcePortRange;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.SourcePortRangeBuilder;
+
+public class PortPairTest {
+
+ @Test
+ public void testSingleSrc() {
+ final SourcePortRange src = new SourcePortRangeBuilder().setLowerPort(new PortNumber(123)).build();
+ final List<PortPair> portPairs = PortPair.fromRange(src, null);
+ assertThat(portPairs, hasSize(1));
+ assertThat(portPairs, contains(new PortPair(123, null)));
+ }
+
+ @Test
+ public void testSrcRange() {
+ final SourcePortRange src = new SourcePortRangeBuilder()
+ .setLowerPort(new PortNumber(123))
+ .setUpperPort(new PortNumber(125)).build();
+ final List<PortPair> portPairs = PortPair.fromRange(src, null);
+ assertThat(portPairs, hasSize(3));
+ assertThat(portPairs, contains(new PortPair(123, null), new PortPair(124, null), new PortPair(125, null)));
+ }
+
+ @Test
+ public void testSrcRangeWithDst() {
+ final SourcePortRange src = new SourcePortRangeBuilder()
+ .setLowerPort(new PortNumber(123))
+ .setUpperPort(new PortNumber(125)).build();
+ final DestinationPortRange dst = new DestinationPortRangeBuilder().setLowerPort(new PortNumber(111)).build();
+ final List<PortPair> portPairs = PortPair.fromRange(src, dst);
+ assertThat(portPairs, hasSize(3));
+ assertThat(portPairs, contains(new PortPair(123, 111), new PortPair(124, 111), new PortPair(125, 111)));
+ }
+
+ @Test
+ public void testSingleDst() {
+ final DestinationPortRange dst = new DestinationPortRangeBuilder().setLowerPort(new PortNumber(123)).build();
+ final List<PortPair> portPairs = PortPair.fromRange(null, dst);
+ assertThat(portPairs, hasSize(1));
+ assertThat(portPairs, contains(new PortPair(null, 123)));
+ }
+
+ @Test
+ public void testDstRange() {
+ final DestinationPortRange dst = new DestinationPortRangeBuilder()
+ .setLowerPort(new PortNumber(10))
+ .setUpperPort(new PortNumber(11)).build();
+ final List<PortPair> portPairs = PortPair.fromRange(null, dst);
+ assertThat(portPairs, hasSize(2));
+ assertThat(portPairs, contains(new PortPair(null, 10), new PortPair(null, 11)));
+ }
+
+ @Test
+ public void testDstRangeWithSrc() {
+ final SourcePortRange src = new SourcePortRangeBuilder().setLowerPort(new PortNumber(111)).build();
+ final DestinationPortRange dst = new DestinationPortRangeBuilder()
+ .setLowerPort(new PortNumber(10))
+ .setUpperPort(new PortNumber(11)).build();
+ final List<PortPair> portPairs = PortPair.fromRange(src, dst);
+ assertThat(portPairs, hasSize(2));
+ assertThat(portPairs, contains(new PortPair(111, 10), new PortPair(111, 11)));
+ }
+
+ @Test
+ public void testSinglePair() {
+ final SourcePortRange src = new SourcePortRangeBuilder().setLowerPort(new PortNumber(123)).build();
+ final DestinationPortRange dst = new DestinationPortRangeBuilder().setLowerPort(new PortNumber(321)).build();
+ final List<PortPair> portPairs = PortPair.fromRange(src, dst);
+ assertThat(portPairs, hasSize(1));
+ assertThat(portPairs, contains(new PortPair(123, 321)));
+ }
+
+ @Test
+ public void testCartesianProduct() {
+ final SourcePortRange src = new SourcePortRangeBuilder()
+ .setLowerPort(new PortNumber(1))
+ .setUpperPort(new PortNumber(2)).build();
+ final DestinationPortRange dst = new DestinationPortRangeBuilder()
+ .setLowerPort(new PortNumber(1))
+ .setUpperPort(new PortNumber(3)).build();
+ final List<PortPair> portPairs = PortPair.fromRange(src, dst);
+ assertThat(portPairs, hasSize(6));
+ assertThat(portPairs,
+ contains(new PortPair(1, 1), new PortPair(1, 2), new PortPair(1, 3), new PortPair(2, 1), new PortPair(2, 2),
+ new PortPair(2, 3)));
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/EgressIetfAclWriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/EgressIetfAclWriterTest.java
new file mode 100644
index 000000000..0b75b5bce
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/EgressIetfAclWriterTest.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.interfaces.acl.egress;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.v3po.interfaces.acl.common.AclTableContextManager;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSessionReply;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply;
+import io.fd.vpp.jvpp.core.dto.ClassifySetInterfaceL2Tables;
+import io.fd.vpp.jvpp.core.dto.ClassifySetInterfaceL2TablesReply;
+import java.util.Collections;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.EthAcl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.AccessListEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.AceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.ActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.MatchesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.PermitBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.ietf.acl.Egress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.ietf.acl.EgressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.context.rev161214.mapping.entry.context.attributes.acl.mapping.entry.context.mapping.table.MappingEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.InterfaceMode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.AccessLists;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.AccessListsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.access.lists.AclBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class EgressIetfAclWriterTest extends WriterCustomizerTest {
+
+ private static final int IF_INDEX = 1;
+ private static final String ACL_NAME = "acl1";
+ private static final Class<? extends AclBase> ACL_TYPE = EthAcl.class;
+
+ private EgressIetfAclWriter writer;
+ @Mock
+ private AclTableContextManager aclCtx;
+ @Mock
+ private InstanceIdentifier<?> id;
+
+ @Override
+ protected void setUp() throws Exception {
+ writer = new EgressIetfAclWriter(api, aclCtx);
+ }
+
+ private static ClassifyAddDelTable classifyAddDelTable(final int tableIndex) {
+ final ClassifyAddDelTable reply = new ClassifyAddDelTable();
+ reply.tableIndex = tableIndex;
+ return reply;
+ }
+
+ private ClassifySetInterfaceL2Tables classifySetInterfaceL2TablesRequest() {
+ final ClassifySetInterfaceL2Tables request = new ClassifySetInterfaceL2Tables();
+ request.isInput = 0;
+ request.ip4TableIndex = -1;
+ request.ip6TableIndex = -1;
+ request.otherTableIndex = -1;
+ request.swIfIndex = IF_INDEX;
+ return request;
+ }
+
+ @Test
+ public void testDeleteAcl() throws Exception {
+ when(api.classifyAddDelTable(any())).thenReturn(future(new ClassifyAddDelTableReply()));
+ when(api.classifySetInterfaceL2Tables(any())).thenReturn(future(new ClassifySetInterfaceL2TablesReply()));
+ when(aclCtx.getEntry(IF_INDEX, mappingContext)).thenReturn(Optional.of(
+ new MappingEntryBuilder()
+ .setIndex(IF_INDEX)
+ .setL2TableId(1)
+ .setIp4TableId(2)
+ .setIp6TableId(3)
+ .build()));
+
+ writer.deleteAcl(id, IF_INDEX, mappingContext);
+
+ verify(api).classifySetInterfaceL2Tables(classifySetInterfaceL2TablesRequest());
+ verify(api).classifyAddDelTable(classifyAddDelTable(1));
+ verify(api).classifyAddDelTable(classifyAddDelTable(2));
+ verify(api).classifyAddDelTable(classifyAddDelTable(3));
+ verify(aclCtx).removeEntry(IF_INDEX, mappingContext);
+ }
+
+ @Test
+ public void testWrite() throws Exception {
+ when(api.classifyAddDelTable(any())).thenReturn(future(new ClassifyAddDelTableReply()));
+ when(api.classifyAddDelSession(any())).thenReturn(future(new ClassifyAddDelSessionReply()));
+ when(api.classifySetInterfaceL2Tables(any())).thenReturn(future(new ClassifySetInterfaceL2TablesReply()));
+
+ final Egress
+ acl = new EgressBuilder().setAccessLists(
+ new AccessListsBuilder().setAcl(
+ Collections.singletonList(new AclBuilder()
+ .setName(ACL_NAME)
+ .setType(ACL_TYPE)
+ .build())
+ ).setMode(InterfaceMode.L2).build()
+ ).build();
+
+ final AccessLists accessLists = acl.getAccessLists();
+
+ when(writeContext.readAfter(any())).thenReturn(Optional.of(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclBuilder()
+ .setAccessListEntries(
+ new AccessListEntriesBuilder().setAce(Collections.singletonList(new AceBuilder()
+ .setMatches(new MatchesBuilder().setAceType(
+ new AceIpBuilder()
+ .setAceIpVersion(new AceIpv4Builder().build())
+ .setProtocol((short) 1)
+ .build()
+ ).build())
+ .setActions(new ActionsBuilder().setPacketHandling(new PermitBuilder().build()).build())
+ .build())).build()
+ ).build()
+
+ ));
+
+ writer.write(id, IF_INDEX, accessLists.getAcl(), accessLists.getDefaultAction(), accessLists.getMode(),
+ writeContext, mappingContext);
+
+ final ClassifySetInterfaceL2Tables request = new ClassifySetInterfaceL2Tables();
+ request.isInput = 0;
+ request.swIfIndex = IF_INDEX;
+ request.otherTableIndex = -1;
+ request.ip4TableIndex = 0;
+ request.ip6TableIndex = -1;
+ verify(api).classifySetInterfaceL2Tables(request);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/IetfAclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/IetfAclCustomizerTest.java
new file mode 100644
index 000000000..07e6518e5
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/IetfAclCustomizerTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.interfaces.acl.egress;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import io.fd.hc2vpp.v3po.interfaces.acl.common.IetfAclWriter;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import java.util.Collections;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.IetfAcl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.ietf.acl.Egress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.ietf.acl.EgressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.InterfaceMode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.MixedAcl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.AccessLists;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.AccessListsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.access.lists.AclBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IetfAclCustomizerTest extends WriterCustomizerTest {
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+ private static final InstanceIdentifier<Egress> IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)).augmentation(
+ VppInterfaceAugmentation.class).child(IetfAcl.class).child(Egress.class);
+ private static final String ACL_NAME = "acl1";
+ private static final Class<? extends AclBase> ACL_TYPE = MixedAcl.class;
+
+ @Mock
+ private IetfAclWriter aclWriter;
+ private IetfAclCustomizer customizer;
+
+ @Override
+ protected void setUp() {
+ customizer = new IetfAclCustomizer(aclWriter, new NamingContext("prefix", IFC_TEST_INSTANCE));
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_TEST_INSTANCE);
+ }
+
+ private static Egress acl(final InterfaceMode mode) {
+ return new EgressBuilder().setAccessLists(
+ new AccessListsBuilder().setAcl(
+ Collections.singletonList(new AclBuilder()
+ .setName(ACL_NAME)
+ .setType(ACL_TYPE)
+ .build())
+ ).setMode(mode)
+ .build()
+ ).build();
+ }
+
+ private void verifyWrite(final AccessLists accessLists) throws WriteFailedException {
+ verify(aclWriter)
+ .write(IID, IF_INDEX, accessLists.getAcl(), accessLists.getDefaultAction(), accessLists.getMode(),
+ writeContext, mappingContext);
+ }
+
+ private void verifyDelete() throws WriteFailedException {
+ verify(aclWriter).deleteAcl(IID, IF_INDEX, mappingContext);
+ }
+
+ @Test
+ public void testWriteL3() throws Exception {
+ customizer.writeCurrentAttributes(IID, acl(InterfaceMode.L3), writeContext);
+ verifyZeroInteractions(aclWriter);
+ }
+
+ @Test
+ public void testWriteL2() throws Exception {
+ final Egress acl = acl(InterfaceMode.L2);
+ customizer.writeCurrentAttributes(IID, acl, writeContext);
+ verifyWrite(acl.getAccessLists());
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ final Egress aclBefore = acl(InterfaceMode.L3);
+ final Egress aclAfter = acl(InterfaceMode.L2);
+ customizer.updateCurrentAttributes(IID, aclBefore, aclAfter, writeContext);
+ verifyDelete();
+ verifyWrite(aclAfter.getAccessLists());
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ final Egress acl = acl(InterfaceMode.L2);
+ customizer.deleteCurrentAttributes(IID, acl, writeContext);
+ verifyDelete();
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/SubInterfaceIetfAclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/SubInterfaceIetfAclCustomizerTest.java
new file mode 100644
index 000000000..24c57a1d5
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/egress/SubInterfaceIetfAclCustomizerTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.interfaces.acl.egress;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.v3po.interfaces.acl.common.IetfAclWriter;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import java.util.Collections;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.InterfaceMode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.MixedAcl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.AccessLists;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.AccessListsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.access.lists.AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.IetfAcl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.ietf.acl.Egress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.ietf.acl.EgressBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceIetfAclCustomizerTest extends WriterCustomizerTest {
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+ private static final String SUBIF_NAME = "local0.0";
+ private static final int SUBIF_INDEX = 11;
+ private static final long SUBIF_ID = 0;
+ private static final InstanceIdentifier<Egress> 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(IetfAcl.class).child(Egress.class);
+ private static final String ACL_NAME = "acl1";
+ private static final Class<? extends AclBase> ACL_TYPE = MixedAcl.class;
+
+ @Mock
+ private IetfAclWriter aclWriter;
+ private SubInterfaceIetfAclCustomizer customizer;
+
+ @Override
+ protected void setUp() {
+ customizer = new SubInterfaceIetfAclCustomizer(aclWriter, new NamingContext("prefix", IFC_TEST_INSTANCE));
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_TEST_INSTANCE);
+ defineMapping(mappingContext, SUBIF_NAME, SUBIF_INDEX, IFC_TEST_INSTANCE);
+
+
+ when(writeContext.readAfter(IID.firstIdentifierOf(SubInterface.class))).thenReturn(Optional.of(
+ new SubInterfaceBuilder().build()
+ ));
+ }
+
+ private static Egress acl(final InterfaceMode mode) {
+ return new EgressBuilder().setAccessLists(
+ new AccessListsBuilder().setAcl(
+ Collections.singletonList(new AclBuilder()
+ .setName(ACL_NAME)
+ .setType(ACL_TYPE)
+ .build())
+ ).setMode(mode)
+ .build()
+ ).build();
+ }
+
+ private void verifyWrite(final AccessLists accessLists) throws WriteFailedException {
+ verify(aclWriter)
+ .write(IID, SUBIF_INDEX, accessLists.getAcl(), accessLists.getDefaultAction(), accessLists.getMode(),
+ writeContext, 0, mappingContext);
+ }
+
+ private void verifyDelete() throws WriteFailedException {
+ verify(aclWriter).deleteAcl(IID, SUBIF_INDEX, mappingContext);
+ }
+
+ @Test
+ public void testWriteL3() throws Exception {
+ customizer.writeCurrentAttributes(IID, acl(InterfaceMode.L3), writeContext);
+ verifyZeroInteractions(aclWriter);
+ }
+
+ @Test
+ public void testWriteL2() throws Exception {
+ final Egress acl = acl(InterfaceMode.L2);
+ customizer.writeCurrentAttributes(IID, acl, writeContext);
+ verifyWrite(acl.getAccessLists());
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ final Egress aclBefore = acl(InterfaceMode.L3);
+ final Egress aclAfter = acl(InterfaceMode.L2);
+ customizer.updateCurrentAttributes(IID, aclBefore, aclAfter, writeContext);
+ verifyDelete();
+ verifyWrite(aclAfter.getAccessLists());
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ final Egress acl = acl(InterfaceMode.L2);
+ customizer.deleteCurrentAttributes(IID, acl, writeContext);
+ verifyDelete();
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/IetfAclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/IetfAclCustomizerTest.java
new file mode 100644
index 000000000..9b7267d52
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/IetfAclCustomizerTest.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.interfaces.acl.ingress;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.v3po.interfaces.acl.common.AclTableContextManager;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSessionReply;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterface;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterfaceReply;
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.EthAcl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.AccessListEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.AceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.ActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.MatchesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.Deny;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.DenyBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.Permit;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.PermitBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv6Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.IetfAcl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.ietf.acl.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.ietf.acl.IngressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.context.rev161214.mapping.entry.context.attributes.acl.mapping.entry.context.mapping.table.MappingEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.AccessListsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.access.lists.AclBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IetfAclCustomizerTest extends WriterCustomizerTest {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+ private static final InstanceIdentifier<Ingress> IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)).augmentation(
+ VppInterfaceAugmentation.class).child(IetfAcl.class).child(Ingress.class);
+ private static final String ACL_NAME = "acl1";
+ private static final Class<? extends AclBase> ACL_TYPE = EthAcl.class;
+
+ @Mock
+ private AclTableContextManager aclCtx;
+
+ private IetfAclCustomizer customizer;
+ private Ingress acl;
+ private int DENY = 0;
+ private int PERMIT = -1;
+
+ @Override
+ protected void setUp() {
+ customizer = new IetfAclCustomizer(new IngressIetfAclWriter(api, aclCtx), new NamingContext("prefix", IFC_TEST_INSTANCE));
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_TEST_INSTANCE);
+ acl = new IngressBuilder().setAccessLists(
+ new AccessListsBuilder().setAcl(
+ Collections.singletonList(new AclBuilder()
+ .setName(ACL_NAME)
+ .setType(ACL_TYPE)
+ .build())
+ ).build()
+ ).build();
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ when(api.classifyAddDelTable(any())).thenReturn(future(new ClassifyAddDelTableReply()));
+ when(api.classifyAddDelSession(any())).thenReturn(future(new ClassifyAddDelSessionReply()));
+
+ when(writeContext.readAfter(any())).thenReturn(Optional.of(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclBuilder()
+ .setAccessListEntries(
+ new AccessListEntriesBuilder().setAce(Arrays.asList(ace(permit()), ace(permit()), ace(deny())
+ )).build()
+ ).build()
+
+ ));
+ when(api.inputAclSetInterface(any())).thenReturn(future(new InputAclSetInterfaceReply()));
+
+ customizer.writeCurrentAttributes(IID, acl, writeContext);
+
+ final InOrder inOrder = Mockito.inOrder(api);
+ inOrder.verify(api).classifyAddDelTable(argThat(actionOnMissEquals(DENY))); // default action
+ inOrder.verify(api).classifyAddDelTable(any());
+ inOrder.verify(api).classifyAddDelSession(argThat(actionOnHitEquals(DENY))); // last deny ACE
+ inOrder.verify(api).classifyAddDelTable(any());
+ inOrder.verify(api).classifyAddDelSession(argThat(actionOnHitEquals(PERMIT)));
+ inOrder.verify(api).classifyAddDelTable(any());
+ inOrder.verify(api).classifyAddDelSession(argThat(actionOnHitEquals(PERMIT)));
+ inOrder.verify(api).inputAclSetInterface(inputAclSetInterfaceWriteRequest()); // assignment
+ }
+
+ private ArgumentMatcher<ClassifyAddDelTable> actionOnMissEquals(final int action) {
+ return table -> table.missNextIndex == action;
+ }
+
+
+ private ArgumentMatcher<ClassifyAddDelSession> actionOnHitEquals(final int action) {
+ return session -> session.hitNextIndex == action;
+ }
+
+ private Deny deny() {
+ return new DenyBuilder().build();
+ }
+
+ private Permit permit() {
+ return new PermitBuilder().build();
+ }
+
+ private static Ace ace(final PacketHandling action) {
+ return new AceBuilder()
+ .setMatches(new MatchesBuilder().setAceType(
+ new AceIpBuilder()
+ .setAceIpVersion(new AceIpv6Builder().build())
+ .setProtocol((short) 1)
+ .build()
+ ).build())
+ .setActions(new ActionsBuilder().setPacketHandling(action).build())
+ .build();
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ when(api.inputAclSetInterface(any())).thenReturn(future(new InputAclSetInterfaceReply()));
+ when(api.classifyAddDelTable(any())).thenReturn(future(new ClassifyAddDelTableReply()));
+ when(aclCtx.getEntry(IF_INDEX, mappingContext)).thenReturn(Optional.of(
+ new MappingEntryBuilder()
+ .setIndex(IF_INDEX)
+ .setL2TableId(1)
+ .setIp4TableId(2)
+ .setIp6TableId(3)
+ .build()));
+
+ customizer.deleteCurrentAttributes(IID, acl, writeContext);
+
+ final ClassifyTableByInterface expectedRequest = new ClassifyTableByInterface();
+ expectedRequest.swIfIndex = IF_INDEX;
+ verify(api).inputAclSetInterface(inputAclSetInterfaceDeleteRequest());
+ verify(api).classifyAddDelTable(classifyAddDelTable(1));
+ verify(api).classifyAddDelTable(classifyAddDelTable(2));
+ verify(api).classifyAddDelTable(classifyAddDelTable(3));
+ }
+
+ private static InputAclSetInterface inputAclSetInterfaceDeleteRequest() {
+ final InputAclSetInterface request = new InputAclSetInterface();
+ request.swIfIndex = IF_INDEX;
+ request.l2TableIndex = 1;
+ request.ip4TableIndex = 2;
+ request.ip6TableIndex = 3;
+ return request;
+ }
+
+ private static ClassifyAddDelTable classifyAddDelTable(final int tableIndex) {
+ final ClassifyAddDelTable reply = new ClassifyAddDelTable();
+ reply.tableIndex = tableIndex;
+ return reply;
+ }
+
+ private static InputAclSetInterface inputAclSetInterfaceWriteRequest() {
+ final InputAclSetInterface request = new InputAclSetInterface();
+ request.swIfIndex = IF_INDEX;
+ request.isAdd = 1;
+ request.l2TableIndex = -1;
+ request.ip4TableIndex = -1;
+ request.ip6TableIndex = 0;
+ return request;
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/SubInterfaceAclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/SubInterfaceAclCustomizerTest.java
new file mode 100644
index 000000000..8b088883f
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/SubInterfaceAclCustomizerTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.interfaces.acl.ingress;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterfaceReply;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.base.attributes.Ip4Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.base.attributes.Ip4AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.base.attributes.Ip6Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.base.attributes.Ip6AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.acl.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.acl.IngressBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceAclCustomizerTest extends WriterCustomizerTest {
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+ private static final String SUBIF_NAME = "local0.0";
+ private static final int SUBIF_INDEX = 11;
+ private static final long SUBIF_ID = 0;
+ private static final String TABLE_NAME = "table0";
+ private static final int TABLE_INDEX = 123;
+
+ private static final InstanceIdentifier<Ingress> IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)).augmentation(
+ SubinterfaceAugmentation.class).child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey(SUBIF_ID)).child(Acl.class).child(Ingress.class);
+
+ @Mock
+ private VppClassifierContextManager classifyTableContext;
+
+ private SubInterfaceAclCustomizer customizer;
+
+ @Override
+ protected void setUp() throws Exception {
+ customizer = new SubInterfaceAclCustomizer(api, new NamingContext("prefix", IFC_TEST_INSTANCE),
+ classifyTableContext);
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_TEST_INSTANCE);
+ defineMapping(mappingContext, SUBIF_NAME, SUBIF_INDEX, IFC_TEST_INSTANCE);
+ when(classifyTableContext.getTableIndex(TABLE_NAME, mappingContext)).thenReturn(TABLE_INDEX);
+ }
+
+ @Test
+ public void testCreate() throws WriteFailedException {
+ when(api.inputAclSetInterface(any())).thenReturn(future(new InputAclSetInterfaceReply()));
+ customizer.writeCurrentAttributes(IID, ip4Acl(), writeContext);
+ verify(api).inputAclSetInterface(expectedIp4AclRequest());
+ }
+
+ @Test(expected = WriteFailedException.class)
+ public void testCreateFailed() throws WriteFailedException {
+ when(api.inputAclSetInterface(any())).thenReturn(failedFuture());
+ customizer.writeCurrentAttributes(IID, ip4Acl(), writeContext);
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testUpdate() throws WriteFailedException {
+ customizer.updateCurrentAttributes(IID, ip4Acl(), ip6Acl(), writeContext);
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ when(api.inputAclSetInterface(any())).thenReturn(future(new InputAclSetInterfaceReply()));
+ customizer.deleteCurrentAttributes(IID, ip6Acl(), writeContext);
+ verify(api).inputAclSetInterface(expectedIp6AclRequest());
+ }
+
+ @Test(expected = WriteFailedException.class)
+ public void testDeleteFailed() throws WriteFailedException {
+ when(api.inputAclSetInterface(any())).thenReturn(failedFuture());
+ customizer.deleteCurrentAttributes(IID, ip4Acl(), writeContext);
+ }
+
+ private Ingress ip4Acl() {
+ final IngressBuilder builder = new IngressBuilder();
+ final Ip4Acl acl = new Ip4AclBuilder().setClassifyTable(TABLE_NAME).build();
+ builder.setIp4Acl(acl);
+ return builder.build();
+ }
+
+ private InputAclSetInterface expectedIp4AclRequest() {
+ final InputAclSetInterface request = new InputAclSetInterface();
+ request.isAdd = 1;
+ request.l2TableIndex = -1;
+ request.ip4TableIndex = TABLE_INDEX;
+ request.ip6TableIndex = -1;
+ request.swIfIndex = SUBIF_INDEX;
+ return request;
+ }
+
+ private Ingress ip6Acl() {
+ final IngressBuilder builder = new IngressBuilder();
+ final Ip6Acl acl = new Ip6AclBuilder().setClassifyTable(TABLE_NAME).build();
+ builder.setIp6Acl(acl);
+ return builder.build();
+ }
+
+ private InputAclSetInterface expectedIp6AclRequest() {
+ final InputAclSetInterface request = new InputAclSetInterface();
+ request.isAdd = 0;
+ request.l2TableIndex = -1;
+ request.ip4TableIndex = -1;
+ request.ip6TableIndex = TABLE_INDEX;
+ request.swIfIndex = SUBIF_INDEX;
+ return request;
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/SubInterfaceIetfAclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/SubInterfaceIetfAclCustomizerTest.java
new file mode 100644
index 000000000..e3c1d86f9
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/acl/ingress/SubInterfaceIetfAclCustomizerTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.interfaces.acl.ingress;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.v3po.interfaces.acl.IetfAclWriter;
+import io.fd.hc2vpp.v3po.interfaces.acl.common.AclTableContextManager;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterface;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterfaceReply;
+import java.util.Collections;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.EthAcl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.AccessListEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.context.rev161214.mapping.entry.context.attributes.acl.mapping.entry.context.mapping.table.MappingEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.AccessListsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.ietf.acl.base.attributes.access.lists.AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.IetfAcl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.ietf.acl.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.ietf.acl.IngressBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceIetfAclCustomizerTest extends WriterCustomizerTest {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+ private static final String SUBIF_NAME = "local0.123";
+ private static final int SUBIF_INDEX = 2;
+ private static final long SUB_IF_ID = 123;
+ private static final InstanceIdentifier<Ingress> IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)).augmentation(
+ SubinterfaceAugmentation.class).child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey(SUB_IF_ID)).child(IetfAcl.class).child(Ingress.class);
+ private static final String ACL_NAME = "acl1";
+ private static final Class<? extends AclBase> ACL_TYPE = EthAcl.class;
+
+ private SubInterfaceIetfAclCustomizer customizer;
+ private Ingress acl;
+
+ @Mock
+ private AclTableContextManager aclCtx;
+
+ @Override
+ protected void setUp() {
+ customizer =
+ new SubInterfaceIetfAclCustomizer(new IngressIetfAclWriter(api, aclCtx), new NamingContext("prefix", IFC_TEST_INSTANCE));
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_TEST_INSTANCE);
+
+ acl = new IngressBuilder().setAccessLists(
+ new AccessListsBuilder().setAcl(
+ Collections.singletonList(new AclBuilder()
+ .setName(ACL_NAME)
+ .setType(ACL_TYPE)
+ .build())
+ ).build()
+ ).build();
+ }
+
+ private static InputAclSetInterface inputAclSetInterfaceWriteRequest() {
+ final InputAclSetInterface request = new InputAclSetInterface();
+ request.swIfIndex = SUBIF_INDEX;
+ request.isAdd = 1;
+ request.l2TableIndex = -1;
+ request.ip4TableIndex = -1;
+ request.ip6TableIndex = -1;
+ return request;
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_TEST_INSTANCE);
+ defineMapping(mappingContext, SUBIF_NAME, SUBIF_INDEX, IFC_TEST_INSTANCE);
+ when(api.inputAclSetInterface(any())).thenReturn(future(new InputAclSetInterfaceReply()));
+ when(aclCtx.getEntry(SUBIF_INDEX, mappingContext)).thenReturn(Optional.of(
+ new MappingEntryBuilder()
+ .setIndex(SUBIF_INDEX)
+ .setL2TableId(-1)
+ .setIp4TableId(-1)
+ .setIp6TableId(-1)
+ .build()));
+
+ customizer.deleteCurrentAttributes(IID, acl, writeContext);
+
+ final ClassifyTableByInterface expectedRequest = new ClassifyTableByInterface();
+ expectedRequest.swIfIndex = SUBIF_INDEX;
+ verify(api).inputAclSetInterface(inputAclSetInterfaceDeleteRequest());
+ }
+
+ private static InputAclSetInterface inputAclSetInterfaceDeleteRequest() {
+ final InputAclSetInterface request = new InputAclSetInterface();
+ request.swIfIndex = SUBIF_INDEX;
+ request.l2TableIndex = -1;
+ request.ip4TableIndex = -1;
+ request.ip6TableIndex = -1;
+ return request;
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_TEST_INSTANCE);
+ defineMapping(mappingContext, SUBIF_NAME, SUBIF_INDEX, IFC_TEST_INSTANCE);
+
+ when(writeContext.readAfter(IID.firstIdentifierOf(SubInterface.class))).thenReturn(Optional.of(
+ new SubInterfaceBuilder().build()
+ ));
+
+ when(writeContext.readAfter(IetfAclWriter.ACL_ID.child(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl.class,
+ new AclKey(ACL_NAME, ACL_TYPE)))).thenReturn(Optional.of(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclBuilder()
+ .setAccessListEntries(
+ new AccessListEntriesBuilder().setAce(Collections.emptyList()).build()
+ ).build()
+ ));
+
+ when(api.inputAclSetInterface(any())).thenReturn(future(new InputAclSetInterfaceReply()));
+
+ customizer.writeCurrentAttributes(IID, acl, writeContext);
+
+ verify(api).inputAclSetInterface(inputAclSetInterfaceWriteRequest());
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/Ipv4AddressCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/Ipv4AddressCustomizerTest.java
new file mode 100644
index 000000000..6659e79b6
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/Ipv4AddressCustomizerTest.java
@@ -0,0 +1,338 @@
+/*
+ * 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.interfaces.ip;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.v3po.interfaces.ip.subnet.validation.SubnetValidationException;
+import io.fd.hc2vpp.v3po.interfaces.ip.subnet.validation.SubnetValidator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.Netmask;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.NetmaskBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.PrefixLength;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.PrefixLengthBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.IpAddressDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceAddDelAddress;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceAddDelAddressReply;
+
+public class Ipv4AddressCustomizerTest extends WriterCustomizerTest {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IFACE_NAME = "eth0";
+ private static final int IFACE_ID = 123;
+
+ @Mock
+ private SubnetValidator subnetValidator;
+
+ private NamingContext interfaceContext;
+ private Ipv4AddressCustomizer customizer;
+
+ @Before
+ public void setUp() throws Exception {
+ interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+
+ customizer = new Ipv4AddressCustomizer(api, interfaceContext, subnetValidator);
+
+ doReturn(future(new IpAddressDetailsReplyDump())).when(api).ipAddressDump(any());
+ when(writeContext.readAfter(Mockito.any()))
+ .thenReturn(Optional.of(new Ipv4Builder().setAddress(Collections.emptyList()).build()));
+ }
+
+ private static InstanceIdentifier<Address> getAddressId(final String ifaceName) {
+ return InstanceIdentifier.builder(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(ifaceName))
+ .augmentation(Interface1.class)
+ .child(Ipv4.class)
+ .child(Address.class)
+ .build();
+ }
+
+ private void whenSwInterfaceAddDelAddressThenSuccess() {
+ doReturn(future(new SwInterfaceAddDelAddressReply())).when(api).swInterfaceAddDelAddress(any(SwInterfaceAddDelAddress.class));
+ }
+
+ private void whenSwInterfaceAddDelAddressThenFailure() {
+ doReturn(failedFuture()).when(api).swInterfaceAddDelAddress(any(SwInterfaceAddDelAddress.class));
+ }
+
+ @Test
+ public void testAddPrefixLengthIpv4Address() throws Exception {
+ doNothing().when(subnetValidator).checkNotAddingToSameSubnet(Mockito.anyList());
+
+ final InstanceIdentifier<Address> id = getAddressId(IFACE_NAME);
+ when(writeContext.readBefore(id)).thenReturn(Optional.absent());
+
+ Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"));
+ PrefixLength length = new PrefixLengthBuilder().setPrefixLength(new Integer(24).shortValue()).build();
+ Address data = new AddressBuilder().setIp(noZoneIp).setSubnet(length).build();
+
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+ whenSwInterfaceAddDelAddressThenSuccess();
+
+ customizer.writeCurrentAttributes(id, data, writeContext);
+
+ verify(api).swInterfaceAddDelAddress(generateSwInterfaceAddDelAddressRequest(new byte[]{-64, -88, 2, 1},
+ (byte) 1, (byte) 24));
+ }
+
+ @Test
+ public void testAddPrefixLengthIpv4AddressFailed() throws Exception {
+ final InstanceIdentifier<Address> id = getAddressId(IFACE_NAME);
+ when(writeContext.readBefore(id)).thenReturn(Optional.absent());
+
+ Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"));
+ PrefixLength length = new PrefixLengthBuilder().setPrefixLength(new Integer(24).shortValue()).build();
+ Address data = new AddressBuilder().setIp(noZoneIp).setSubnet(length).build();
+
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+ whenSwInterfaceAddDelAddressThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(id, data, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).swInterfaceAddDelAddress(
+ generateSwInterfaceAddDelAddressRequest(new byte[]{-64, -88, 2, 1},
+ (byte) 1, (byte) 24));
+ return;
+ }
+ fail("WriteFailedException was expected");
+ }
+
+ @Test
+ public void testAddPrefixLengthIpv4AddressConflicted() throws Exception {
+
+ final InstanceIdentifier<Address> id = getAddressId(IFACE_NAME);
+ when(writeContext.readBefore(id)).thenReturn(Optional.absent());
+
+ Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"));
+ PrefixLength length = new PrefixLengthBuilder().setPrefixLength(new Integer(24).shortValue()).build();
+ Address data = new AddressBuilder().setIp(noZoneIp).setSubnet(length).build();
+ final List<Address> addressList = Arrays.asList(data);
+
+ //throws when validation invoked
+ Mockito.doThrow(SubnetValidationException.forConflictingData((short) 24, Arrays.asList(data))).when(subnetValidator)
+ .checkNotAddingToSameSubnet(addressList);
+
+ //fake data return from WriteContext
+ doReturn(Optional.of(new Ipv4Builder().setAddress(addressList).build())).when(writeContext)
+ .readAfter(argThat(matchInstanceIdentifier(Ipv4.class)));
+
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+
+ try {
+ customizer.writeCurrentAttributes(id, data, writeContext);
+ } catch (WriteFailedException e) {
+ //verifies if cause of exception is correct type
+ assertTrue(e.getCause() instanceof SubnetValidationException);
+
+ //verify that validation call was invoked with data from writeContext
+ verify(subnetValidator, times(1)).checkNotAddingToSameSubnet(addressList);
+ }
+
+ }
+
+ private static ArgumentMatcher<InstanceIdentifier<?>> matchInstanceIdentifier(
+ Class<?> desiredClass) {
+ return o -> o instanceof InstanceIdentifier && (o.getTargetType().equals(desiredClass));
+ }
+
+ @Test(expected = WriteFailedException.UpdateFailedException.class)
+ public void testUpdate() throws Exception {
+ final Address data = mock(Address.class);
+ customizer.updateCurrentAttributes(getAddressId(IFACE_NAME), data, data, writeContext);
+ }
+
+ private SwInterfaceAddDelAddress generateSwInterfaceAddDelAddressRequest(final byte[] address, final byte isAdd,
+ final byte prefixLength) {
+ final SwInterfaceAddDelAddress request = new SwInterfaceAddDelAddress();
+ request.swIfIndex = IFACE_ID;
+ request.isAdd = isAdd;
+ request.isIpv6 = 0;
+ request.delAll = 0;
+ request.addressLength = prefixLength;
+ request.address = address;
+ return request;
+ }
+
+ @Test
+ public void testDeletePrefixLengthIpv4Address() throws Exception {
+ final InstanceIdentifier<Address> id = getAddressId(IFACE_NAME);
+
+ Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"));
+ PrefixLength length = new PrefixLengthBuilder().setPrefixLength(new Integer(24).shortValue()).build();
+ Address data = new AddressBuilder().setIp(noZoneIp).setSubnet(length).build();
+
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+ whenSwInterfaceAddDelAddressThenSuccess();
+
+ customizer.deleteCurrentAttributes(id, data, writeContext);
+
+ verify(api).swInterfaceAddDelAddress(generateSwInterfaceAddDelAddressRequest(new byte[]{-64, -88, 2, 1},
+ (byte) 0, (byte) 24));
+ }
+
+ @Test
+ public void testDeletePrefixLengthIpv4AddressFailed() throws Exception {
+ final InstanceIdentifier<Address> id = getAddressId(IFACE_NAME);
+
+ Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"));
+ PrefixLength length = new PrefixLengthBuilder().setPrefixLength(new Integer(24).shortValue()).build();
+ Address data = new AddressBuilder().setIp(noZoneIp).setSubnet(length).build();
+
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+ whenSwInterfaceAddDelAddressThenFailure();
+
+ try {
+ customizer.deleteCurrentAttributes(id, data, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).swInterfaceAddDelAddress(
+ generateSwInterfaceAddDelAddressRequest(new byte[]{-64, -88, 2, 1},
+ (byte) 0, (byte) 24));
+ return;
+ }
+ fail("WriteFailedException was expec16ted");
+ }
+
+ @Test
+ public void testNetmaskFailed() {
+ final int expectedPrefixLength = 1;
+ final String stringMask = "128.0.0.0";
+ final InstanceIdentifier<Address> id = getAddressId(IFACE_NAME);
+ when(writeContext.readBefore(id)).thenReturn(Optional.absent());
+
+ Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"));
+ Netmask subnet = new NetmaskBuilder().setNetmask(new DottedQuad(stringMask)).build();
+ Address data = new AddressBuilder().setIp(noZoneIp).setSubnet(subnet).build();
+
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+ whenSwInterfaceAddDelAddressThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(id, data, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).swInterfaceAddDelAddress(generateSwInterfaceAddDelAddressRequest(new byte[]{-64, -88, 2, 1},
+ (byte) 1, (byte) expectedPrefixLength));
+ return;
+ }
+ fail("WriteFailedException was expec16ted");
+
+ }
+
+ private void testSingleNetmask(final int expectedPrefixLength, final String stringMask) throws Exception {
+ final InstanceIdentifier<Address> id = getAddressId(IFACE_NAME);
+ when(writeContext.readBefore(id)).thenReturn(Optional.absent());
+
+ Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"));
+ Netmask subnet = new NetmaskBuilder().setNetmask(new DottedQuad(stringMask)).build();
+ Address data = new AddressBuilder().setIp(noZoneIp).setSubnet(subnet).build();
+
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+ whenSwInterfaceAddDelAddressThenSuccess();
+
+ customizer.writeCurrentAttributes(id, data, writeContext);
+
+ verify(api).swInterfaceAddDelAddress(generateSwInterfaceAddDelAddressRequest(new byte[]{-64, -88, 2, 1},
+ (byte) 1, (byte) expectedPrefixLength));
+ }
+
+ private void testSingleIllegalNetmask(final String stringMask) throws Exception {
+ try {
+ final InstanceIdentifier<Address> id = getAddressId(IFACE_NAME);
+ when(writeContext.readBefore(id)).thenReturn(Optional.absent());
+
+ Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"));
+ Netmask subnet = new NetmaskBuilder().setNetmask(new DottedQuad(stringMask)).build();
+ Address data = new AddressBuilder().setIp(noZoneIp).setSubnet(subnet).build();
+
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+ whenSwInterfaceAddDelAddressThenSuccess();
+
+ customizer.writeCurrentAttributes(id, data, writeContext);
+ } catch (IllegalArgumentException e) {
+ return;
+ }
+ fail("IllegalArgumentException expected");
+
+ }
+
+ /**
+ * Test contiguous netmask length from QuadDotted notation
+ */
+ @Test
+ public void testNetmaskLength() throws Exception {
+ testSingleNetmask(1, "128.0.0.0");
+ testSingleNetmask(2, "192.0.0.0");
+ testSingleNetmask(8, "255.0.0.0");
+ testSingleNetmask(9, "255.128.0.0");
+ testSingleNetmask(16, "255.255.0.0");
+ testSingleNetmask(24, "255.255.255.0");
+ }
+
+ @Test
+ public void testNetmaskIllegal() throws Exception {
+ testSingleIllegalNetmask("");
+ testSingleIllegalNetmask(".");
+ testSingleIllegalNetmask(".255");
+ testSingleIllegalNetmask("255");
+ testSingleIllegalNetmask("255.");
+ testSingleIllegalNetmask("255.255");
+ testSingleIllegalNetmask("255.255.0");
+ testSingleIllegalNetmask("255.255.255.");
+ testSingleIllegalNetmask("255.255.255.256");
+ testSingleIllegalNetmask("0.0.0.0");
+ testSingleIllegalNetmask("10.10.10.10");
+ testSingleIllegalNetmask("255.1.255.0");
+ testSingleIllegalNetmask("255.255.255.255");
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/Ipv4NeighbourCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/Ipv4NeighbourCustomizerTest.java
new file mode 100644
index 000000000..390561d80
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/Ipv4NeighbourCustomizerTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.interfaces.ip;
+
+import static junit.framework.TestCase.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.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Neighbor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.NeighborBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.IpNeighborAddDel;
+import io.fd.vpp.jvpp.core.dto.IpNeighborAddDelReply;
+
+public class Ipv4NeighbourCustomizerTest extends WriterCustomizerTest implements Ipv4Translator {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IFACE_NAME = "parent";
+ private static final int IFACE_ID = 5;
+ private static final InstanceIdentifier<Neighbor> IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(Interface1.class).child(Ipv4.class).child(Neighbor.class);
+
+ private Ipv4NeighbourCustomizer customizer;
+
+ @Override
+ public void setUp() {
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+ customizer = new Ipv4NeighbourCustomizer(api, new NamingContext("prefix", IFC_CTX_NAME));
+ }
+
+ @Test
+ public void testWriteCurrentAttributes() throws WriteFailedException {
+ when(api.ipNeighborAddDel(any())).thenReturn(future(new IpNeighborAddDelReply()));
+ customizer.writeCurrentAttributes(IID, getData(), writeContext);
+ verify(api).ipNeighborAddDel(getExpectedRequest(true));
+ }
+
+ @Test
+ public void testWriteCurrentAttributesFailed() {
+ when(api.ipNeighborAddDel(any())).thenReturn(failedFuture());
+ try {
+ customizer.writeCurrentAttributes(IID, getData(), writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).ipNeighborAddDel(getExpectedRequest(true));
+ return;
+ }
+ fail("WriteFailedException expected");
+ }
+ @Test(expected = UnsupportedOperationException.class)
+ public void testUpdateCurrentAttributes() throws WriteFailedException {
+ customizer.updateCurrentAttributes(IID, getData(), getData(), writeContext);
+ }
+
+ @Test
+ public void testDeleteCurrentAttributes() throws WriteFailedException {
+ when(api.ipNeighborAddDel(any())).thenReturn(future(new IpNeighborAddDelReply()));
+ customizer.deleteCurrentAttributes(IID, getData(), writeContext);
+ verify(api).ipNeighborAddDel(getExpectedRequest(false));
+ }
+
+ @Test
+ public void testDeleteCurrentAttributesFailed() {
+ when(api.ipNeighborAddDel(any())).thenReturn(failedFuture());
+ try {
+ customizer.deleteCurrentAttributes(IID, getData(), writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).ipNeighborAddDel(getExpectedRequest(false));
+ return;
+ }
+ fail("WriteFailedException expected");
+ }
+
+ private Neighbor getData() {
+ final Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"));
+ final PhysAddress mac = new PhysAddress("aa:bb:cc:ee:11:22");
+ return new NeighborBuilder().setIp(noZoneIp).setLinkLayerAddress(mac).build();
+ }
+ private IpNeighborAddDel getExpectedRequest(final boolean isAdd) {
+ final IpNeighborAddDel request = new IpNeighborAddDel();
+ request.isIpv6 = 0;
+ request.isAdd = booleanToByte(isAdd);
+ request.isStatic = 1;
+ request.dstAddress = new byte[] {(byte) 192, (byte) 168, 2, 1};
+ request.macAddress = new byte[] {(byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xee, 0x11, 0x22};
+ request.swIfIndex = IFACE_ID;
+ return request;
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/SubInterfaceIpv4AddressCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/SubInterfaceIpv4AddressCustomizerTest.java
new file mode 100644
index 000000000..be0869fa9
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/SubInterfaceIpv4AddressCustomizerTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.interfaces.ip;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.address.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.address.subnet.Netmask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.address.subnet.NetmaskBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.address.subnet.PrefixLength;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.address.subnet.PrefixLengthBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceAddDelAddress;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceAddDelAddressReply;
+
+public class SubInterfaceIpv4AddressCustomizerTest extends WriterCustomizerTest implements ByteDataTranslator {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IFACE_NAME = "eth0";
+ private static final int IFACE_INDEX = 0;
+ private static final String SUBIF_NAME = "eth0.1";
+ private static final long SUBIF_ID = 1;
+ private static final int SUBIF_INDEX = 123;
+ private static final InstanceIdentifier<Address> IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(SubinterfaceAugmentation.class).child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey(SUBIF_ID)).child(Ipv4.class).child(Address.class);
+
+ private SubInterfaceIpv4AddressCustomizer customizer;
+
+ @Override
+ protected void setUp() {
+ customizer = new SubInterfaceIpv4AddressCustomizer(api, new NamingContext("prefix", IFC_CTX_NAME));
+ defineMapping(mappingContext, IFACE_NAME, IFACE_INDEX, IFC_CTX_NAME);
+ defineMapping(mappingContext, SUBIF_NAME, SUBIF_INDEX, IFC_CTX_NAME);
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ when(api.swInterfaceAddDelAddress(any())).thenReturn(future(new SwInterfaceAddDelAddressReply()));
+ customizer.writeCurrentAttributes(IID, address(prefixLength()), writeContext);
+ verify(api).swInterfaceAddDelAddress(expectedRequest(true));
+ }
+
+ @Test
+ public void testWriteFailed() {
+ when(api.swInterfaceAddDelAddress(any())).thenReturn(failedFuture());
+ try {
+ customizer.writeCurrentAttributes(IID, address(prefixLength()), writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).swInterfaceAddDelAddress(expectedRequest(true));
+ return;
+ }
+ fail("WriteFailedException expected");
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ when(api.swInterfaceAddDelAddress(any())).thenReturn(future(new SwInterfaceAddDelAddressReply()));
+ customizer.deleteCurrentAttributes(IID, address(netmask()), writeContext);
+ verify(api).swInterfaceAddDelAddress(expectedRequest(false));
+ }
+
+ @Test
+ public void testDeleteFailed() {
+ when(api.swInterfaceAddDelAddress(any())).thenReturn(failedFuture());
+ try {
+ customizer.deleteCurrentAttributes(IID, address(netmask()), writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).swInterfaceAddDelAddress(expectedRequest(false));
+ return;
+ }
+ fail("WriteFailedException expected");
+ }
+
+ private SwInterfaceAddDelAddress expectedRequest(boolean isAdd) {
+ final SwInterfaceAddDelAddress request = new SwInterfaceAddDelAddress();
+ request.isAdd = booleanToByte(isAdd);
+ request.swIfIndex = SUBIF_INDEX;
+ request.isIpv6 = 0;
+ request.delAll = 0;
+ request.addressLength = 24;
+ request.address = new byte[] {(byte) 192, (byte) 168, 2, 1};
+ return request;
+ }
+
+ @Test(expected = WriteFailedException.UpdateFailedException.class)
+ public void testUpdate() throws Exception {
+ final Address address = address(prefixLength());
+ customizer.updateCurrentAttributes(IID, address, address, writeContext);
+ }
+
+ private Address address(final Subnet subnet) {
+ final Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"));
+ return new AddressBuilder().setIp(noZoneIp).setSubnet(subnet).build();
+ }
+
+ private PrefixLength prefixLength() {
+ return new PrefixLengthBuilder().setPrefixLength(new Integer(24).shortValue()).build();
+ }
+
+ private Netmask netmask() {
+ return new NetmaskBuilder().setNetmask(new DottedQuad("255.255.255.0")).build();
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/subnet/validation/SubnetValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/subnet/validation/SubnetValidatorTest.java
new file mode 100644
index 000000000..0c1e878a8
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/ip/subnet/validation/SubnetValidatorTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.interfaces.ip.subnet.validation;
+
+
+import com.google.common.collect.Lists;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.NetmaskBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.PrefixLengthBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
+
+public class SubnetValidatorTest {
+
+ private SubnetValidator subnetValidator;
+
+ @Before
+ public void init() {
+ subnetValidator = new SubnetValidator();
+ }
+
+ @Test(expected = SubnetValidationException.class)
+ public void testValidateNegativeSameTypes() throws SubnetValidationException {
+ List<Address> addresses = Lists.newArrayList();
+
+ addresses.add(new AddressBuilder().setSubnet(new PrefixLengthBuilder().setPrefixLength((short) 24).build())
+ .build());
+ addresses.add(new AddressBuilder().setSubnet(new PrefixLengthBuilder().setPrefixLength((short) 24).build())
+ .build());
+
+ subnetValidator.checkNotAddingToSameSubnet(addresses);
+ }
+
+ @Test(expected = SubnetValidationException.class)
+ public void testValidateNegativeMixedTypes() throws SubnetValidationException {
+ List<Address> addresses = Lists.newArrayList();
+
+ addresses.add(new AddressBuilder().setSubnet(new PrefixLengthBuilder().setPrefixLength((short) 24).build())
+ .build());
+ addresses.add(new AddressBuilder()
+ .setSubnet(new NetmaskBuilder().setNetmask(new DottedQuad("255.255.255.0")).build())
+ .build());
+
+ subnetValidator.checkNotAddingToSameSubnet(addresses);
+ }
+
+ @Test
+ public void testValidatePositiveSameTypes() throws SubnetValidationException {
+ List<Address> addresses = Lists.newArrayList();
+
+ addresses.add(new AddressBuilder().setSubnet(new PrefixLengthBuilder().setPrefixLength((short) 24).build())
+ .build());
+ addresses.add(new AddressBuilder().setSubnet(new PrefixLengthBuilder().setPrefixLength((short) 25).build())
+ .build());
+
+ subnetValidator.checkNotAddingToSameSubnet(addresses);
+ }
+
+ @Test
+ public void testValidatePositiveMixedTypes() throws SubnetValidationException {
+ List<Address> addresses = Lists.newArrayList();
+
+ addresses.add(new AddressBuilder().setSubnet(new PrefixLengthBuilder().setPrefixLength((short) 24).build())
+ .build());
+ addresses.add(new AddressBuilder()
+ .setSubnet(new NetmaskBuilder().setNetmask(new DottedQuad("255.255.0.0")).build())
+ .build());
+
+ subnetValidator.checkNotAddingToSameSubnet(addresses);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteCustomizerTest.java
new file mode 100644
index 000000000..fa68e61b6
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteCustomizerTest.java
@@ -0,0 +1,312 @@
+/*
+ * 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.interfaces.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.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.VppCallbackException;
+import io.fd.vpp.jvpp.core.dto.L2InterfacePbbTagRewrite;
+import io.fd.vpp.jvpp.core.dto.L2InterfacePbbTagRewriteReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pbb.types.rev161214.Operation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev161214.PbbRewriteInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewrite;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewriteBuilder;
+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 setUp() 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, validData(), writeContext);
+ verifyRewriteRequest(desiredSetResult());
+ }
+
+ @Test
+ public void testWriteFailedCallFailed() {
+ whenRewriteThenFail();
+ final PbbRewrite validData = 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 testWriteFailedInvalidData() {
+ verifyInvalidWriteDataCombination(invalidDataNoDestination());
+ verifyInvalidWriteDataCombination(invalidDataNoSource());
+ verifyInvalidWriteDataCombination(invalidDataNoItag());
+ verifyInvalidWriteDataCombination(invalidDataNoOperation());
+ verifyInvalidWriteDataCombination(invalidDataNoVlan());
+ }
+
+ @Test
+ public void testUpdate() throws WriteFailedException {
+ whenRewriteThenSuccess();
+ final PbbRewrite rewrite = validData();
+ customizer.updateCurrentAttributes(validId, rewrite, rewrite, writeContext);
+ verifyRewriteRequest(desiredSetResult());
+ }
+
+ @Test
+ public void testUpdateFailedCallFailed() {
+ whenRewriteThenFail();
+ final PbbRewrite invalidData = invalidDataNoVlan();
+ final PbbRewrite validData = 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 testUpdateFailedInvalidData() {
+ verifyInvalidUpdateDataCombination(invalidDataNoDestination());
+ verifyInvalidUpdateDataCombination(invalidDataNoSource());
+ verifyInvalidUpdateDataCombination(invalidDataNoItag());
+ verifyInvalidUpdateDataCombination(invalidDataNoOperation());
+ verifyInvalidUpdateDataCombination(invalidDataNoVlan());
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ whenRewriteThenSuccess();
+ customizer.deleteCurrentAttributes(validId, validData(), writeContext);
+ verifyRewriteRequest(desiredDisableResult());
+ }
+
+ @Test
+ public void testDeleteFailedCallFailed() {
+ whenRewriteThenFail();
+ final PbbRewrite validData = 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");
+ }
+
+ @Test
+ public void testDeleteFailedInvalidData() {
+ verifyInvalidDeleteDataCombination(invalidDataNoDestination());
+ verifyInvalidDeleteDataCombination(invalidDataNoSource());
+ verifyInvalidDeleteDataCombination(invalidDataNoItag());
+ verifyInvalidDeleteDataCombination(invalidDataNoOperation());
+ verifyInvalidDeleteDataCombination(invalidDataNoVlan());
+ }
+
+ private void whenRewriteThenSuccess() {
+ when(api.l2InterfacePbbTagRewrite(any())).thenReturn(future(new L2InterfacePbbTagRewriteReply()));
+ }
+
+ private void whenRewriteThenFail() {
+ when(api.l2InterfacePbbTagRewrite(any())).thenReturn(failedFuture());
+ }
+
+ private void verifyInvalidWriteDataCombination(final PbbRewrite invalidData) {
+ try {
+ customizer.writeCurrentAttributes(validId, invalidData, writeContext);
+ } catch (Exception e) {
+ assertTrue(e instanceof NullPointerException);
+ return;
+ }
+
+ fail("Verifying of invalid combination failed");
+ }
+
+ private void verifyInvalidUpdateDataCombination(final PbbRewrite invalidData) {
+ try {
+ customizer.updateCurrentAttributes(validId, validData(), invalidData, writeContext);
+ } catch (Exception e) {
+ assertTrue(e instanceof NullPointerException);
+ return;
+ }
+
+ fail("Verifying of invalid combination failed");
+ }
+
+
+ private void verifyInvalidDeleteDataCombination(final PbbRewrite invalidData) {
+ try {
+ customizer.deleteCurrentAttributes(validId, invalidData, writeContext);
+ } catch (Exception e) {
+ assertTrue(e instanceof NullPointerException);
+ return;
+ }
+
+ fail("Verifying of invalid combination failed");
+ }
+
+
+ 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 = 1;
+ 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 = 1;
+ 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);
+ }
+
+ private PbbRewrite invalidDataNoDestination() {
+ return new PbbRewriteBuilder()
+ .setBVlanTagVlanId(1)
+ .setITagIsid(2L)
+ .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+ .setInterfaceOperation(Operation.Pop2)
+ .build();
+ }
+
+ private PbbRewrite invalidDataNoSource() {
+ return new PbbRewriteBuilder()
+ .setBVlanTagVlanId(1)
+ .setITagIsid(2L)
+ .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+ .setInterfaceOperation(Operation.Pop2)
+ .build();
+ }
+
+ private PbbRewrite invalidDataNoItag() {
+ return new PbbRewriteBuilder()
+ .setBVlanTagVlanId(1)
+ .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+ .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+ .setInterfaceOperation(Operation.Pop2)
+ .build();
+ }
+
+ private 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();
+ }
+
+ private 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();
+ }
+
+ private PbbRewrite validData() {
+ return new PbbRewriteBuilder()
+ .setBVlanTagVlanId(1)
+ .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/interfacesstate/EthernetCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizerTest.java
new file mode 100644
index 000000000..338d63333
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/EthernetCustomizerTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.interfacesstate;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.EthernetStateAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.Ethernet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.EthernetBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+
+public class EthernetCustomizerTest extends ReaderCustomizerTest<Ethernet, EthernetBuilder> implements
+ InterfaceDumpHelper {
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+ private static final InstanceIdentifier<Ethernet> IID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(VppInterfaceStateAugmentation.class).child(Ethernet.class);
+ private NamingContext interfaceContext;
+
+ public EthernetCustomizerTest() {
+ super(Ethernet.class, VppInterfaceStateAugmentationBuilder.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
+ }
+
+ @Override
+ protected ReaderCustomizer<Ethernet, EthernetBuilder> initCustomizer() {
+ return new EthernetCustomizer(api, interfaceContext);
+ }
+
+ private void testRead(final int linkDuplex, final EthernetStateAttributes.Duplex duplex) throws ReadFailedException {
+ final EthernetBuilder builder = mock(EthernetBuilder.class);
+ final short mtu = 123;
+ whenSwInterfaceDumpThenReturn(api, ifaceDetails(mtu, linkDuplex));
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+ verify(builder).setMtu((int)mtu);
+ verify(builder).setDuplex(duplex);
+ }
+
+ private SwInterfaceDetails ifaceDetails(final short mtu, final int duplex) {
+ final SwInterfaceDetails details = new SwInterfaceDetails();
+ details.swIfIndex = IF_INDEX;
+ details.linkMtu = mtu;
+ details.linkDuplex = (byte)duplex;
+ return details;
+ }
+
+ @Test
+ public void testReadHalfDuplex() throws ReadFailedException {
+ testRead(1, EthernetStateAttributes.Duplex.Half);
+ }
+
+ @Test
+ public void testReadFullDuplex() throws ReadFailedException {
+ testRead(2, EthernetStateAttributes.Duplex.Full);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/GreCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/GreCustomizerTest.java
new file mode 100644
index 000000000..1aadb5bd1
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/GreCustomizerTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.interfacesstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import com.google.common.collect.Lists;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.Gre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.GreBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.GreTunnelDetails;
+import io.fd.vpp.jvpp.core.dto.GreTunnelDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.GreTunnelDump;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+
+public class GreCustomizerTest extends ReaderCustomizerTest<Gre, GreBuilder> {
+
+ private static final String IFACE_NAME = "ifc1";
+ private static final int IFACE_ID = 0;
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+
+ private NamingContext interfacesContext;
+ static final InstanceIdentifier<Gre> IID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(VppInterfaceStateAugmentation.class).child(Gre.class);
+
+ public GreCustomizerTest() {
+ super(Gre.class, VppInterfaceStateAugmentationBuilder.class);
+ }
+
+ @Override
+ public void setUp() throws UnknownHostException, VppInvocationException {
+ interfacesContext = new NamingContext("gre-tunnel", IFC_CTX_NAME);
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+
+ final SwInterfaceDetails v = new SwInterfaceDetails();
+ v.interfaceName = "gre-tunnel4".getBytes();
+ final Map<Integer, SwInterfaceDetails> map = new HashMap<>();
+ map.put(0, v);
+ cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map);
+
+ final GreTunnelDetailsReplyDump value = new GreTunnelDetailsReplyDump();
+ final GreTunnelDetails greTunnelDetails = new GreTunnelDetails();
+ greTunnelDetails.isIpv6 = 0;
+ greTunnelDetails.dstAddress = InetAddress.getByName("1.2.3.4").getAddress();
+ greTunnelDetails.srcAddress = InetAddress.getByName("1.2.3.5").getAddress();
+ greTunnelDetails.outerFibId = 55;
+ greTunnelDetails.swIfIndex = 0;
+ value.greTunnelDetails = Lists.newArrayList(greTunnelDetails);
+
+ doReturn(future(value)).when(api).greTunnelDump(any(GreTunnelDump.class));
+ }
+
+ @Test
+ public void testReadCurrentAttributes() throws Exception {
+ final GreBuilder builder = getCustomizer().getBuilder(IID);
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+
+ assertEquals(55, builder.getOuterFibId().intValue());
+
+ assertNull(builder.getSrc().getIpv6Address());
+ assertNotNull(builder.getSrc().getIpv4Address());
+ assertEquals("1.2.3.5", builder.getSrc().getIpv4Address().getValue());
+
+ assertNull(builder.getDst().getIpv6Address());
+ assertNotNull(builder.getDst().getIpv4Address());
+ assertEquals("1.2.3.4", builder.getDst().getIpv4Address().getValue());
+
+ verify(api).greTunnelDump(any(GreTunnelDump.class));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testReadCurrentAttributesVppNameNotCached() throws Exception {
+ InterfaceCustomizer.getCachedInterfaceDump(cache).remove(0);
+
+ final GreBuilder builder = getCustomizer().getBuilder(IID);
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+ }
+
+ @Test
+ public void testReadCurrentAttributesWrongType() throws Exception {
+ final SwInterfaceDetails v = new SwInterfaceDetails();
+ v.interfaceName = "tap-2".getBytes();
+ InterfaceCustomizer.getCachedInterfaceDump(cache).put(0, v);
+
+ final GreBuilder builder = getCustomizer().getBuilder(IID);
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+
+ // Should be ignored
+ verifyZeroInteractions(api);
+ }
+
+ @Override
+ protected ReaderCustomizer<Gre, GreBuilder> initCustomizer() {
+ return new GreCustomizer(api, interfacesContext);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizerTest.java
new file mode 100644
index 000000000..295805114
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceCustomizerTest.java
@@ -0,0 +1,200 @@
+/*
+ * 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.interfacesstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest;
+import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDump;
+
+public class InterfaceCustomizerTest extends ListReaderCustomizerTest<Interface, InterfaceKey, InterfaceBuilder>
+ implements InterfaceDataTranslator, InterfaceDumpHelper {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IFACE0_NAME = "eth0";
+ private static final String IFACE1_NAME = "eth1";
+ private static final String SUB_IFACE_NAME = "eth1.1";
+ private static final int IFACE0_ID = 0;
+ private static final int IFACE1_ID = 1;
+ private static final int SUB_IFACE_ID = 2;
+
+ private NamingContext interfacesContext;
+ @Mock
+ private DisabledInterfacesManager interfaceDisableContext;
+
+ public InterfaceCustomizerTest() {
+ super(Interface.class, InterfacesStateBuilder.class);
+ }
+
+ @Override
+ public void setUp() {
+ interfacesContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ defineMapping(mappingContext, IFACE0_NAME, IFACE0_ID, IFC_CTX_NAME);
+ defineMapping(mappingContext, IFACE1_NAME, IFACE1_ID, IFC_CTX_NAME);
+ defineMapping(mappingContext, SUB_IFACE_NAME, SUB_IFACE_ID, IFC_CTX_NAME);
+ }
+
+ @Override
+ protected ReaderCustomizer<Interface, InterfaceBuilder> initCustomizer() {
+ return new InterfaceCustomizer(api, interfacesContext, interfaceDisableContext);
+ }
+
+ private void verifySwInterfaceDumpWasInvoked(final int nameFilterValid, final String ifaceName,
+ final int dumpIfcsInvocationCount)
+ throws VppInvocationException {
+ final SwInterfaceDump expected = new SwInterfaceDump();
+ expected.nameFilterValid = (byte) nameFilterValid;
+ expected.nameFilter = ifaceName.getBytes();
+ verify(api, times(dumpIfcsInvocationCount)).swInterfaceDump(expected);
+ }
+
+ private void assertIfacesAreEqual(final Interface iface, final SwInterfaceDetails details) {
+ assertEquals(iface.getName(), new String(details.interfaceName));
+ assertEquals(yangIfIndexToVpp(iface.getIfIndex().intValue()), details.swIfIndex);
+ assertEquals(iface.getPhysAddress().getValue(), vppPhysAddrToYang(details.l2Address));
+ }
+
+ @Test
+ public void testReadCurrentAttributes() throws Exception {
+ final InstanceIdentifier<Interface> id = InstanceIdentifier.create(InterfacesState.class)
+ .child(Interface.class, new InterfaceKey(IFACE0_NAME));
+ final InterfaceBuilder builder = getCustomizer().getBuilder(id);
+
+ final SwInterfaceDetails iface = new SwInterfaceDetails();
+ iface.interfaceName = IFACE0_NAME.getBytes();
+ iface.swIfIndex = 0;
+ iface.linkSpeed = 1;
+ iface.l2AddressLength = 6;
+ iface.l2Address = new byte[iface.l2AddressLength];
+ whenSwInterfaceDumpThenReturn(api, iface);
+
+ getCustomizer().readCurrentAttributes(id, builder, ctx);
+
+ verifySwInterfaceDumpWasInvoked(1, IFACE0_NAME, 1);
+ assertIfacesAreEqual(builder.build(), iface);
+ }
+
+ @Test
+ public void testReadCurrentAttributesFailed() throws Exception {
+ final String ifaceName = IFACE0_NAME;
+ final InstanceIdentifier<Interface> id = InstanceIdentifier.create(InterfacesState.class)
+ .child(Interface.class, new InterfaceKey(ifaceName));
+ final InterfaceBuilder builder = getCustomizer().getBuilder(id);
+
+ whenSwInterfaceDumpThenReturn(api);
+
+ try {
+ getCustomizer().readCurrentAttributes(id, builder, ctx);
+ } catch (IllegalArgumentException e) {
+ verifySwInterfaceDumpWasInvoked(0, ifaceName, 2);
+ return;
+ }
+
+ fail("ReadFailedException was expected");
+ }
+
+ @Test
+ public void testReadSubInterface() throws Exception {
+ final InstanceIdentifier<Interface> id = InstanceIdentifier.create(InterfacesState.class)
+ .child(Interface.class, new InterfaceKey(SUB_IFACE_NAME));
+ final InterfaceBuilder builder = mock(InterfaceBuilder.class);
+
+ final SwInterfaceDetails iface = new SwInterfaceDetails();
+ iface.interfaceName = SUB_IFACE_NAME.getBytes();
+ iface.swIfIndex = 2;
+ iface.supSwIfIndex = 1;
+ iface.subId = 1;
+ whenSwInterfaceDumpThenReturn(api, iface);
+
+ getCustomizer().readCurrentAttributes(id, builder, ctx);
+
+ verifySwInterfaceDumpWasInvoked(1, SUB_IFACE_NAME, 1);
+ verifyZeroInteractions(builder);
+ }
+
+ @Test
+ public void testGetAllIds() throws Exception {
+ final InstanceIdentifier<Interface> id = InstanceIdentifier.create(InterfacesState.class)
+ .child(Interface.class);
+
+ final SwInterfaceDetails swIf0 = new SwInterfaceDetails();
+ swIf0.swIfIndex = 0;
+ swIf0.interfaceName = IFACE0_NAME.getBytes();
+ final SwInterfaceDetails swIf1 = new SwInterfaceDetails();
+ swIf1.swIfIndex = 1;
+ swIf1.interfaceName = IFACE1_NAME.getBytes();
+ final SwInterfaceDetails swSubIf1 = new SwInterfaceDetails();
+ swSubIf1.swIfIndex = 2;
+ swSubIf1.subId = 1;
+ swSubIf1.supSwIfIndex = 1;
+ swSubIf1.interfaceName = SUB_IFACE_NAME.getBytes();
+ whenSwInterfaceDumpThenReturn(api, swIf0, swIf1, swSubIf1);
+
+ final List<InterfaceKey> expectedIds = Arrays.asList(new InterfaceKey(IFACE0_NAME), new InterfaceKey(
+ IFACE1_NAME));
+ final List<InterfaceKey> actualIds = getCustomizer().getAllIds(id, ctx);
+
+ verifySwInterfaceDumpWasInvoked(0, "", 1);
+
+ // sub-interface should not be on the list
+ assertEquals(expectedIds, actualIds);
+ }
+
+ @Test
+ public void testGetAllIdsWithDisabled() throws Exception {
+ final InstanceIdentifier<Interface> id = InstanceIdentifier.create(InterfacesState.class)
+ .child(Interface.class);
+
+ doReturn(true).when(interfaceDisableContext).isInterfaceDisabled(1, mappingContext);
+
+ final SwInterfaceDetails swIf0 = new SwInterfaceDetails();
+ swIf0.swIfIndex = 0;
+ swIf0.interfaceName = IFACE0_NAME.getBytes();
+ final SwInterfaceDetails swIf1 = new SwInterfaceDetails();
+ swIf1.swIfIndex = 1;
+ swIf1.interfaceName = IFACE1_NAME.getBytes();
+ whenSwInterfaceDumpThenReturn(api, swIf0, swIf1);
+
+ final List<InterfaceKey> expectedIds = Arrays.asList(new InterfaceKey(IFACE0_NAME));
+ final List<InterfaceKey> actualIds = getCustomizer().getAllIds(id, ctx);
+
+ // disabled interface should not be on the list
+ assertEquals(expectedIds, actualIds);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslatorTest.java
new file mode 100644
index 000000000..7c7f64817
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/InterfaceDataTranslatorTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.interfacesstate;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.Tap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VhostUser;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanGpeTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanTunnel;
+
+public class InterfaceDataTranslatorTest implements InterfaceDataTranslator {
+
+ @Test
+ public void testVppPhysAddrToYang() throws Exception {
+ assertEquals("01:02:03:04:05:06", vppPhysAddrToYang(new byte[]{1, 2, 3, 4, 5, 6}));
+ assertEquals("0a:0b:0c:0d:0e:0f", vppPhysAddrToYang(new byte[]{0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0}));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testVppPhysAddrToYangFailNullArgument() throws Exception {
+ vppPhysAddrToYang(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testVppPhysAddrToYangInvalidByteArrayLength() throws Exception {
+ vppPhysAddrToYang(new byte[]{1, 2, 3, 4, 5});
+ }
+
+ @Test
+ public void testGetInterfaceType() {
+ assertEquals(Tap.class, getInterfaceType("tap0"));
+ assertEquals(VxlanTunnel.class, getInterfaceType("vxlan0"));
+ assertEquals(VxlanGpeTunnel.class, getInterfaceType("vxlan_gpe0"));
+ assertEquals(VhostUser.class, getInterfaceType("VirtualEthernet0/0/0"));
+ assertEquals(EthernetCsmacd.class, getInterfaceType("eth0.0"));
+ assertEquals(EthernetCsmacd.class, getInterfaceType("local0"));
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/L2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/L2CustomizerTest.java
new file mode 100644
index 000000000..531e18d22
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/L2CustomizerTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.interfacesstate;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.L2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.Interconnection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.interconnection.BridgeBasedBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.BridgeDomainDetails;
+import io.fd.vpp.jvpp.core.dto.BridgeDomainDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.BridgeDomainDump;
+import io.fd.vpp.jvpp.core.dto.BridgeDomainSwIfDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+
+public class L2CustomizerTest extends ReaderCustomizerTest<L2, L2Builder> {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String BD_CTX_NAME = "bd-test-instance";
+ private NamingContext interfaceContext;
+ private NamingContext bridgeDomainContext;
+
+ public L2CustomizerTest() {
+ super(L2.class, VppInterfaceStateAugmentationBuilder.class);
+ }
+
+ @Override
+ public void setUp() {
+ interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ bridgeDomainContext = new NamingContext("generatedBDName", BD_CTX_NAME);
+ }
+
+ @Override
+ protected ReaderCustomizer<L2, L2Builder> initCustomizer() {
+ return new L2Customizer(api, interfaceContext, bridgeDomainContext);
+ }
+
+ private InstanceIdentifier<L2> getL2Id(final String name) {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name))
+ .augmentation(
+ VppInterfaceStateAugmentation.class).child(L2.class);
+ }
+
+ private void whenBridgeDomainSwIfDumpThenReturn(final List<BridgeDomainSwIfDetails> bdSwIfList,
+ final List<BridgeDomainDetails> bridgeDomainDetailses) {
+ final BridgeDomainDetailsReplyDump reply = new BridgeDomainDetailsReplyDump();
+ reply.bridgeDomainSwIfDetails = bdSwIfList;
+ reply.bridgeDomainDetails = bridgeDomainDetailses;
+ when(api.bridgeDomainSwIfDump(any(BridgeDomainDump.class))).thenReturn(future(reply));
+ }
+
+
+ private BridgeDomainSwIfDetails generateBdSwIfDetails(final int ifId, final int bdId) {
+ final BridgeDomainSwIfDetails bdSwIfDetails = new BridgeDomainSwIfDetails();
+ bdSwIfDetails.swIfIndex = ifId;
+ bdSwIfDetails.shg = 1;
+ bdSwIfDetails.bdId = bdId;
+ return bdSwIfDetails;
+ }
+
+ private Interconnection generateInterconnection(final int ifId, final String bdName, final Boolean bvi) {
+ final BridgeBasedBuilder bbBuilder = new BridgeBasedBuilder();
+ bbBuilder.setBridgeDomain(bdName);
+ bbBuilder.setSplitHorizonGroup((short) 1);
+ if (bvi != null) {
+ bbBuilder.setBridgedVirtualInterface(bvi);
+ } else {
+ bbBuilder.setBridgedVirtualInterface(false); // false is default
+ }
+ return bbBuilder.build();
+ }
+
+ @Test
+ public void testRead() throws Exception {
+ final Map<Integer, SwInterfaceDetails> cachedInterfaceDump = new HashMap<>();
+ final int ifId = 1;
+ final int bdId = 1;
+ final String bdName = "bd001";
+ final String ifName = "eth0.sub0";
+ defineMapping(mappingContext, ifName, ifId, IFC_CTX_NAME);
+ defineMapping(mappingContext, bdName, bdId, BD_CTX_NAME);
+
+ final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails();
+ ifaceDetails.subId = ifId;
+ cachedInterfaceDump.put(ifId, ifaceDetails);
+ cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump);
+
+ // BVIinterfaceContext
+ whenBridgeDomainSwIfDumpThenReturn(Collections.singletonList(generateBdSwIfDetails(ifId, bdId)),
+ Collections.singletonList(generateBdDetails(ifId, bdId)));
+
+ L2Builder builder = mock(L2Builder.class);
+ getCustomizer().readCurrentAttributes(getL2Id(ifName), builder, ctx);
+
+ verify(builder).setInterconnection(generateInterconnection(ifId, bdName, true));
+
+ // Not BVI
+ whenBridgeDomainSwIfDumpThenReturn(Collections.singletonList(generateBdSwIfDetails(ifId, bdId)),
+ Collections.singletonList(generateBdDetails(99 /* Different ifc is marked as BVI in bd details */, bdId)));
+
+ builder = mock(L2Builder.class);
+ getCustomizer().readCurrentAttributes(getL2Id(ifName), builder, ctx);
+
+ verify(builder).setInterconnection(generateInterconnection(ifId, bdName, null));
+ }
+
+ private BridgeDomainDetails generateBdDetails(final int ifId, final int bdId) {
+ final BridgeDomainDetails bridgeDomainDetails = new BridgeDomainDetails();
+ bridgeDomainDetails.bviSwIfIndex = ifId;
+ bridgeDomainDetails.bdId = bdId;
+ return bridgeDomainDetails;
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizerTest.java
new file mode 100644
index 000000000..1b79f518c
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/RewriteCustomizerTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.interfacesstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.translate.util.TagRewriteOperation;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214._802dot1q;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.l2.Rewrite;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.l2.RewriteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.tag.rewrite.PushTags;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+
+public class RewriteCustomizerTest extends ReaderCustomizerTest<Rewrite, RewriteBuilder> {
+
+ private static final String IFC_CTX_NAME = "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_INDEX = 11;
+ private static final int VLAN_ID = 1;
+
+ private NamingContext interfacesContext;
+
+ @Captor
+ private ArgumentCaptor<List<PushTags>> captor;
+
+ public RewriteCustomizerTest() {
+ super(Rewrite.class, L2Builder.class);
+ }
+
+ @Override
+ public void setUp() {
+ interfacesContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ defineMapping(mappingContext, VLAN_IF_NAME, VLAN_IF_INDEX, IFC_CTX_NAME);
+ }
+
+ @Override
+ protected ReaderCustomizer<Rewrite, RewriteBuilder> initCustomizer() {
+ return new RewriteCustomizer(api, interfacesContext);
+ }
+
+ private InstanceIdentifier<Rewrite> getVlanTagRewriteId(final String name, final long index) {
+ final Class<ChildOf<? super SubInterface>> child = (Class)Rewrite.class;
+ final InstanceIdentifier id =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name)).augmentation(
+ SubinterfaceStateAugmentation.class).child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey(index))
+ .child(child);
+ return id;
+ }
+
+ @Test
+ public void testRead() throws ReadFailedException {
+ final Map<Integer, SwInterfaceDetails> cachedInterfaceDump = new HashMap<>();
+
+ final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails();
+ ifaceDetails.subId = VLAN_ID;
+ ifaceDetails.interfaceName = VLAN_IF_NAME.getBytes();
+ ifaceDetails.vtrOp = TagRewriteOperation.translate_2_to_2.ordinal();
+ ifaceDetails.subNumberOfTags = 2;
+ ifaceDetails.vtrTag1 = 123;
+ ifaceDetails.vtrTag2 = 321;
+ ifaceDetails.vtrPushDot1Q = 1;
+ cachedInterfaceDump.put(VLAN_IF_INDEX, ifaceDetails);
+ cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump);
+
+ final RewriteBuilder builder = mock(RewriteBuilder.class);
+
+ getCustomizer().readCurrentAttributes(getVlanTagRewriteId(IF_NAME, VLAN_ID), builder, ctx);
+
+ verify(builder).setVlanType(_802dot1q.class);
+ verify(builder).setPopTags((short) 2);
+
+ verify(builder).setPushTags(captor.capture());
+ final List<PushTags> tags = captor.getValue();
+ assertEquals(ifaceDetails.subNumberOfTags, tags.size());
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizerTest.java
new file mode 100644
index 000000000..802d040dc
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceCustomizerTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.interfacesstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest;
+import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.SubInterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.match.attributes.match.type.VlanTagged;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.Tags;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+
+public class SubInterfaceCustomizerTest extends ListReaderCustomizerTest<SubInterface, SubInterfaceKey, SubInterfaceBuilder> implements
+ InterfaceDumpHelper {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String SUPER_IF_NAME = "local0";
+ private static final int SUPER_IF_INDEX = 1;
+ 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 interfacesContext;
+
+ public SubInterfaceCustomizerTest() {
+ super(SubInterface.class, SubInterfacesBuilder.class);
+ }
+
+ @Override
+ public void setUp() {
+ interfacesContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ defineMapping(mappingContext, SUPER_IF_NAME, SUPER_IF_INDEX, IFC_CTX_NAME);
+ defineMapping(mappingContext, VLAN_IF_NAME, VLAN_IF_INDEX, IFC_CTX_NAME);
+ }
+
+ @Override
+ protected ReaderCustomizer<SubInterface, SubInterfaceBuilder> initCustomizer() {
+ return new SubInterfaceCustomizer(api, interfacesContext);
+ }
+
+ private InstanceIdentifier<SubInterface> getSubInterfaceId(final String name, final long id) {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(name)).augmentation(
+ SubinterfaceStateAugmentation.class).child(
+ SubInterfaces.class).child(SubInterface.class, new SubInterfaceKey(id));
+ }
+
+ @Test
+ public void testRead() throws ReadFailedException {
+ final Map<Integer, SwInterfaceDetails> cachedInterfaceDump = new HashMap<>();
+
+ final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails();
+ ifaceDetails.subId = VLAN_IF_ID;
+ ifaceDetails.interfaceName = VLAN_IF_NAME.getBytes();
+ ifaceDetails.subDot1Ad = 1;
+ defineMapping(mappingContext, SUPER_IF_NAME, SUPER_IF_INDEX, IFC_CTX_NAME);
+ defineMapping(mappingContext, VLAN_IF_NAME, VLAN_IF_INDEX, IFC_CTX_NAME);
+ ifaceDetails.subNumberOfTags = 2;
+ ifaceDetails.subOuterVlanIdAny = 1;
+ ifaceDetails.subInnerVlanIdAny = 1;
+ ifaceDetails.subExactMatch = 1;
+ cachedInterfaceDump.put(VLAN_IF_INDEX, ifaceDetails);
+ cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump);
+
+ final SubInterfaceBuilder builder = mock(SubInterfaceBuilder.class);
+ getCustomizer().readCurrentAttributes(getSubInterfaceId(SUPER_IF_NAME, VLAN_IF_ID), builder, ctx);
+
+ verify(builder).setIdentifier((long) VLAN_IF_ID);
+
+ ArgumentCaptor<Tags> tagCaptor = ArgumentCaptor.forClass(Tags.class);
+ verify(builder).setTags(tagCaptor.capture());
+ assertEquals(ifaceDetails.subNumberOfTags, tagCaptor.getValue().getTag().size());
+
+ ArgumentCaptor<Match> matchCaptor = ArgumentCaptor.forClass(Match.class);
+ verify(builder).setMatch(matchCaptor.capture());
+ final VlanTagged matchType = (VlanTagged)matchCaptor.getValue().getMatchType();
+ assertTrue(matchType.getVlanTagged().isMatchExactTags());
+ }
+
+ @Test
+ public void testGetAllIds() throws Exception {
+ final SwInterfaceDetails iface = new SwInterfaceDetails();
+ iface.interfaceName = VLAN_IF_NAME.getBytes();
+ iface.swIfIndex = VLAN_IF_INDEX;
+ iface.subId = VLAN_IF_ID;
+ iface.supSwIfIndex = SUPER_IF_INDEX;
+ whenSwInterfaceDumpThenReturn(api, iface);
+
+ final List<SubInterfaceKey> allIds =
+ getCustomizer().getAllIds(getSubInterfaceId(SUPER_IF_NAME, VLAN_IF_ID), ctx);
+
+ assertEquals(1, allIds.size());
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2CustomizerTest.java
new file mode 100644
index 000000000..fc7d8e853
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/SubInterfaceL2CustomizerTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.interfacesstate;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.L2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.L2Builder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceL2CustomizerTest extends ReaderCustomizerTest<L2, L2Builder> {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String BD_CTX_NAME = "bd-test-instance";
+ private NamingContext interfaceContext;
+ private NamingContext bridgeDomainContext;
+
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+ private static final String SUB_IF_NAME = "local0.1";
+ private static final long SUB_IF_ID = 1;
+ private static final int SUB_IF_INDEX = 11;
+ private InstanceIdentifier<L2> IID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(SubinterfaceStateAugmentation.class)
+ .child(SubInterfaces.class).child(SubInterface.class, new SubInterfaceKey(SUB_IF_ID)).child(L2.class);
+
+ public SubInterfaceL2CustomizerTest() {
+ super(L2.class, SubInterfaceBuilder.class);
+ }
+
+ @Override
+ protected void setUp() {
+ interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ bridgeDomainContext = new NamingContext("generatedBDName", BD_CTX_NAME);
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
+ defineMapping(mappingContext, SUB_IF_NAME, SUB_IF_INDEX, IFC_CTX_NAME);
+ }
+
+ @Override
+ protected ReaderCustomizer<L2, L2Builder> initCustomizer() {
+ return new SubInterfaceL2Customizer(api, interfaceContext, bridgeDomainContext);
+ }
+
+ @Test(expected = ReadFailedException.class)
+ public void testReadFailed() throws ReadFailedException {
+ final L2Builder builder = mock(L2Builder.class);
+ when(api.swInterfaceDump(any())).thenReturn(failedFuture());
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java
new file mode 100644
index 000000000..c9de7102a
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/TapCustomizerTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfacesstate;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.Tap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.TapBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceTapDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceTapDetailsReplyDump;
+
+public class TapCustomizerTest extends ReaderCustomizerTest<Tap, TapBuilder> implements InterfaceDumpHelper {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IF_NAME = "tap1";
+ private static final String TAP_NAME = "testTapName";
+ private static final int IF_INDEX = 1;
+ private static final InstanceIdentifier<Tap> IID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(VppInterfaceStateAugmentation.class).child(Tap.class);
+ private NamingContext interfaceContext;
+
+ public TapCustomizerTest() {
+ super(Tap.class, VppInterfaceStateAugmentationBuilder.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
+ whenSwInterfaceDumpThenReturn(api, ifaceDetails());
+ }
+
+ private SwInterfaceDetails ifaceDetails() {
+ final SwInterfaceDetails details = new SwInterfaceDetails();
+ details.swIfIndex = IF_INDEX;
+ details.interfaceName = IF_NAME.getBytes();
+ return details;
+ }
+
+ @Override
+ protected ReaderCustomizer<Tap, TapBuilder> initCustomizer() {
+ return new TapCustomizer(api, interfaceContext);
+ }
+
+ @Test
+ public void testRead() throws ReadFailedException {
+ final TapBuilder builder = mock(TapBuilder.class);
+ when(api.swInterfaceTapDump(any())).thenReturn(future(tapDump()));
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+ verify(builder).setTapName(TAP_NAME);
+ }
+
+ @Test(expected = ReadFailedException.class)
+ public void testReadFailed() throws ReadFailedException {
+ when(api.swInterfaceTapDump(any())).thenReturn(failedFuture());
+ getCustomizer().readCurrentAttributes(IID, mock(TapBuilder.class), ctx);
+ }
+
+ private SwInterfaceTapDetailsReplyDump tapDump() {
+ final SwInterfaceTapDetailsReplyDump reply = new SwInterfaceTapDetailsReplyDump();
+ final SwInterfaceTapDetails details = new SwInterfaceTapDetails();
+ details.devName = TAP_NAME.getBytes();
+ details.swIfIndex = IF_INDEX;
+ reply.swInterfaceTapDetails.add(details);
+ return reply;
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizerTest.java
new file mode 100644
index 000000000..57655db73
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VhostUserCustomizerTest.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.interfacesstate;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.hc2vpp.common.test.util.InterfaceDumpHelper;
+import java.math.BigInteger;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VhostUserRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.VhostUser;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.VhostUserBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetails;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceVhostUserDetailsReplyDump;
+
+public class VhostUserCustomizerTest extends ReaderCustomizerTest<VhostUser, VhostUserBuilder> implements
+ InterfaceDumpHelper {
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IF_NAME = "VirtualEthernet1";
+ private static final int IF_INDEX = 1;
+ private static final InstanceIdentifier<VhostUser> IID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(VppInterfaceStateAugmentation.class).child(VhostUser.class);
+
+ private NamingContext interfaceContext;
+
+ public VhostUserCustomizerTest() {
+ super(VhostUser.class, VppInterfaceStateAugmentationBuilder.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
+ whenSwInterfaceDumpThenReturn(api, ifaceDetails());
+ }
+
+ private SwInterfaceDetails ifaceDetails() {
+ final SwInterfaceDetails details = new SwInterfaceDetails();
+ details.swIfIndex = IF_INDEX;
+ details.interfaceName = IF_NAME.getBytes();
+ return details;
+ }
+
+ @Override
+ protected ReaderCustomizer<VhostUser, VhostUserBuilder> initCustomizer() {
+ return new VhostUserCustomizer(api, interfaceContext);
+ }
+
+ @Test
+ public void testRead() throws ReadFailedException {
+ final VhostUserBuilder builder = mock(VhostUserBuilder.class);
+ when(api.swInterfaceVhostUserDump(any())).thenReturn(future(vhostDump()));
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+ verifyVhostBuilder(builder);
+ }
+
+ @Test(expected = ReadFailedException.class)
+ public void testReadFailed() throws ReadFailedException {
+ when(api.swInterfaceVhostUserDump(any())).thenReturn(failedFuture());
+ getCustomizer().readCurrentAttributes(IID, mock(VhostUserBuilder.class), ctx);
+ }
+
+ private SwInterfaceVhostUserDetailsReplyDump vhostDump() {
+ final SwInterfaceVhostUserDetailsReplyDump reply = new SwInterfaceVhostUserDetailsReplyDump();
+ final SwInterfaceVhostUserDetails details = new SwInterfaceVhostUserDetails();
+ details.swIfIndex = IF_INDEX;
+ details.interfaceName = IF_NAME.getBytes();
+ details.isServer = 1;
+ details.features = 2;
+ details.numRegions = 3;
+ details.sockFilename = "socketName".getBytes();
+ details.virtioNetHdrSz = 4;
+ details.sockErrno = 5;
+ reply.swInterfaceVhostUserDetails.add(details);
+ return reply;
+ }
+
+ private void verifyVhostBuilder(final VhostUserBuilder builder) {
+ verify(builder).setRole(VhostUserRole.Server);
+ verify(builder).setFeatures(BigInteger.valueOf(2));
+ verify(builder).setNumMemoryRegions(3L);
+ verify(builder).setSocket("socketName");
+ verify(builder).setVirtioNetHdrSize(4L);
+ verify(builder).setConnectError("5");
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizerTest.java
new file mode 100644
index 000000000..d59d13672
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanCustomizerTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.interfacesstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import com.google.common.collect.Lists;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.Vxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.VxlanBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetails;
+import io.fd.vpp.jvpp.core.dto.VxlanTunnelDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.VxlanTunnelDump;
+
+public class VxlanCustomizerTest extends ReaderCustomizerTest<Vxlan, VxlanBuilder> {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IF_NAME = "ifc1";
+ private static final int IF_INDEX = 0;
+
+ private NamingContext interfacesContext;
+ static final InstanceIdentifier<Vxlan> IID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(VppInterfaceStateAugmentation.class).child(Vxlan.class);
+
+ public VxlanCustomizerTest() {
+ super(Vxlan.class, VppInterfaceStateAugmentationBuilder.class);
+ }
+
+ @Override
+ public void setUp() throws UnknownHostException, VppInvocationException {
+ interfacesContext = new NamingContext("vxlan-tunnel", IFC_CTX_NAME);
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
+
+ final SwInterfaceDetails v = new SwInterfaceDetails();
+ v.interfaceName = "vxlan-tunnel4".getBytes();
+ final Map<Integer, SwInterfaceDetails> map = new HashMap<>();
+ map.put(0, v);
+ cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map);
+
+ final VxlanTunnelDetailsReplyDump value = new VxlanTunnelDetailsReplyDump();
+ final VxlanTunnelDetails vxlanTunnelDetails = new VxlanTunnelDetails();
+ vxlanTunnelDetails.isIpv6 = 0;
+ vxlanTunnelDetails.decapNextIndex = 1;
+ vxlanTunnelDetails.dstAddress = InetAddress.getByName("1.2.3.4").getAddress();
+ vxlanTunnelDetails.srcAddress = InetAddress.getByName("1.2.3.5").getAddress();
+ vxlanTunnelDetails.encapVrfId = 55;
+ vxlanTunnelDetails.swIfIndex = 0;
+ vxlanTunnelDetails.vni = 9;
+ value.vxlanTunnelDetails = Lists.newArrayList(vxlanTunnelDetails);
+ doReturn(future(value)).when(api).vxlanTunnelDump(any(VxlanTunnelDump.class));
+ }
+
+ @Test
+ public void testReadCurrentAttributes() throws Exception {
+ final VxlanBuilder builder = getCustomizer().getBuilder(IID);
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+
+ assertEquals(9, builder.getVni().getValue().intValue());
+ assertEquals(55, builder.getEncapVrfId().intValue());
+
+ assertNull(builder.getSrc().getIpv6Address());
+ assertNotNull(builder.getSrc().getIpv4Address());
+ assertEquals("1.2.3.5", builder.getSrc().getIpv4Address().getValue());
+
+ assertNull(builder.getDst().getIpv6Address());
+ assertNotNull(builder.getDst().getIpv4Address());
+ assertEquals("1.2.3.4", builder.getDst().getIpv4Address().getValue());
+
+ verify(api).vxlanTunnelDump(any(VxlanTunnelDump.class));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testReadCurrentAttributesVppNameNotCached() throws Exception {
+ InterfaceCustomizer.getCachedInterfaceDump(cache).remove(0);
+
+ final VxlanBuilder builder = getCustomizer().getBuilder(IID);
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+ }
+
+ @Test
+ public void testReadCurrentAttributesWrongType() throws Exception {
+ final SwInterfaceDetails v = new SwInterfaceDetails();
+ v.interfaceName = "tap-2".getBytes();
+ InterfaceCustomizer.getCachedInterfaceDump(cache).put(0, v);
+
+ final VxlanBuilder builder = getCustomizer().getBuilder(IID);
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+
+ // Should be ignored
+ verifyZeroInteractions(api);
+ }
+
+ @Override
+ protected ReaderCustomizer<Vxlan, VxlanBuilder> initCustomizer() {
+ return new VxlanCustomizer(api, interfacesContext);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizerTest.java
new file mode 100644
index 000000000..e0abd51ec
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizerTest.java
@@ -0,0 +1,278 @@
+/*
+ * 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.interfacesstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import com.google.common.collect.Lists;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.VxlanGpe;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.VxlanGpeBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceDetails;
+import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetails;
+import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.VxlanGpeTunnelDump;
+
+public class VxlanGpeCustomizerTest extends ReaderCustomizerTest<VxlanGpe, VxlanGpeBuilder> {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IF_NAME = "ifc2";
+ private static final int IF_INDEX = 0;
+
+ private NamingContext interfacesContext;
+ private static final InstanceIdentifier<VxlanGpe> VXLAN_GPE_ID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(VppInterfaceStateAugmentation.class).child(VxlanGpe.class);
+
+ public VxlanGpeCustomizerTest() {
+ super(VxlanGpe.class, VppInterfaceStateAugmentationBuilder.class);
+ }
+
+ @Override
+ public void setUp() throws UnknownHostException, VppBaseCallException {
+ interfacesContext = new NamingContext("vxlan_gpe_inf", IFC_CTX_NAME);
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
+
+ final SwInterfaceDetails v = new SwInterfaceDetails();
+ v.interfaceName = "vxlan_gpe_inf2".getBytes();
+ final Map<Integer, SwInterfaceDetails> map = new HashMap<>();
+ map.put(0, v);
+ cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map);
+
+ final VxlanGpeTunnelDetailsReplyDump value = new VxlanGpeTunnelDetailsReplyDump();
+ final VxlanGpeTunnelDetails vxlanGpeTunnelDetails = new VxlanGpeTunnelDetails();
+ vxlanGpeTunnelDetails.isIpv6 = 0;
+ vxlanGpeTunnelDetails.local = InetAddress.getByName("1.2.3.4").getAddress();
+ vxlanGpeTunnelDetails.remote = InetAddress.getByName("1.2.3.5").getAddress();
+ vxlanGpeTunnelDetails.vni = 9;
+ vxlanGpeTunnelDetails.protocol = 1;
+ vxlanGpeTunnelDetails.encapVrfId = 55;
+ vxlanGpeTunnelDetails.decapVrfId = 66;
+ vxlanGpeTunnelDetails.swIfIndex = 0;
+ value.vxlanGpeTunnelDetails = Lists.newArrayList(vxlanGpeTunnelDetails);
+ doReturn(future(value)).when(api).vxlanGpeTunnelDump(any(VxlanGpeTunnelDump.class));
+ }
+
+ @Test
+ public void testReadCurrentAttributes() throws Exception {
+ final VxlanGpeBuilder builder = getCustomizer().getBuilder(VXLAN_GPE_ID);
+ getCustomizer().readCurrentAttributes(VXLAN_GPE_ID, builder, ctx);
+
+ assertNull(builder.getLocal().getIpv6Address());
+ assertNotNull(builder.getLocal().getIpv4Address());
+ assertEquals("1.2.3.4", builder.getLocal().getIpv4Address().getValue());
+
+ assertNull(builder.getRemote().getIpv6Address());
+ assertNotNull(builder.getRemote().getIpv4Address());
+ assertEquals("1.2.3.5", builder.getRemote().getIpv4Address().getValue());
+
+ assertEquals(9, builder.getVni().getValue().intValue());
+ assertEquals(1, builder.getNextProtocol().getIntValue());
+ assertEquals(55, builder.getEncapVrfId().intValue());
+ assertEquals(66, builder.getDecapVrfId().intValue());
+
+ verify(api).vxlanGpeTunnelDump(any(VxlanGpeTunnelDump.class));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testReadCurrentAttributesVppNameNotCached() throws Exception {
+ InterfaceCustomizer.getCachedInterfaceDump(cache).remove(0);
+
+ final VxlanGpeBuilder builder = getCustomizer().getBuilder(VXLAN_GPE_ID);
+ getCustomizer().readCurrentAttributes(VXLAN_GPE_ID, builder, ctx);
+ }
+
+ @Test
+ public void testReadCurrentAttributesWrongType() throws Exception {
+ final SwInterfaceDetails v = new SwInterfaceDetails();
+ v.interfaceName = "tap-3".getBytes();
+ InterfaceCustomizer.getCachedInterfaceDump(cache).put(0, v);
+
+ final VxlanGpeBuilder builder = getCustomizer().getBuilder(VXLAN_GPE_ID);
+ getCustomizer().readCurrentAttributes(VXLAN_GPE_ID, builder, ctx);
+
+ // Should be ignored
+ verifyZeroInteractions(api);
+ }
+
+ @Override
+ protected ReaderCustomizer<VxlanGpe, VxlanGpeBuilder> initCustomizer() {
+ return new VxlanGpeCustomizer(api, interfacesContext);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/acl/ingress/AclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/acl/ingress/AclCustomizerTest.java
new file mode 100644
index 000000000..6948302e8
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/acl/ingress/AclCustomizerTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.interfacesstate.acl.ingress;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterfaceReply;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.base.attributes.L2AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.acl.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces.state._interface.acl.IngressBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AclCustomizerTest extends ReaderCustomizerTest<Ingress, IngressBuilder> {
+
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+ private static final int TABLE_INDEX = 123;
+ private static final String TABLE_NAME = "table123";
+ private static final InstanceIdentifier<Ingress> IID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(VppInterfaceStateAugmentation.class).child(Acl.class).child(Ingress.class);
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+
+ private NamingContext interfaceContext;
+
+ @Mock
+ private VppClassifierContextManager classifyTableContext;
+
+ public AclCustomizerTest() {
+ super(Ingress.class, AclBuilder.class);
+ }
+
+ @Override
+ public void setUp() {
+ interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
+ }
+
+ @Override
+ protected ReaderCustomizer<Ingress, IngressBuilder> initCustomizer() {
+ return new AclCustomizer(api, interfaceContext, classifyTableContext);
+ }
+
+ @Test
+ public void testRead() throws ReadFailedException {
+ final IngressBuilder builder = mock(IngressBuilder.class);
+
+ final ClassifyTableByInterfaceReply reply = new ClassifyTableByInterfaceReply();
+ reply.l2TableId = TABLE_INDEX;
+ reply.ip4TableId = ~0;
+ reply.ip6TableId = ~0;
+ when(api.classifyTableByInterface(any())).thenReturn(future(reply));
+
+ when(classifyTableContext.getTableName(TABLE_INDEX, mappingContext)).thenReturn(TABLE_NAME);
+
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+
+ verify(builder).setL2Acl(new L2AclBuilder().setClassifyTable(TABLE_NAME).build());
+ verify(builder).setIp4Acl(null);
+ verify(builder).setIp6Acl(null);
+ }
+
+ @Test(expected = ReadFailedException.class)
+ public void testReadFailed() throws ReadFailedException {
+ when(api.classifyTableByInterface(any())).thenReturn(failedFuture());
+ getCustomizer().readCurrentAttributes(IID, mock(IngressBuilder.class), ctx);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/acl/ingress/SubInterfaceAclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/acl/ingress/SubInterfaceAclCustomizerTest.java
new file mode 100644
index 000000000..9dbb20fb0
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/acl/ingress/SubInterfaceAclCustomizerTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.interfacesstate.acl.ingress;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManager;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterfaceReply;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.base.attributes.Ip4AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.acl.base.attributes.Ip6AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.acl.Ingress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.base.attributes.acl.IngressBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceAclCustomizerTest extends ReaderCustomizerTest<Ingress, IngressBuilder> {
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+ private static final String SUB_IF_NAME = "local0.1";
+ private static final long SUB_IF_ID = 1;
+ private static final int SUB_IF_INDEX = 11;
+ private static final int TABLE_INDEX = 123;
+ private static final String TABLE_NAME = "table123";
+
+ private static final InstanceIdentifier<Ingress> IID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(SubinterfaceStateAugmentation.class).child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey(SUB_IF_ID)).child(Acl.class).child(Ingress.class);
+
+ private NamingContext interfaceContext;
+
+ @Mock
+ private VppClassifierContextManager classifyTableContext;
+
+ public SubInterfaceAclCustomizerTest() {
+ super(Ingress.class, AclBuilder.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
+ defineMapping(mappingContext, SUB_IF_NAME, SUB_IF_INDEX, IFC_CTX_NAME);
+ }
+
+ @Override
+ protected ReaderCustomizer<Ingress, IngressBuilder> initCustomizer() {
+ return new SubInterfaceAclCustomizer(api, interfaceContext, classifyTableContext);
+ }
+
+ @Test
+ public void testRead() throws ReadFailedException {
+ final IngressBuilder builder = mock(IngressBuilder.class);
+
+ final ClassifyTableByInterfaceReply reply = new ClassifyTableByInterfaceReply();
+ reply.swIfIndex = SUB_IF_INDEX;
+ reply.l2TableId = ~0;
+ reply.ip4TableId = TABLE_INDEX;
+ reply.ip6TableId = TABLE_INDEX;
+ when(api.classifyTableByInterface(any())).thenReturn(future(reply));
+
+ when(classifyTableContext.getTableName(TABLE_INDEX, mappingContext)).thenReturn(TABLE_NAME);
+
+ getCustomizer().readCurrentAttributes(IID, builder, ctx);
+
+ verify(builder).setL2Acl(null);
+ verify(builder).setIp4Acl(new Ip4AclBuilder().setClassifyTable(TABLE_NAME).build());
+ verify(builder).setIp6Acl(new Ip6AclBuilder().setClassifyTable(TABLE_NAME).build());
+ }
+
+ @Test(expected = ReadFailedException.class)
+ public void testReadFailed() throws ReadFailedException {
+ when(api.classifyTableByInterface(any())).thenReturn(failedFuture());
+ getCustomizer().readCurrentAttributes(IID, mock(IngressBuilder.class), ctx);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/Ipv4AddressCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/Ipv4AddressCustomizerTest.java
new file mode 100644
index 000000000..a2eda9157
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/Ipv4AddressCustomizerTest.java
@@ -0,0 +1,284 @@
+/*
+ * 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.interfacesstate.ip;
+
+
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.CacheKeyFactory;
+import io.fd.honeycomb.translate.util.read.cache.IdentifierCacheKeyFactory;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest;
+import io.fd.vpp.jvpp.core.dto.IpAddressDetails;
+import io.fd.vpp.jvpp.core.dto.IpAddressDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.IpAddressDump;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.AddressKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.address.subnet.PrefixLength;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Ipv4AddressCustomizerTest extends ListReaderCustomizerTest<Address, AddressKey, AddressBuilder> implements
+ Ipv4Translator {
+
+ private static final String IFACE_NAME = "eth0";
+ private static final String IFACE_2_NAME = "eth1";
+ private static final int IFACE_ID = 1;
+ private static final int IFACE_2_ID = 2;
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+
+ private NamingContext interfacesContext;
+ private InstanceIdentifier<Address> ifaceOneAddressOneIdentifier;
+ private InstanceIdentifier<Address> ifaceTwoAddressOneIdentifier;
+ private CacheKeyFactory cacheKeyFactory;
+
+ public Ipv4AddressCustomizerTest() {
+ super(Address.class, Ipv4Builder.class);
+ }
+
+ @Override
+ public void setUp() {
+ interfacesContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+ defineMapping(mappingContext, IFACE_2_NAME, IFACE_2_ID, IFC_CTX_NAME);
+
+ ifaceOneAddressOneIdentifier =
+ InstanceIdentifier.create(InterfacesState.class)
+ .child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(Interface2.class)
+ .child(Ipv4.class)
+ .child(Address.class, new AddressKey(new Ipv4AddressNoZone("192.168.2.1")));
+ ifaceTwoAddressOneIdentifier =
+ InstanceIdentifier.create(InterfacesState.class)
+ .child(Interface.class, new InterfaceKey(IFACE_2_NAME))
+ .augmentation(Interface2.class)
+ .child(Ipv4.class)
+ .child(Address.class, new AddressKey(new Ipv4AddressNoZone("192.168.2.1")));
+
+ // to simulate complex key
+ cacheKeyFactory = new IdentifierCacheKeyFactory(ImmutableSet.of(Interface.class));
+ }
+
+ @Override
+ protected ReaderCustomizer<Address, AddressBuilder> initCustomizer() {
+ return new Ipv4AddressCustomizer(api, interfacesContext);
+ }
+
+ private static InstanceIdentifier<Address> getId(final String address, final String ifaceName) {
+ return InstanceIdentifier.builder(InterfacesState.class)
+ .child(Interface.class, new InterfaceKey(ifaceName))
+ .augmentation(Interface2.class)
+ .child(Ipv4.class)
+ .child(Address.class, new AddressKey(new Ipv4AddressNoZone(new Ipv4Address(address))))
+ .build();
+ }
+
+ @Test
+ public void testReadCurrentAttributesFor2Ifcs() throws ReadFailedException {
+ //changed to mock to not store first dumped data(otherwise that double thenReturn on line 118 is not gonna work)
+
+ IpAddressDetails detail1 = new IpAddressDetails();
+ IpAddressDetails detail2 = new IpAddressDetails();
+
+ detail1.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"))));
+ detail2.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.2"))));
+
+ IpAddressDetailsReplyDump reply = new IpAddressDetailsReplyDump();
+ reply.ipAddressDetails = ImmutableList.of(detail1);
+ IpAddressDetailsReplyDump reply2 = new IpAddressDetailsReplyDump();
+ reply2.ipAddressDetails = ImmutableList.of(detail2);
+
+ CompletableFuture<IpAddressDetailsReplyDump> future = new CompletableFuture<>();
+ future.complete(reply);
+ CompletableFuture<IpAddressDetailsReplyDump> future2 = new CompletableFuture<>();
+ future2.complete(reply2);
+
+ when(api.ipAddressDump(Mockito.any(IpAddressDump.class))).thenReturn(future).thenReturn(future2)
+ .thenReturn(future).thenReturn(future2);
+ when(api.ipAddressDump(Mockito.any(IpAddressDump.class))).thenReturn(future(reply)).thenReturn(future(reply2))
+ .thenReturn(future(reply)).thenReturn(future(reply2));
+ when(ctx.getModificationCache()).thenReturn(cache);
+
+
+ final InstanceIdentifier<Address> id = getId("192.168.2.1", IFACE_NAME);
+ final InstanceIdentifier<Address> id2 = getId("192.168.2.2", IFACE_2_NAME);
+
+ final List<AddressKey> ifc1Ids = getCustomizer().getAllIds(id, ctx);
+ assertThat(ifc1Ids.size(), is(1));
+ assertThat(ifc1Ids, Matchers.hasItem(new AddressKey(new Ipv4AddressNoZone("192.168.2.1"))));
+ final List<AddressKey> ifc2Ids = getCustomizer().getAllIds(id2, ctx);
+ assertThat(ifc2Ids.size(), is(1));
+ assertThat(ifc2Ids, Matchers.hasItem(new AddressKey(new Ipv4AddressNoZone("192.168.2.2"))));
+
+ AddressBuilder builder = new AddressBuilder();
+ getCustomizer().readCurrentAttributes(id, builder, ctx);
+ assertEquals(builder.getIp().getValue(), "192.168.2.1");
+ builder = new AddressBuilder();
+ getCustomizer().readCurrentAttributes(id2, builder, ctx);
+ assertEquals(builder.getIp().getValue(), "192.168.2.2");
+ }
+
+ @Test
+ public void testReadCurrentAttributesSuccessfull() throws ReadFailedException {
+ IpAddressDetails detail1 = new IpAddressDetails();
+ IpAddressDetails detail2 = new IpAddressDetails();
+ IpAddressDetails detail3 = new IpAddressDetails();
+
+ detail1.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"))));
+ detail2.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.2"))));
+ detail3.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.3"))));
+
+ IpAddressDetailsReplyDump reply = new IpAddressDetailsReplyDump();
+ reply.ipAddressDetails = ImmutableList.of(detail1, detail2, detail3);
+ when(api.ipAddressDump(Mockito.any(IpAddressDump.class))).thenReturn(future(reply));
+ when(ctx.getModificationCache()).thenReturn(cache);
+
+ final AddressBuilder builder = new AddressBuilder();
+ final InstanceIdentifier<Address> id = getId("192.168.2.1", IFACE_NAME);
+
+ getCustomizer().readCurrentAttributes(id, builder, ctx);
+
+ assertEquals("192.168.2.1", builder.getIp().getValue());
+ }
+
+ @Test
+ public void testGetAllIdsFromSuccessfull() throws ReadFailedException {
+ IpAddressDetails detail1 = new IpAddressDetails();
+ IpAddressDetails detail2 = new IpAddressDetails();
+ IpAddressDetails detail3 = new IpAddressDetails();
+
+ detail1.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"))));
+ detail2.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.2"))));
+ detail3.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.3"))));
+
+ IpAddressDetailsReplyDump reply = new IpAddressDetailsReplyDump();
+ reply.ipAddressDetails = ImmutableList.of(detail1, detail2, detail3);
+ when(api.ipAddressDump(Mockito.any(IpAddressDump.class))).thenReturn(future(reply));
+ when(ctx.getModificationCache()).thenReturn(cache);
+
+ final InstanceIdentifier<Address> id = getId("192.168.2.1", IFACE_NAME);
+
+ List<Ipv4AddressNoZone> ids = getCustomizer().getAllIds(id, ctx).stream()
+ .map(key -> key.getIp())
+ .collect(Collectors.toList());
+
+ assertEquals(3, ids.size());
+ assertEquals(true, "192.168.2.1".equals(ids.get(0).getValue()));
+ assertEquals(true, "192.168.2.2".equals(ids.get(1).getValue()));
+ assertEquals(true, "192.168.2.3".equals(ids.get(2).getValue()));
+ }
+
+ @Test
+ public void testCachingScopeSpecificRequest() throws ReadFailedException {
+ fillCacheForTwoIfaces();
+ final AddressBuilder ifaceOneAddressBuilder = new AddressBuilder();
+ final AddressBuilder ifaceTwoAddressBuilder = new AddressBuilder();
+
+ getCustomizer().readCurrentAttributes(ifaceOneAddressOneIdentifier, ifaceOneAddressBuilder, ctx);
+ getCustomizer().readCurrentAttributes(ifaceTwoAddressOneIdentifier, ifaceTwoAddressBuilder, ctx);
+
+ // addresses have caching scope of parent interface, so returned address should have respective prefix lengths
+ assertEquals("192.168.2.1", ifaceOneAddressBuilder.getIp().getValue());
+ assertTrue(ifaceOneAddressBuilder.getSubnet() instanceof PrefixLength);
+ assertEquals(22, PrefixLength.class.cast(ifaceOneAddressBuilder.getSubnet()).getPrefixLength().intValue());
+
+ assertEquals("192.168.2.1", ifaceTwoAddressBuilder.getIp().getValue());
+ assertTrue(ifaceTwoAddressBuilder.getSubnet() instanceof PrefixLength);
+ assertEquals(23, PrefixLength.class.cast(ifaceTwoAddressBuilder.getSubnet()).getPrefixLength().intValue());
+ }
+
+ @Test
+ public void testCachingScopeGetAll() throws ReadFailedException {
+ fillCacheForFirstIfaceSecondEmpty();
+
+ final List<AddressKey> keysForIfaceOne = getCustomizer().getAllIds(ifaceOneAddressOneIdentifier, ctx);
+ assertThat(keysForIfaceOne, hasSize(1));
+ final AddressKey keyIfaceOne = keysForIfaceOne.get(0);
+ assertEquals("192.168.2.1", keyIfaceOne.getIp().getValue());
+
+ final List<AddressKey> keysForIfaceTwo = getCustomizer().getAllIds(ifaceTwoAddressOneIdentifier, ctx);
+ assertThat(keysForIfaceTwo, is(empty()));
+ }
+
+ private void fillCacheForTwoIfaces() {
+ IpAddressDetails detailIfaceOneAddressOne = new IpAddressDetails();
+ IpAddressDetails detailIfaceTwoAddressOne = new IpAddressDetails();
+ IpAddressDetailsReplyDump replyIfaceOne = new IpAddressDetailsReplyDump();
+ IpAddressDetailsReplyDump replyIfaceTwo = new IpAddressDetailsReplyDump();
+
+ replyIfaceOne.ipAddressDetails = Arrays.asList(detailIfaceOneAddressOne);
+ replyIfaceTwo.ipAddressDetails = Arrays.asList(detailIfaceTwoAddressOne);
+
+ detailIfaceOneAddressOne.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"))));
+ detailIfaceOneAddressOne.prefixLength = 22;
+
+ detailIfaceTwoAddressOne.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"))));
+ detailIfaceTwoAddressOne.prefixLength = 23;
+
+ cache.put(cacheKeyFactory.createKey(ifaceOneAddressOneIdentifier), replyIfaceOne);
+ cache.put(cacheKeyFactory.createKey(ifaceTwoAddressOneIdentifier), replyIfaceTwo);
+ }
+
+ private void fillCacheForFirstIfaceSecondEmpty() {
+ IpAddressDetails detailIfaceOneAddressOne = new IpAddressDetails();
+ IpAddressDetailsReplyDump replyIfaceOne = new IpAddressDetailsReplyDump();
+ replyIfaceOne.ipAddressDetails = Arrays.asList(detailIfaceOneAddressOne);
+
+ detailIfaceOneAddressOne.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"))));
+ detailIfaceOneAddressOne.prefixLength = 22;
+
+ cache.put(cacheKeyFactory.createKey(ifaceOneAddressOneIdentifier), replyIfaceOne);
+ cache.put(cacheKeyFactory.createKey(ifaceTwoAddressOneIdentifier), new IpAddressDetailsReplyDump());
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/Ipv4CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/Ipv4CustomizerTest.java
new file mode 100644
index 000000000..1bfb62771
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/Ipv4CustomizerTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.interfacesstate.ip;
+
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4Builder;
+
+public class Ipv4CustomizerTest extends ReaderCustomizerTest<Ipv4, Ipv4Builder> {
+
+ public Ipv4CustomizerTest() {
+ super(Ipv4.class, Interface2Builder.class);
+ }
+
+ @Test
+ public void testReadCurrentAttributes() throws Exception {
+ customizer.readCurrentAttributes(null, null, ctx);
+ verifyZeroInteractions(api);
+ }
+
+ @Override
+ protected ReaderCustomizer<Ipv4, Ipv4Builder> initCustomizer() {
+ return new Ipv4Customizer(api);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/SubInterfaceIpv4AddressCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/SubInterfaceIpv4AddressCustomizerTest.java
new file mode 100644
index 000000000..cecc70235
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/ip/SubInterfaceIpv4AddressCustomizerTest.java
@@ -0,0 +1,247 @@
+/*
+ * 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.interfacesstate.ip;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.honeycomb.translate.util.read.cache.CacheKeyFactory;
+import io.fd.honeycomb.translate.util.read.cache.IdentifierCacheKeyFactory;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest;
+import io.fd.vpp.jvpp.core.dto.IpAddressDetails;
+import io.fd.vpp.jvpp.core.dto.IpAddressDetailsReplyDump;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.SubinterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.interfaces.state._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.AddressKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.address.subnet.PrefixLength;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev161214.sub._interface.ip4.attributes.ipv4.address.subnet.PrefixLengthBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceIpv4AddressCustomizerTest extends ListReaderCustomizerTest<Address, AddressKey, AddressBuilder>
+ implements Ipv4Translator {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IF_NAME = "local0";
+ private static final int IF_INDEX = 1;
+ private static final String SUB_IF_NAME = "local0.1";
+ private static final String SUB_IF_2_NAME = "local0.2";
+ private static final long SUB_IF_ID = 1;
+ private static final int SUB_IF_INDEX = 11;
+ private static final int SUB_IF_2_INDEX = 12;
+ private static final InstanceIdentifier<Ipv4> IP4_IID =
+ InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(SubinterfaceStateAugmentation.class)
+ .child(SubInterfaces.class).child(SubInterface.class, new SubInterfaceKey(SUB_IF_ID))
+ .child(Ipv4.class);
+ private InstanceIdentifier<Address> ifaceOneAddressOneIdentifier;
+ private InstanceIdentifier<Address> ifaceTwoAddressOneIdentifier;
+ private CacheKeyFactory cacheKeyFactory;
+ private static final Ipv4AddressNoZone IP1 = new Ipv4AddressNoZone("10.1.1.1");
+ private static final Ipv4AddressNoZone IP2 = new Ipv4AddressNoZone("10.1.1.2");
+ private static final short PREFIX_LENGTH = 16;
+
+ private NamingContext interfaceContext;
+
+ public SubInterfaceIpv4AddressCustomizerTest() {
+ super(Address.class, Ipv4Builder.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ interfaceContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+
+ ifaceOneAddressOneIdentifier = InstanceIdentifier.create(InterfacesState.class)
+ .child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(SubinterfaceStateAugmentation.class)
+ .child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey(1L))
+ .child(Ipv4.class)
+ .child(Address.class, new AddressKey(new Ipv4AddressNoZone("192.168.2.1")));
+ ifaceTwoAddressOneIdentifier = InstanceIdentifier.create(InterfacesState.class)
+ .child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(SubinterfaceStateAugmentation.class)
+ .child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey(2L))
+ .child(Ipv4.class)
+ .child(Address.class, new AddressKey(new Ipv4AddressNoZone("192.168.2.1")));
+
+ // to simulate complex key
+ cacheKeyFactory = new IdentifierCacheKeyFactory(ImmutableSet.of(SubInterface.class));
+
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_CTX_NAME);
+ defineMapping(mappingContext, SUB_IF_NAME, SUB_IF_INDEX, IFC_CTX_NAME);
+ defineMapping(mappingContext, SUB_IF_2_NAME, SUB_IF_2_INDEX, IFC_CTX_NAME);
+ }
+
+ @Override
+ protected ListReaderCustomizer<Address, AddressKey, AddressBuilder> initCustomizer() {
+ return new SubInterfaceIpv4AddressCustomizer(api, interfaceContext);
+ }
+
+ private static InstanceIdentifier<Address> getId() {
+ return IP4_IID.child(Address.class);
+ }
+
+ private static InstanceIdentifier<Address> getId(final Ipv4AddressNoZone ip) {
+ return IP4_IID.child(Address.class, new AddressKey(ip));
+ }
+
+ @Test
+ public void testRead() throws ReadFailedException {
+ final AddressBuilder builder = mock(AddressBuilder.class);
+ when(api.ipAddressDump(any())).thenReturn(future(dump()));
+ getCustomizer().readCurrentAttributes(getId(IP2), builder, ctx);
+ verify(builder).setIp(IP2);
+ verify(builder).setSubnet(new PrefixLengthBuilder().setPrefixLength(PREFIX_LENGTH).build());
+ }
+
+ @Test(expected = ReadFailedException.class)
+ public void testReadFailed() throws ReadFailedException {
+ when(api.ipAddressDump(any())).thenReturn(failedFuture());
+ getCustomizer().readCurrentAttributes(getId(IP1), mock(AddressBuilder.class), ctx);
+ }
+
+ @Test
+ public void testGetAllIds() throws ReadFailedException {
+ when(api.ipAddressDump(any())).thenReturn(future(dump()));
+ final List<AddressKey> allIds = getCustomizer().getAllIds(getId(), ctx);
+ assertThat(allIds, hasSize(2));
+ assertThat(allIds, containsInAnyOrder(new AddressKey(IP1), new AddressKey(IP2)));
+ }
+
+ @Test(expected = ReadFailedException.class)
+ public void testGetAllIdsFailed() throws ReadFailedException {
+ when(api.ipAddressDump(any())).thenReturn(failedFuture());
+ getCustomizer().getAllIds(getId(), ctx);
+ }
+
+ @Test
+ public void testCacheScope() {
+
+ }
+
+ @Test
+ public void testCachingScopeSpecificRequest() throws ReadFailedException {
+ fillCacheForTwoIfaces();
+ final AddressBuilder ifaceOneAddressBuilder = new AddressBuilder();
+ final AddressBuilder ifaceTwoAddressBuilder = new AddressBuilder();
+
+ getCustomizer().readCurrentAttributes(ifaceOneAddressOneIdentifier, ifaceOneAddressBuilder, ctx);
+ getCustomizer().readCurrentAttributes(ifaceTwoAddressOneIdentifier, ifaceTwoAddressBuilder, ctx);
+
+ // addresses have caching scope of parent interface, so returned address should have respective prefix lengths
+ assertEquals("192.168.2.1", ifaceOneAddressBuilder.getIp().getValue());
+ assertTrue(ifaceOneAddressBuilder.getSubnet() instanceof PrefixLength);
+ assertEquals(22, PrefixLength.class.cast(ifaceOneAddressBuilder.getSubnet()).getPrefixLength().intValue());
+
+ assertEquals("192.168.2.1", ifaceTwoAddressBuilder.getIp().getValue());
+ assertTrue(ifaceTwoAddressBuilder.getSubnet() instanceof PrefixLength);
+ assertEquals(23, PrefixLength.class.cast(ifaceTwoAddressBuilder.getSubnet()).getPrefixLength().intValue());
+ }
+
+ @Test
+ public void testCachingScopeGetAll() throws ReadFailedException {
+ fillCacheForFirstIfaceSecondEmpty();
+
+ final List<AddressKey> keysForIfaceOne = getCustomizer().getAllIds(ifaceOneAddressOneIdentifier, ctx);
+ Assert.assertThat(keysForIfaceOne, hasSize(1));
+ final AddressKey keyIfaceOne = keysForIfaceOne.get(0);
+ assertEquals("192.168.2.1", keyIfaceOne.getIp().getValue());
+
+ final List<AddressKey> keysForIfaceTwo = getCustomizer().getAllIds(ifaceTwoAddressOneIdentifier, ctx);
+ Assert.assertThat(keysForIfaceTwo, is(empty()));
+ }
+
+ private void fillCacheForTwoIfaces() {
+ IpAddressDetails detailIfaceOneAddressOne = new IpAddressDetails();
+ IpAddressDetails detailIfaceTwoAddressOne = new IpAddressDetails();
+ IpAddressDetailsReplyDump replyIfaceOne = new IpAddressDetailsReplyDump();
+ IpAddressDetailsReplyDump replyIfaceTwo = new IpAddressDetailsReplyDump();
+
+ replyIfaceOne.ipAddressDetails = Arrays.asList(detailIfaceOneAddressOne);
+ replyIfaceTwo.ipAddressDetails = Arrays.asList(detailIfaceTwoAddressOne);
+
+ detailIfaceOneAddressOne.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"))));
+ detailIfaceOneAddressOne.prefixLength = 22;
+
+ detailIfaceTwoAddressOne.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"))));
+ detailIfaceTwoAddressOne.prefixLength = 23;
+
+ cache.put(cacheKeyFactory.createKey(ifaceOneAddressOneIdentifier), replyIfaceOne);
+ cache.put(cacheKeyFactory.createKey(ifaceTwoAddressOneIdentifier), replyIfaceTwo);
+ }
+
+ private void fillCacheForFirstIfaceSecondEmpty() {
+ IpAddressDetails detailIfaceOneAddressOne = new IpAddressDetails();
+ IpAddressDetailsReplyDump replyIfaceOne = new IpAddressDetailsReplyDump();
+ replyIfaceOne.ipAddressDetails = Arrays.asList(detailIfaceOneAddressOne);
+
+ detailIfaceOneAddressOne.ip = reverseBytes(
+ ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1"))));
+ detailIfaceOneAddressOne.prefixLength = 22;
+
+ cache.put(cacheKeyFactory.createKey(ifaceOneAddressOneIdentifier), replyIfaceOne);
+ cache.put(cacheKeyFactory.createKey(ifaceTwoAddressOneIdentifier), new IpAddressDetailsReplyDump());
+ }
+
+ private IpAddressDetailsReplyDump dump() {
+ final IpAddressDetailsReplyDump reply = new IpAddressDetailsReplyDump();
+
+ final IpAddressDetails details1 = new IpAddressDetails();
+ details1.ip = new byte[]{1, 1, 1, 10};
+ details1.prefixLength = (byte) PREFIX_LENGTH;
+ reply.ipAddressDetails.add(details1);
+
+ final IpAddressDetails details2 = new IpAddressDetails();
+ details2.ip = new byte[]{2, 1, 1, 10};
+ details2.prefixLength = (byte) PREFIX_LENGTH;
+ reply.ipAddressDetails.add(details2);
+
+ return reply;
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/pbb/PbbRewriteStateCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/pbb/PbbRewriteStateCustomizerTest.java
new file mode 100644
index 000000000..2fd959add
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/pbb/PbbRewriteStateCustomizerTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.interfacesstate.pbb;
+
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev161214.PbbRewriteStateInterfaceAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev161214.interfaces.state._interface.PbbRewriteState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.pbb.rev161214.interfaces.state._interface.PbbRewriteStateBuilder;
+
+public class PbbRewriteStateCustomizerTest extends ReaderCustomizerTest<PbbRewriteState, PbbRewriteStateBuilder> {
+
+ public PbbRewriteStateCustomizerTest() {
+ super(PbbRewriteState.class, PbbRewriteStateInterfaceAugmentationBuilder.class);
+ }
+
+ @Override
+ protected ReaderCustomizer<PbbRewriteState, PbbRewriteStateBuilder> initCustomizer() {
+ return new PbbRewriteStateCustomizer(api);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/notification/InterfaceChangeNotificationProducerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/notification/InterfaceChangeNotificationProducerTest.java
new file mode 100644
index 000000000..38c658895
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/notification/InterfaceChangeNotificationProducerTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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.notification;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import io.fd.honeycomb.notification.NotificationCollector;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.hc2vpp.common.test.util.NamingContextHelper;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.util.FutureProducer;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.InterfaceStateChange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.InterfaceStatus;
+import io.fd.vpp.jvpp.core.callback.SwInterfaceSetFlagsNotificationCallback;
+import io.fd.vpp.jvpp.core.dto.SwInterfaceSetFlagsNotification;
+import io.fd.vpp.jvpp.core.dto.WantInterfaceEvents;
+import io.fd.vpp.jvpp.core.dto.WantInterfaceEventsReply;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import io.fd.vpp.jvpp.core.notification.CoreNotificationRegistry;
+
+public class InterfaceChangeNotificationProducerTest implements FutureProducer, NamingContextHelper {
+
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private static final String IFACE_NAME = "eth0";
+ private static final int IFACE_ID = 0;
+
+ @Mock
+ private FutureJVppCore jVpp;
+ private NamingContext namingContext = new NamingContext("test", IFC_CTX_NAME);
+ @Mock
+ private MappingContext mappingContext;
+ @Mock
+ private NotificationCollector collector;
+ @Mock
+ private CoreNotificationRegistry notificationRegistry;
+ @Mock
+ private AutoCloseable notificationListenerReg;
+
+ private ArgumentCaptor<SwInterfaceSetFlagsNotificationCallback> callbackArgumentCaptor;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ doReturn(notificationRegistry).when(jVpp).getNotificationRegistry();
+ callbackArgumentCaptor = ArgumentCaptor.forClass(SwInterfaceSetFlagsNotificationCallback.class);
+ doReturn(notificationListenerReg).when(notificationRegistry).registerSwInterfaceSetFlagsNotificationCallback(
+ callbackArgumentCaptor.capture());
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+ doReturn(future(new WantInterfaceEventsReply())).when(jVpp).wantInterfaceEvents(any(WantInterfaceEvents.class));
+ }
+
+ @Test
+ public void testStart() throws Exception {
+ final InterfaceChangeNotificationProducer interfaceChangeNotificationProducer =
+ new InterfaceChangeNotificationProducer(jVpp, namingContext, mappingContext);
+
+ interfaceChangeNotificationProducer.start(collector);
+ verify(jVpp).wantInterfaceEvents(any(WantInterfaceEvents.class));
+ verify(jVpp).getNotificationRegistry();
+ verify(notificationRegistry).registerSwInterfaceSetFlagsNotificationCallback(any(
+ SwInterfaceSetFlagsNotificationCallback.class));
+
+ interfaceChangeNotificationProducer.stop();
+ verify(jVpp, times(2)).wantInterfaceEvents(any(WantInterfaceEvents.class));
+ verify(notificationListenerReg).close();
+ }
+
+ @Test
+ public void testNotification() throws Exception {
+ final InterfaceChangeNotificationProducer interfaceChangeNotificationProducer =
+ new InterfaceChangeNotificationProducer(jVpp, namingContext, mappingContext);
+
+ interfaceChangeNotificationProducer.start(collector);
+
+ final SwInterfaceSetFlagsNotification swInterfaceSetFlagsNotification = new SwInterfaceSetFlagsNotification();
+ swInterfaceSetFlagsNotification.deleted = 0;
+ swInterfaceSetFlagsNotification.swIfIndex = IFACE_ID;
+ swInterfaceSetFlagsNotification.adminUpDown = 1;
+ swInterfaceSetFlagsNotification.linkUpDown = 1;
+ callbackArgumentCaptor.getValue().onSwInterfaceSetFlagsNotification(swInterfaceSetFlagsNotification);
+ final ArgumentCaptor<InterfaceStateChange> notificationCaptor =
+ ArgumentCaptor.forClass(InterfaceStateChange.class);
+ verify(collector).onNotification(notificationCaptor.capture());
+
+ assertEquals(IFACE_NAME, notificationCaptor.getValue().getName().getString());
+ assertEquals(InterfaceStatus.Up, notificationCaptor.getValue().getAdminStatus());
+ assertEquals(InterfaceStatus.Up, notificationCaptor.getValue().getOperStatus());
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/util/SubinterfaceUtilsTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/util/SubinterfaceUtilsTest.java
new file mode 100644
index 000000000..fc08fbc59
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/util/SubinterfaceUtilsTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class SubinterfaceUtilsTest {
+
+ @Test
+ public void testGetSubInterfaceName() throws Exception {
+ final String superIfName = "GigabitEthernet0/9/0";
+ final int subIfaceId = 123;
+ final String expectedSubIfaceName = "GigabitEthernet0/9/0.123";
+ assertEquals(expectedSubIfaceName, SubInterfaceUtils.getSubInterfaceName(superIfName, subIfaceId));
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/ArpTerminationTableEntryCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/ArpTerminationTableEntryCustomizerTest.java
new file mode 100644
index 000000000..3377809b7
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/ArpTerminationTableEntryCustomizerTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.vpp;
+
+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.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.BdIpMacAddDel;
+import io.fd.vpp.jvpp.core.dto.BdIpMacAddDelReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+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.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.bridge.domain.attributes.ArpTerminationTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.bridge.domain.attributes.arp.termination.table.ArpTerminationTableEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.bridge.domain.attributes.arp.termination.table.ArpTerminationTableEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.bridge.domain.attributes.arp.termination.table.ArpTerminationTableEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.BridgeDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.bridge.domains.BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.bridge.domains.BridgeDomainKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class ArpTerminationTableEntryCustomizerTest extends WriterCustomizerTest {
+ private static final String BD_CTX_NAME = "bd-test-instance";
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+
+ private static final String BD_NAME = "testBD0";
+ private static final int BD_ID = 111;
+ private static final String IFACE_NAME = "eth0";
+ private static final int IFACE_ID = 123;
+ private ArpTerminationTableEntryCustomizer customizer;
+ private byte[] ipAddressRaw;
+ private byte[] physAddressRaw;
+ private PhysAddress physAddress;
+ private IpAddress ipAddress;
+ private ArpTerminationTableEntry entry;
+ private InstanceIdentifier<ArpTerminationTableEntry> id;
+
+ @Override
+ public void setUp() throws Exception {
+ customizer = new ArpTerminationTableEntryCustomizer(api, new NamingContext("generatedBdName", BD_CTX_NAME));
+
+ ipAddressRaw = new byte[]{1, 2, 3, 4};
+ physAddressRaw = new byte[]{1, 2, 3, 4, 5, 6};
+ physAddress = new PhysAddress("01:02:03:04:05:06");
+
+ ipAddress = new IpAddress(Ipv4AddressNoZone.getDefaultInstance("1.2.3.4"));
+ entry = generateArpEntry(ipAddress, physAddress);
+ id = getArpEntryId(ipAddress, physAddress);
+
+ defineMapping(mappingContext, BD_NAME, BD_ID, BD_CTX_NAME);
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+ }
+
+ private static InstanceIdentifier<ArpTerminationTableEntry> getArpEntryId(final IpAddress ipAddress,
+ final PhysAddress physAddress) {
+ return InstanceIdentifier.create(BridgeDomains.class).child(BridgeDomain.class, new BridgeDomainKey(BD_NAME))
+ .child(ArpTerminationTable.class)
+ .child(ArpTerminationTableEntry.class, new ArpTerminationTableEntryKey(ipAddress, physAddress));
+ }
+
+ private void whenBdIpMacAddDelThenSuccess() {
+ doReturn(future(new BdIpMacAddDelReply())).when(api).bdIpMacAddDel(any(BdIpMacAddDel.class));
+ }
+
+ private void whenBdIpMacAddDelThenFailure() {
+ doReturn(failedFuture()).when(api).bdIpMacAddDel(any(BdIpMacAddDel.class));
+ }
+
+ private BdIpMacAddDel generateBdIpMacAddDelRequest(final byte[] ipAddress, final byte[] macAddress,
+ final byte isAdd) {
+ final BdIpMacAddDel request = new BdIpMacAddDel();
+ request.ipAddress = ipAddress;
+ request.macAddress = macAddress;
+ request.bdId = BD_ID;
+ request.isAdd = isAdd;
+ return request;
+ }
+
+ private ArpTerminationTableEntry generateArpEntry(final IpAddress ipAddress, final PhysAddress physAddress) {
+ final ArpTerminationTableEntryBuilder entry = new ArpTerminationTableEntryBuilder();
+ entry.setKey(new ArpTerminationTableEntryKey(ipAddress, physAddress));
+ entry.setPhysAddress(physAddress);
+ entry.setIpAddress(ipAddress);
+ return entry.build();
+ }
+
+ private void verifyBdIpMacAddDelWasInvoked(final BdIpMacAddDel expected) throws
+ VppInvocationException {
+ ArgumentCaptor<BdIpMacAddDel> argumentCaptor = ArgumentCaptor.forClass(BdIpMacAddDel.class);
+ verify(api).bdIpMacAddDel(argumentCaptor.capture());
+ final BdIpMacAddDel actual = argumentCaptor.getValue();
+ assertArrayEquals(expected.macAddress, actual.macAddress);
+ assertArrayEquals(expected.ipAddress, actual.ipAddress);
+ assertEquals(expected.bdId, actual.bdId);
+ assertEquals(expected.isAdd, actual.isAdd);
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ whenBdIpMacAddDelThenSuccess();
+ customizer.writeCurrentAttributes(id, entry, writeContext);
+ verifyBdIpMacAddDelWasInvoked(generateBdIpMacAddDelRequest(ipAddressRaw, physAddressRaw, (byte) 1));
+ }
+
+ @Test
+ public void testCreateFailed() throws Exception {
+ whenBdIpMacAddDelThenFailure();
+ try {
+ customizer.writeCurrentAttributes(id, entry, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyBdIpMacAddDelWasInvoked(generateBdIpMacAddDelRequest(ipAddressRaw, physAddressRaw, (byte) 1));
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testUpdate() throws Exception {
+ customizer.updateCurrentAttributes(InstanceIdentifier.create(ArpTerminationTableEntry.class),
+ mock(ArpTerminationTableEntry.class),
+ mock(ArpTerminationTableEntry.class), writeContext);
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ whenBdIpMacAddDelThenSuccess();
+ customizer.deleteCurrentAttributes(id, entry, writeContext);
+ verifyBdIpMacAddDelWasInvoked(generateBdIpMacAddDelRequest(ipAddressRaw, physAddressRaw, (byte) 0));
+ }
+
+ @Test
+ public void testDeleteFailed() throws Exception {
+ whenBdIpMacAddDelThenFailure();
+ try {
+ customizer.deleteCurrentAttributes(id, entry, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyBdIpMacAddDelWasInvoked(generateBdIpMacAddDelRequest(ipAddressRaw, physAddressRaw, (byte) 0));
+ return;
+ }
+ fail("WriteFailedException.DeleteFailedException was expected");
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/BridgeDomainCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/BridgeDomainCustomizerTest.java
new file mode 100644
index 000000000..cab5d5c3b
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/BridgeDomainCustomizerTest.java
@@ -0,0 +1,276 @@
+/*
+ * 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.vpp;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+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.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.BridgeDomainAddDel;
+import io.fd.vpp.jvpp.core.dto.BridgeDomainAddDelReply;
+import javax.annotation.Nullable;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.BridgeDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.bridge.domains.BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.bridge.domains.BridgeDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.bridge.domains.BridgeDomainKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+public class BridgeDomainCustomizerTest extends WriterCustomizerTest implements ByteDataTranslator {
+
+ private static final String BD_CTX_NAME = "bd-test-instance";
+ private static final byte ADD_OR_UPDATE_BD = (byte) 1;
+ private BridgeDomainCustomizer customizer;
+
+ @Override
+ public void setUp() throws Exception {
+ customizer = new BridgeDomainCustomizer(api, new NamingContext("generatedBDName", BD_CTX_NAME));
+ }
+
+ @Nullable
+ private static Boolean intToBoolean(final int value) {
+ if (value == 0) {
+ return Boolean.FALSE;
+ }
+ if (value == 1) {
+ return Boolean.TRUE;
+ }
+ return null;
+ }
+
+ private static KeyedInstanceIdentifier<BridgeDomain, BridgeDomainKey> bdIdentifierForName(
+ final String bdName) {
+ return InstanceIdentifier.create(BridgeDomains.class).child(BridgeDomain.class, new BridgeDomainKey(bdName));
+ }
+
+ private BridgeDomain generateBridgeDomain(final String bdName) {
+ final byte arpTerm = 0;
+ final byte flood = 1;
+ final byte forward = 0;
+ final byte learn = 1;
+ final byte uuf = 0;
+ return generateBridgeDomain(bdName, arpTerm, flood, forward, learn, uuf);
+ }
+
+ private BridgeDomain generateBridgeDomain(final String bdName, final int arpTerm, final int flood,
+ final int forward, final int learn, final int uuf) {
+ return new BridgeDomainBuilder()
+ .setName(bdName)
+ .setArpTermination(intToBoolean(arpTerm))
+ .setFlood(intToBoolean(flood))
+ .setForward(intToBoolean(forward))
+ .setLearn(intToBoolean(learn))
+ .setUnknownUnicastFlood(intToBoolean(uuf))
+ .build();
+ }
+
+ private void verifyBridgeDomainAddOrUpdateWasInvoked(final BridgeDomain bd, final int bdId)
+ throws VppInvocationException {
+ final BridgeDomainAddDel expected = new BridgeDomainAddDel();
+ expected.arpTerm = booleanToByte(bd.isArpTermination());
+ expected.flood = booleanToByte(bd.isFlood());
+ expected.forward = booleanToByte(bd.isForward());
+ expected.learn = booleanToByte(bd.isLearn());
+ expected.uuFlood = booleanToByte(bd.isUnknownUnicastFlood());
+ expected.isAdd = ADD_OR_UPDATE_BD;
+ expected.bdId = bdId;
+ verify(api).bridgeDomainAddDel(expected);
+ }
+
+ private void verifyBridgeDomainDeleteWasInvoked(final int bdId) throws VppInvocationException {
+ final BridgeDomainAddDel expected = new BridgeDomainAddDel();
+ expected.bdId = bdId;
+ verify(api).bridgeDomainAddDel(expected);
+ }
+
+ private void whenBridgeDomainAddDelThenSuccess() {
+ when(api.bridgeDomainAddDel(any(BridgeDomainAddDel.class))).thenReturn(future(new BridgeDomainAddDelReply()));
+ }
+
+ private void whenBridgeDomainAddDelThenFailure() {
+ doReturn(failedFuture()).when(api).bridgeDomainAddDel(any(BridgeDomainAddDel.class));
+ }
+
+ @Test
+ public void testAddBridgeDomain() throws Exception {
+ final int bdId = 1;
+ final String bdName = "bd1";
+ final BridgeDomain bd = generateBridgeDomain(bdName);
+ noMappingDefined(mappingContext, bdName, BD_CTX_NAME);
+
+ whenBridgeDomainAddDelThenSuccess();
+
+ customizer.writeCurrentAttributes(bdIdentifierForName(bdName), bd, writeContext);
+
+ verifyBridgeDomainAddOrUpdateWasInvoked(bd, bdId);
+ verify(mappingContext).put(mappingIid(bdName, BD_CTX_NAME), mapping(bdName, bdId).get());
+ }
+
+ @Test
+ public void testAddBridgeDomainPresentInBdContext() throws Exception {
+ final int bdId = 1;
+ final String bdName = "bd1";
+ final BridgeDomain bd = generateBridgeDomain(bdName);
+ defineMapping(mappingContext, bdName, bdId, BD_CTX_NAME);
+
+ whenBridgeDomainAddDelThenSuccess();
+
+ customizer.writeCurrentAttributes(bdIdentifierForName(bdName), bd, writeContext);
+
+ verifyBridgeDomainAddOrUpdateWasInvoked(bd, bdId);
+ verify(mappingContext).put(mappingIid(bdName, BD_CTX_NAME), mapping(bdName, bdId).get());
+ }
+
+ @Test
+ public void testAddBridgeDomainFailed() throws Exception {
+ final int bdId = 1;
+ final String bdName = "bd1";
+ final BridgeDomain bd = generateBridgeDomain(bdName);
+ noMappingDefined(mappingContext, bdName, BD_CTX_NAME);
+
+ whenBridgeDomainAddDelThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(bdIdentifierForName(bdName), bd, writeContext);
+ } catch (WriteFailedException e) {
+ verifyBridgeDomainAddOrUpdateWasInvoked(bd, bdId);
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test
+ public void testDeleteBridgeDomain() throws Exception {
+ final int bdId = 1;
+ final String bdName = "bd1";
+ final BridgeDomain bd = generateBridgeDomain(bdName);
+ defineMapping(mappingContext, bdName, bdId, BD_CTX_NAME);
+
+ whenBridgeDomainAddDelThenSuccess();
+
+ customizer.deleteCurrentAttributes(bdIdentifierForName(bdName), bd, writeContext);
+
+ verifyBridgeDomainDeleteWasInvoked(bdId);
+ }
+
+ @Test
+ public void testDeleteUnknownBridgeDomain() throws Exception {
+ final String bdName = "bd1";
+ final BridgeDomain bd = generateBridgeDomain("bd1");
+ noMappingDefined(mappingContext, bdName, BD_CTX_NAME);
+
+ try {
+ customizer.deleteCurrentAttributes(bdIdentifierForName(bdName), bd, writeContext);
+ } catch (IllegalArgumentException e) {
+ verify(api, never()).bridgeDomainAddDel(any(BridgeDomainAddDel.class));
+ return;
+ }
+ fail("IllegalArgumentException was expected");
+ }
+
+ @Test
+ public void testDeleteBridgeDomainFailed() throws Exception {
+ final int bdId = 1;
+ final String bdName = "bd1";
+ final BridgeDomain bd = generateBridgeDomain(bdName);
+ defineMapping(mappingContext, bdName, bdId, BD_CTX_NAME);
+
+ whenBridgeDomainAddDelThenFailure();
+
+ try {
+ customizer.deleteCurrentAttributes(bdIdentifierForName(bdName), bd, writeContext);
+ } catch (WriteFailedException e) {
+ verifyBridgeDomainDeleteWasInvoked(bdId);
+ return;
+ }
+
+ fail("WriteFailedException.DeleteFailedException was expected");
+ }
+
+ @Test
+ public void testUpdateBridgeDomain() throws Exception {
+ final int bdId = 1;
+ final String bdName = "bd1";
+ defineMapping(mappingContext, bdName, bdId, BD_CTX_NAME);
+
+ final byte arpTermBefore = 1;
+ final byte floodBefore = 1;
+ final byte forwardBefore = 0;
+ final byte learnBefore = 1;
+ final byte uufBefore = 0;
+
+ final BridgeDomain dataBefore =
+ generateBridgeDomain(bdName, arpTermBefore, floodBefore, forwardBefore, learnBefore, uufBefore);
+ final BridgeDomain dataAfter =
+ generateBridgeDomain(bdName, arpTermBefore ^ 1, floodBefore ^ 1, forwardBefore ^ 1, learnBefore ^ 1,
+ uufBefore ^ 1);
+
+ whenBridgeDomainAddDelThenSuccess();
+
+ customizer
+ .updateCurrentAttributes(bdIdentifierForName(bdName), dataBefore, dataAfter,
+ writeContext);
+ verifyBridgeDomainAddOrUpdateWasInvoked(dataAfter, bdId);
+ }
+
+ @Test
+ public void testUpdateUnknownBridgeDomain() throws Exception {
+ final String bdName = "bd1";
+ final BridgeDomain bdBefore = generateBridgeDomain(bdName, 0, 1, 0, 1, 0);
+ final BridgeDomain bdAfter = generateBridgeDomain(bdName, 1, 1, 0, 1, 0);
+ noMappingDefined(mappingContext, bdName, BD_CTX_NAME);
+
+ try {
+ customizer
+ .updateCurrentAttributes(bdIdentifierForName(bdName), bdBefore, bdAfter,
+ writeContext);
+ } catch (IllegalArgumentException e) {
+ verify(api, never()).bridgeDomainAddDel(any(BridgeDomainAddDel.class));
+ return;
+ }
+ fail("IllegalArgumentException was expected");
+ }
+
+ @Test
+ public void testUpdateBridgeDomainFailed() throws Exception {
+ final int bdId = 1;
+ final String bdName = "bd1";
+ final BridgeDomain bdBefore = generateBridgeDomain(bdName, 0, 1, 0, 1, 0);
+ final BridgeDomain bdAfter = generateBridgeDomain(bdName, 1, 1, 0, 1, 0);
+ defineMapping(mappingContext, bdName, bdId, BD_CTX_NAME);
+
+ whenBridgeDomainAddDelThenFailure();
+
+ try {
+ customizer.updateCurrentAttributes(bdIdentifierForName(bdName), bdBefore, bdAfter, writeContext);
+ } catch (WriteFailedException e) {
+ verifyBridgeDomainAddOrUpdateWasInvoked(bdAfter, bdId);
+ return;
+ }
+ fail("IllegalStateException was expected");
+ }
+
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/L2FibEntryCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/L2FibEntryCustomizerTest.java
new file mode 100644
index 000000000..6bb5bc6cf
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/L2FibEntryCustomizerTest.java
@@ -0,0 +1,190 @@
+/*
+ * 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.vpp;
+
+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.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.L2FibAddDel;
+import io.fd.vpp.jvpp.core.dto.L2FibAddDelReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.L2FibFilter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.L2FibTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.l2.fib.table.L2FibEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.l2.fib.table.L2FibEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.l2.fib.table.L2FibEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.BridgeDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.bridge.domains.BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.bridge.domains.BridgeDomainKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class L2FibEntryCustomizerTest extends WriterCustomizerTest {
+ private static final String BD_CTX_NAME = "bd-test-instance";
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+
+ private static final String BD_NAME = "testBD0";
+ private static final int BD_ID = 111;
+ private static final String IFACE_NAME = "eth0";
+ private static final int IFACE_ID = 123;
+
+ private L2FibEntryCustomizer customizer;
+
+ @Override
+ public void setUp() throws Exception {
+ defineMapping(mappingContext, BD_NAME, BD_ID, BD_CTX_NAME);
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+
+ customizer = new L2FibEntryCustomizer(
+ api,
+ new NamingContext("generatedBdName", BD_CTX_NAME),
+ new NamingContext("generatedIfaceName", IFC_CTX_NAME));
+ }
+
+ private static InstanceIdentifier<L2FibEntry> getL2FibEntryId(final PhysAddress address) {
+ return InstanceIdentifier.create(BridgeDomains.class).child(BridgeDomain.class, new BridgeDomainKey(BD_NAME))
+ .child(L2FibTable.class).child(L2FibEntry.class, new L2FibEntryKey(address));
+ }
+
+ private void whenL2FibAddDelThenSuccess() {
+ doReturn(future(new L2FibAddDelReply())).when(api).l2FibAddDel(any(L2FibAddDel.class));
+ }
+
+ private void whenL2FibAddDelThenFailure() {
+ doReturn(failedFuture()).when(api).l2FibAddDel(any(L2FibAddDel.class));
+ }
+
+ private L2FibAddDel generateL2FibAddDelRequest(final long mac, final byte isAdd) {
+ final L2FibAddDel request = new L2FibAddDel();
+ request.mac = mac;
+ request.bdId = BD_ID;
+ request.swIfIndex = IFACE_ID;
+ request.isAdd = isAdd;
+ if (isAdd == 1) {
+ request.staticMac = 1;
+ request.filterMac = 1;
+ }
+ return request;
+ }
+
+ private L2FibEntry generateL2FibEntry(final PhysAddress address) {
+ final L2FibEntryBuilder entry = new L2FibEntryBuilder();
+ entry.setKey(new L2FibEntryKey(address));
+ entry.setPhysAddress(address);
+ entry.setStaticConfig(true);
+ entry.setBridgedVirtualInterface(false);
+ entry.setAction(L2FibFilter.class);
+ entry.setOutgoingInterface(IFACE_NAME);
+ return entry.build();
+ }
+
+ private void verifyL2FibAddDelWasInvoked(final L2FibAddDel expected) throws
+ VppInvocationException {
+ ArgumentCaptor<L2FibAddDel> argumentCaptor = ArgumentCaptor.forClass(L2FibAddDel.class);
+ verify(api).l2FibAddDel(argumentCaptor.capture());
+ final L2FibAddDel actual = argumentCaptor.getValue();
+ assertEquals(expected.mac, actual.mac);
+ assertEquals(expected.bdId, actual.bdId);
+ assertEquals(expected.swIfIndex, actual.swIfIndex);
+ assertEquals(expected.isAdd, actual.isAdd);
+ assertEquals(expected.staticMac, actual.staticMac);
+ assertEquals(expected.filterMac, actual.filterMac);
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ final long address_vpp = 0x0102030405060000L;
+ final PhysAddress address = new PhysAddress("01:02:03:04:05:06");
+ final L2FibEntry entry = generateL2FibEntry(address);
+ final InstanceIdentifier<L2FibEntry> id = getL2FibEntryId(address);
+
+ whenL2FibAddDelThenSuccess();
+
+ customizer.writeCurrentAttributes(id, entry, writeContext);
+
+ verifyL2FibAddDelWasInvoked(generateL2FibAddDelRequest(address_vpp, (byte) 1));
+ }
+
+ @Test
+ public void testCreateFailed() throws Exception {
+ final long address_vpp = 0x1122334455660000L;
+ final PhysAddress address = new PhysAddress("11:22:33:44:55:66");
+ final L2FibEntry entry = generateL2FibEntry(address);
+ final InstanceIdentifier<L2FibEntry> id = getL2FibEntryId(address);
+
+ whenL2FibAddDelThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(id, entry, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyL2FibAddDelWasInvoked(generateL2FibAddDelRequest(address_vpp, (byte) 1));
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testUpdate() throws Exception {
+ customizer.updateCurrentAttributes(InstanceIdentifier.create(L2FibEntry.class), mock(L2FibEntry.class),
+ mock(L2FibEntry.class), writeContext);
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ final long address_vpp = 0x1122334455660000L;
+ final PhysAddress address = new PhysAddress("11:22:33:44:55:66");
+ final L2FibEntry entry = generateL2FibEntry(address);
+ final InstanceIdentifier<L2FibEntry> id = getL2FibEntryId(address);
+
+ whenL2FibAddDelThenSuccess();
+
+ customizer.deleteCurrentAttributes(id, entry, writeContext);
+
+ verifyL2FibAddDelWasInvoked(generateL2FibAddDelRequest(address_vpp, (byte) 0));
+ }
+
+ @Test
+ public void testDeleteFailed() throws Exception {
+ final long address_vpp = 0x0102030405060000L;
+ final PhysAddress address = new PhysAddress("01:02:03:04:05:06");
+ final L2FibEntry entry = generateL2FibEntry(address);
+ final InstanceIdentifier<L2FibEntry> id = getL2FibEntryId(address);
+
+ whenL2FibAddDelThenFailure();
+
+ try {
+ customizer.deleteCurrentAttributes(id, entry, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyL2FibAddDelWasInvoked(generateL2FibAddDelRequest(address_vpp, (byte) 0));
+ return;
+ }
+ fail("WriteFailedException.DeleteFailedException was expected");
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifySessionReaderTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifySessionReaderTest.java
new file mode 100644
index 000000000..f8645da4d
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifySessionReaderTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.v3po.vppclassifier;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppClassifierState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.classify.table.base.attributes.ClassifySession;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.classify.table.base.attributes.ClassifySessionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.classify.table.base.attributes.ClassifySessionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.vpp.classifier.state.ClassifyTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.vpp.classifier.state.ClassifyTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.vpp.classifier.state.ClassifyTableKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.ClassifySessionDetails;
+import io.fd.vpp.jvpp.core.dto.ClassifySessionDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.ClassifySessionDump;
+
+public class ClassifySessionReaderTest extends
+ ListReaderCustomizerTest<ClassifySession, ClassifySessionKey, ClassifySessionBuilder> {
+
+ private static final String MATCH_1 = "00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00";
+ private static final String MATCH_2 = "00:00:00:00:00:00:01:02:03:04:05:07:00:00:00:00";
+
+ private static final int TABLE_INDEX = 1;
+ private static final String TABLE_NAME = "table1";
+
+ @Mock
+ private VppClassifierContextManager classifierContext;
+
+ public ClassifySessionReaderTest() {
+ super(ClassifySession.class, ClassifyTableBuilder.class);
+ }
+
+ @Override
+ protected ReaderCustomizer<ClassifySession, ClassifySessionBuilder> initCustomizer() {
+ return new ClassifySessionReader(api, classifierContext);
+ }
+
+ private static InstanceIdentifier<ClassifySession> getClassifySessionId(final String tableName,
+ final String match) {
+ return InstanceIdentifier.create(VppClassifierState.class)
+ .child(ClassifyTable.class, new ClassifyTableKey(tableName))
+ .child(ClassifySession.class, new ClassifySessionKey(new HexString(match)));
+ }
+
+ @Test
+ public void testReadWithCache() throws ReadFailedException {
+ final InstanceIdentifier<ClassifySession> id = getClassifySessionId(TABLE_NAME, MATCH_1);
+ final ClassifySessionBuilder builder = mock(ClassifySessionBuilder.class);
+ final ModificationCache cache = new ModificationCache();
+ final ClassifySessionDetailsReplyDump dump = new ClassifySessionDetailsReplyDump();
+ final ClassifySessionDetails details = new ClassifySessionDetails();
+ details.match =
+ new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, 0x00, 0x00, 0x00, 0x00};
+ dump.classifySessionDetails = Collections.singletonList(details);
+ cache.put(ClassifySessionReader.CACHE_KEY + id.firstKeyOf(ClassifyTable.class), dump);
+ when(ctx.getModificationCache()).thenReturn(cache);
+
+ getCustomizer().readCurrentAttributes(id, builder, ctx);
+ }
+
+ @Test
+ public void testGetAllIds() throws ReadFailedException {
+ final InstanceIdentifier<ClassifySession> id = getClassifySessionId(TABLE_NAME, MATCH_1);
+ final ClassifySessionDetailsReplyDump dump = new ClassifySessionDetailsReplyDump();
+ final ClassifySessionDetails details1 = new ClassifySessionDetails();
+ details1.match =
+ new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, 0x00, 0x00, 0x00, 0x00};
+ final ClassifySessionDetails details2 = new ClassifySessionDetails();
+ details2.match =
+ new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x07, 0x00, 0x00, 0x00, 0x00};
+ dump.classifySessionDetails = Arrays.asList(details1, details2);
+ doReturn(future(dump)).when(api).classifySessionDump(any(ClassifySessionDump.class));
+
+ when(classifierContext.containsTable(TABLE_NAME, mappingContext)).thenReturn(true);
+ when(classifierContext.getTableIndex(TABLE_NAME, mappingContext)).thenReturn(TABLE_INDEX);
+
+ final List<ClassifySessionKey> allIds = getCustomizer().getAllIds(id, ctx);
+ assertEquals(2, allIds.size());
+ assertEquals(MATCH_1, allIds.get(0).getMatch().getValue());
+ assertEquals(MATCH_2, allIds.get(1).getMatch().getValue());
+ }
+
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifySessionWriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifySessionWriterTest.java
new file mode 100644
index 000000000..654900c81
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifySessionWriterTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.vppclassifier;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSessionReply;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.OpaqueIndex;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.PacketHandlingAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppClassifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppNodeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.classify.table.base.attributes.ClassifySession;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.classify.table.base.attributes.ClassifySessionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.classify.table.base.attributes.ClassifySessionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.vpp.classifier.ClassifyTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.vpp.classifier.ClassifyTableKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class ClassifySessionWriterTest extends WriterCustomizerTest {
+
+ private static final int TABLE_INDEX = 123;
+ private static final String TABLE_NAME = "table123";
+
+ @Mock
+ private VppClassifierContextManager classfierContext;
+
+ private ClassifySessionWriter customizer;
+ private static final int SESSION_INDEX = 456;
+
+ @Override
+ public void setUp() throws Exception {
+ customizer = new ClassifySessionWriter(api, classfierContext);
+
+ when(classfierContext.containsTable(TABLE_NAME, mappingContext)).thenReturn(true);
+ when(classfierContext.getTableIndex(TABLE_NAME, mappingContext)).thenReturn(TABLE_INDEX);
+
+ final ClassifyTable table = mock(ClassifyTable.class);
+ when(table.getClassifierNode()).thenReturn(new VppNodeName("ip4-classifier"));
+ when(writeContext.readAfter(any())).thenReturn(Optional.of(table));
+ when(writeContext.readBefore(any())).thenReturn(Optional.of(table));
+ }
+
+ private static ClassifySession generateClassifySession(final long opaqueIndex, final String match) {
+ final ClassifySessionBuilder builder = new ClassifySessionBuilder();
+ builder.setOpaqueIndex(new OpaqueIndex(opaqueIndex));
+ builder.setHitNext(new VppNode(PacketHandlingAction.Deny));
+ builder.setAdvance(123);
+ builder.setMatch(new HexString(match));
+ return builder.build();
+ }
+
+ private static InstanceIdentifier<ClassifySession> getClassifySessionId(final String tableName,
+ final String match) {
+ return InstanceIdentifier.create(VppClassifier.class)
+ .child(ClassifyTable.class, new ClassifyTableKey(tableName))
+ .child(ClassifySession.class, new ClassifySessionKey(new HexString(match)));
+ }
+
+ private void whenClassifyAddDelSessionThenSuccess() {
+ doReturn(future(new ClassifyAddDelSessionReply())).when(api)
+ .classifyAddDelSession(any(ClassifyAddDelSession.class));
+ }
+
+ private void whenClassifyAddDelSessionThenFailure() {
+ doReturn(failedFuture()).when(api).classifyAddDelSession(any(ClassifyAddDelSession.class));
+ }
+
+ private static ClassifyAddDelSession generateClassifyAddDelSession(final byte isAdd, final int tableIndex,
+ final int sessionIndex) {
+ final ClassifyAddDelSession request = new ClassifyAddDelSession();
+ request.isAdd = isAdd;
+ request.tableIndex = tableIndex;
+ request.opaqueIndex = sessionIndex;
+ request.hitNextIndex = 0;
+ request.advance = 123;
+ request.match =
+ new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, 0x00, 0x00, 0x00, 0x00};
+ return request;
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ final String match = "00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00";
+ final ClassifySession classifySession = generateClassifySession(SESSION_INDEX, match);
+ final InstanceIdentifier<ClassifySession> id = getClassifySessionId(TABLE_NAME, match);
+
+ whenClassifyAddDelSessionThenSuccess();
+
+ customizer.writeCurrentAttributes(id, classifySession, writeContext);
+
+ verify(api).classifyAddDelSession(generateClassifyAddDelSession((byte) 1, TABLE_INDEX, SESSION_INDEX));
+ }
+
+ @Test
+ public void testCreateFailed() throws Exception {
+ final String match = "00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00";
+ final ClassifySession classifySession = generateClassifySession(SESSION_INDEX, match);
+ final InstanceIdentifier<ClassifySession> id = getClassifySessionId(TABLE_NAME, match);
+
+ whenClassifyAddDelSessionThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(id, classifySession, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).classifyAddDelSession(generateClassifyAddDelSession((byte) 1, TABLE_INDEX, SESSION_INDEX));
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testUpdate() throws Exception {
+ customizer.updateCurrentAttributes(null, null, null, writeContext);
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ final String match = "00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00";
+ final ClassifySession classifySession = generateClassifySession(SESSION_INDEX, match);
+ final InstanceIdentifier<ClassifySession> id = getClassifySessionId(TABLE_NAME, match);
+
+ whenClassifyAddDelSessionThenSuccess();
+
+ customizer.deleteCurrentAttributes(id, classifySession, writeContext);
+
+ verify(api).classifyAddDelSession(generateClassifyAddDelSession((byte) 0, TABLE_INDEX, SESSION_INDEX));
+ }
+
+ @Test
+ public void testDeleteFailed() throws Exception {
+ final String match = "00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00";
+ final ClassifySession classifySession = generateClassifySession(SESSION_INDEX, match);
+ final InstanceIdentifier<ClassifySession> id = getClassifySessionId(TABLE_NAME, match);
+
+ whenClassifyAddDelSessionThenFailure();
+
+ try {
+ customizer.deleteCurrentAttributes(id, classifySession, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).classifyAddDelSession(generateClassifyAddDelSession((byte) 0, TABLE_INDEX, SESSION_INDEX));
+ return;
+ }
+ fail("WriteFailedException.DeleteFailedException was expected");
+
+ customizer.deleteCurrentAttributes(id, classifySession, writeContext);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifyTableReaderTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifyTableReaderTest.java
new file mode 100644
index 000000000..70200743f
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifyTableReaderTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.vppclassifier;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.PacketHandlingAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppClassifierState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppClassifierStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.vpp.classifier.state.ClassifyTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.vpp.classifier.state.ClassifyTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.vpp.classifier.state.ClassifyTableKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableIds;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableIdsReply;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableInfo;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableInfoReply;
+
+public class ClassifyTableReaderTest extends
+ ListReaderCustomizerTest<ClassifyTable, ClassifyTableKey, ClassifyTableBuilder> {
+
+ private static final int TABLE_INDEX_1 = 1;
+ private static final String TABLE_NAME_1 = "table1";
+ private static final int TABLE_INDEX_2 = 2;
+ private static final String TABLE_NAME_2 = "table2";
+
+ @Mock
+ private VppClassifierContextManager classifierContext;
+
+ public ClassifyTableReaderTest() {
+ super(ClassifyTable.class, VppClassifierStateBuilder.class);
+ }
+
+ @Override
+ protected ReaderCustomizer<ClassifyTable, ClassifyTableBuilder> initCustomizer() {
+ return new ClassifyTableReader(api, classifierContext);
+ }
+
+ private static InstanceIdentifier<ClassifyTable> getClassifyTableId(final String name) {
+ return InstanceIdentifier.create(VppClassifierState.class)
+ .child(ClassifyTable.class, new ClassifyTableKey(name));
+ }
+
+ private static ClassifyTableInfoReply generateClassifyTableInfoReply() {
+ final ClassifyTableInfoReply reply = new ClassifyTableInfoReply();
+ reply.tableId = TABLE_INDEX_1;
+ reply.nbuckets = 2;
+ reply.skipNVectors = 0;
+ reply.matchNVectors = 1;
+ reply.nextTableIndex = ~0;
+ reply.missNextIndex = ~0;
+ reply.mask =
+ new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, 0x00, 0x00, 0x00, 0x00};
+ return reply;
+ }
+
+ private void verifyClasifyTableRead(final ClassifyTableBuilder builder) {
+ verify(builder).setName(TABLE_NAME_1);
+ verify(builder).setNbuckets(2L);
+ verify(builder, times(0)).setNextTable(anyString());
+ verify(builder).setMissNext(new VppNode(PacketHandlingAction.Permit));
+ verify(builder).setMask(new HexString("00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00"));
+ verify(builder).setActiveSessions(0L);
+ }
+
+ @Test
+ public void testRead() throws ReadFailedException {
+ doReturn(future(generateClassifyTableInfoReply())).when(api).classifyTableInfo(any(ClassifyTableInfo.class));
+
+ when(classifierContext.containsTable(TABLE_NAME_1, mappingContext)).thenReturn(true);
+ when(classifierContext.getTableIndex(TABLE_NAME_1, mappingContext)).thenReturn(TABLE_INDEX_1);
+ when(classifierContext.getTableBaseNode(TABLE_NAME_1, mappingContext)).thenReturn(Optional.absent());
+
+ final ClassifyTableBuilder builder = mock(ClassifyTableBuilder.class);
+ getCustomizer().readCurrentAttributes(getClassifyTableId(TABLE_NAME_1), builder, ctx);
+
+ verifyClasifyTableRead(builder);
+ }
+
+ @Test
+ public void testGetAllIds() throws ReadFailedException {
+ final ClassifyTableIdsReply reply = new ClassifyTableIdsReply();
+ reply.ids = new int[] {1, 2};
+ doReturn(future(reply)).when(api).classifyTableIds(any(ClassifyTableIds.class));
+
+ when(classifierContext.getTableName(TABLE_INDEX_1, mappingContext)).thenReturn(TABLE_NAME_1);
+ when(classifierContext.getTableName(TABLE_INDEX_2, mappingContext)).thenReturn(TABLE_NAME_2);
+
+ final List<ClassifyTableKey> allIds = getCustomizer().getAllIds(getClassifyTableId(TABLE_NAME_1), ctx);
+
+ assertEquals(reply.ids.length, allIds.size());
+ assertEquals(TABLE_NAME_1, allIds.get(0).getName());
+ assertEquals(TABLE_NAME_2, allIds.get(1).getName());
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifyTableWriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifyTableWriterTest.java
new file mode 100644
index 000000000..a4da54631
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/ClassifyTableWriterTest.java
@@ -0,0 +1,181 @@
+/*
+ * 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.vppclassifier;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+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.honeycomb.translate.write.WriteFailedException;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.PacketHandlingAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppClassifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppNodeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.vpp.classifier.ClassifyTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.vpp.classifier.ClassifyTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.vpp.classifier.ClassifyTableKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class ClassifyTableWriterTest extends WriterCustomizerTest {
+
+ private static final int TABLE_INDEX = 123;
+ private static final String TABLE_NAME = "table123";
+
+ @Mock
+ private VppClassifierContextManager classifierContext;
+
+ private ClassifyTableWriter customizer;
+
+ @Override
+ public void setUp() throws Exception {
+ customizer = new ClassifyTableWriter(api, classifierContext);
+ }
+
+ private static ClassifyTable generateClassifyTable(final String name) {
+ final ClassifyTableBuilder builder = new ClassifyTableBuilder();
+ builder.setName(name);
+ builder.setClassifierNode(new VppNodeName("ip4-classifier"));
+ builder.setKey(new ClassifyTableKey(name));
+ builder.setSkipNVectors(0L);
+ builder.setNbuckets(2L);
+ builder.setMemorySize(2L << 20);
+ builder.setMissNext(new VppNode(PacketHandlingAction.Permit));
+ builder.setMask(new HexString("00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00"));
+ return builder.build();
+ }
+
+ private static InstanceIdentifier<ClassifyTable> getClassifyTableId(final String name) {
+ return InstanceIdentifier.create(VppClassifier.class)
+ .child(ClassifyTable.class, new ClassifyTableKey(name));
+ }
+
+ private void whenClassifyAddDelTableThenSuccess() {
+ final ClassifyAddDelTableReply reply = new ClassifyAddDelTableReply();
+ reply.newTableIndex = TABLE_INDEX;
+ doReturn(future(reply)).when(api).classifyAddDelTable(any(ClassifyAddDelTable.class));
+ }
+
+ private void whenClassifyAddDelTableThenFailure() {
+ doReturn(failedFuture()).when(api).classifyAddDelTable(any(ClassifyAddDelTable.class));
+ }
+
+ private static ClassifyAddDelTable generateClassifyAddDelTable(final byte isAdd) {
+ return generateClassifyAddDelTable(isAdd, -1);
+ }
+
+ private static ClassifyAddDelTable generateClassifyAddDelTable(final byte isAdd, final int tableIndex) {
+ final ClassifyAddDelTable request = new ClassifyAddDelTable();
+ request.isAdd = isAdd;
+ request.tableIndex = tableIndex;
+ request.nbuckets = 2;
+ request.memorySize = 2 << 20;
+ request.skipNVectors = 0;
+ request.matchNVectors = 1;
+ request.nextTableIndex = ~0;
+ request.missNextIndex = ~0;
+ request.mask =
+ new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, 0x00, 0x00, 0x00, 0x00};
+ return request;
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ final ClassifyTable classifyTable = generateClassifyTable(TABLE_NAME);
+ final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME);
+
+ whenClassifyAddDelTableThenSuccess();
+
+ customizer.writeCurrentAttributes(id, classifyTable, writeContext);
+
+ verify(api).classifyAddDelTable(generateClassifyAddDelTable((byte) 1));
+ verify(classifierContext)
+ .addTable(TABLE_INDEX, classifyTable.getName(), classifyTable.getClassifierNode(), mappingContext);
+ }
+
+ @Test
+ public void testCreateFailed() throws Exception {
+ final ClassifyTable classifyTable = generateClassifyTable(TABLE_NAME);
+ final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME);
+
+ whenClassifyAddDelTableThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(id, classifyTable, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).classifyAddDelTable(generateClassifyAddDelTable((byte) 1));
+ verify(classifierContext, times(0))
+ .addTable(TABLE_INDEX, classifyTable.getName(), classifyTable.getClassifierNode(), mappingContext);
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ final ClassifyTable classifyTable = generateClassifyTable(TABLE_NAME);
+ final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME);
+
+ when(classifierContext.containsTable(TABLE_NAME, mappingContext)).thenReturn(true);
+ when(classifierContext.getTableIndex(TABLE_NAME, mappingContext)).thenReturn(TABLE_INDEX);
+ whenClassifyAddDelTableThenSuccess();
+
+ customizer.deleteCurrentAttributes(id, classifyTable, writeContext);
+
+ verify(api).classifyAddDelTable(generateClassifyAddDelTable((byte) 0, TABLE_INDEX));
+ }
+
+ @Test
+ public void testDeleteFailed() throws Exception {
+ final ClassifyTable classifyTable = generateClassifyTable(TABLE_NAME);
+ final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME);
+
+ when(classifierContext.containsTable(TABLE_NAME, mappingContext)).thenReturn(true);
+ when(classifierContext.getTableIndex(TABLE_NAME, mappingContext)).thenReturn(TABLE_INDEX);
+ whenClassifyAddDelTableThenFailure();
+
+ try {
+ customizer.deleteCurrentAttributes(id, classifyTable, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).classifyAddDelTable(generateClassifyAddDelTable((byte) 0, TABLE_INDEX));
+ return;
+ }
+ fail("WriteFailedException.DeleteFailedException was expected");
+
+ customizer.deleteCurrentAttributes(id, classifyTable, writeContext);
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testUpdate() throws Exception {
+ final ClassifyTable classifyTableBefore = generateClassifyTable(TABLE_NAME);
+ final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME);
+ customizer.updateCurrentAttributes(id, classifyTableBefore, new ClassifyTableBuilder().build(), writeContext);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/VppClassifierContextManagerImplTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/VppClassifierContextManagerImplTest.java
new file mode 100644
index 000000000..c334fe84f
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppclassifier/VppClassifierContextManagerImplTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.vppclassifier;
+
+import static io.fd.hc2vpp.v3po.vppclassifier.VppClassifierContextManagerImpl.VPP_CLASSIFIER_CONTEXT_IID;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.translate.MappingContext;
+import java.util.Arrays;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev161214.VppNodeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextKey;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+public class VppClassifierContextManagerImplTest {
+
+ private static final int TABLE_ID_0 = 0;
+ private static final String TABLE_NAME_0 = "table0";
+ private static final KeyedInstanceIdentifier<ClassifyTableContext, ClassifyTableContextKey> TABLE_IID_0 =
+ VPP_CLASSIFIER_CONTEXT_IID.child(ClassifyTableContext.class, new ClassifyTableContextKey(TABLE_NAME_0));
+
+ private static final int TABLE_ID_1 = 1;
+ private static final String TABLE_NAME_1 = "table1";
+
+ private VppClassifierContextManagerImpl vppClassfierContext;
+
+ @Mock
+ private MappingContext ctx;
+
+ @Before
+ public void setUp() throws Exception {
+ initMocks(this);
+ vppClassfierContext = new VppClassifierContextManagerImpl("classify-table-");
+ }
+
+ @Test
+ public void testAddTable() throws Exception {
+ final String classfierNodeName = "node123";
+ vppClassfierContext.addTable(TABLE_ID_0, TABLE_NAME_0, new VppNodeName(classfierNodeName), ctx);
+ verify(ctx).put(TABLE_IID_0, table(TABLE_ID_0, TABLE_NAME_0, classfierNodeName));
+ }
+
+ @Test
+ public void testContainsTable() throws Exception {
+ when(ctx.read(TABLE_IID_0)).thenReturn(Optional.absent());
+ assertFalse(vppClassfierContext.containsTable(TABLE_NAME_0, ctx));
+ }
+
+ @Test
+ public void testGetTableIndex() throws Exception {
+ when(ctx.read(TABLE_IID_0)).thenReturn(Optional.of(table(TABLE_ID_0, TABLE_NAME_0)));
+ assertEquals(TABLE_ID_0, vppClassfierContext.getTableIndex(TABLE_NAME_0, ctx));
+ }
+
+ @Test
+ public void testGetTableName() throws Exception {
+ when(ctx.read(VPP_CLASSIFIER_CONTEXT_IID))
+ .thenReturn(Optional.of(context(table(TABLE_ID_0, TABLE_NAME_0), table(TABLE_ID_1, TABLE_NAME_1))));
+ assertEquals(TABLE_NAME_0, (vppClassfierContext.getTableName(TABLE_ID_0, ctx)));
+ }
+
+ @Test
+ public void testGetTableBaseNode() throws Exception {
+ final String classfierNodeName = "node123";
+ when(ctx.read(TABLE_IID_0)).thenReturn(Optional.of(table(TABLE_ID_0, TABLE_NAME_0, classfierNodeName)));
+ vppClassfierContext.getTableBaseNode(TABLE_NAME_0, ctx);
+ assertEquals(Optional.of(classfierNodeName), (vppClassfierContext.getTableBaseNode(TABLE_NAME_0, ctx)));
+ }
+
+ @Test
+ public void testRemoveTable() throws Exception {
+ vppClassfierContext.removeTable(TABLE_NAME_0, ctx);
+ verify(ctx).delete(TABLE_IID_0);
+ }
+
+ @Test
+ public void testAddNodeName() throws Exception {
+ final String nodeName = "node123";
+ final int nodeIndex = 1;
+
+ vppClassfierContext.addNodeName(TABLE_NAME_0, nodeIndex, nodeName, ctx);
+ verify(ctx).put(
+ TABLE_IID_0.child(NodeContext.class, new NodeContextKey(nodeName)),
+ node(nodeName, nodeIndex)
+ );
+ }
+
+ @Test
+ public void testGetNonExistingNodeName() throws Exception {
+ when(ctx.read(VPP_CLASSIFIER_CONTEXT_IID)).thenReturn(Optional.of(context(table(TABLE_ID_1, TABLE_NAME_1))));
+ assertFalse(vppClassfierContext.getNodeName(TABLE_ID_0, 123, ctx).isPresent());
+ }
+
+ @Test
+ public void testGetNodeNameMissingNodeCtx() throws Exception {
+ final ClassifyTableContext tableCtx = table(TABLE_ID_0, TABLE_NAME_0, "aa");
+ when(ctx.read(VPP_CLASSIFIER_CONTEXT_IID)).thenReturn(Optional.of(context(tableCtx)));
+ when(ctx.read(TABLE_IID_0)).thenReturn(Optional.of(tableCtx));
+ assertEquals(Optional.absent(), vppClassfierContext.getNodeName(TABLE_ID_0, 123, ctx));
+ }
+
+ @Test
+ public void testGetNodeName() throws Exception {
+ final ClassifyTableContext tableCtx = table(TABLE_ID_0, TABLE_NAME_0, "aa", node("node123", 123));
+ when(ctx.read(VPP_CLASSIFIER_CONTEXT_IID)).thenReturn(Optional.of(context(tableCtx)));
+ when(ctx.read(TABLE_IID_0)).thenReturn(Optional.of(tableCtx));
+ assertEquals(Optional.of("node123"), vppClassfierContext.getNodeName(TABLE_ID_0, 123, ctx));
+ }
+
+ private VppClassifierContext context(ClassifyTableContext... tables) {
+ VppClassifierContextBuilder context = new VppClassifierContextBuilder();
+ context.setClassifyTableContext(Arrays.asList(tables));
+ return context.build();
+ }
+
+ private static ClassifyTableContext table(final Integer id, final String name) {
+ return table(id, name, null);
+ }
+
+ private static ClassifyTableContext table(final Integer id, final String name, final String classfierNodeName,
+ final NodeContext... nodeContexts) {
+ final ClassifyTableContextBuilder builder =
+ new ClassifyTableContextBuilder().setIndex(id).setName(name).setClassifierNodeName(classfierNodeName);
+
+ if (nodeContexts.length > 0) {
+ builder.setNodeContext(Arrays.asList(nodeContexts));
+ }
+
+ return builder.build();
+ }
+
+ private NodeContext node(final String nodeName, final int nodeIndex) {
+ return new NodeContextBuilder().setName(nodeName).setIndex(nodeIndex).build();
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/BridgeDomainCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/BridgeDomainCustomizerTest.java
new file mode 100644
index 000000000..0fbdb986e
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/BridgeDomainCustomizerTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.vppstate;
+
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.BridgeDomainsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomainKey;
+
+public class BridgeDomainCustomizerTest
+ extends ListReaderCustomizerTest<BridgeDomain, BridgeDomainKey, BridgeDomainBuilder> {
+
+ private NamingContext bdContext;
+ private NamingContext interfacesContext;
+
+ public BridgeDomainCustomizerTest() {
+ super(BridgeDomain.class, BridgeDomainsBuilder.class);
+ }
+
+ @Override
+ public void setUp() {
+ bdContext = new NamingContext("generatedBdName", "bd-test-instance");
+ interfacesContext = new NamingContext("generatedIfaceName", "ifc-test-instance");
+ }
+
+ @Override
+ protected ReaderCustomizer<BridgeDomain, BridgeDomainBuilder> initCustomizer() {
+ return new BridgeDomainCustomizer(api, bdContext);
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/L2FibEntryCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/L2FibEntryCustomizerTest.java
new file mode 100644
index 000000000..94a654c15
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/L2FibEntryCustomizerTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.vppstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.read.ListReaderCustomizerTest;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.L2FibForward;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.L2FibTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.L2FibTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.l2.fib.table.L2FibEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.l2.fib.table.L2FibEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.l2.fib.table.L2FibEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.BridgeDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomainKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.VppInvocationException;
+import io.fd.vpp.jvpp.core.dto.L2FibTableDump;
+import io.fd.vpp.jvpp.core.dto.L2FibTableEntry;
+import io.fd.vpp.jvpp.core.dto.L2FibTableEntryReplyDump;
+
+public class L2FibEntryCustomizerTest extends ListReaderCustomizerTest<L2FibEntry, L2FibEntryKey, L2FibEntryBuilder> {
+
+ private static final String BD_NAME = "testBD0";
+ private static final int BD_ID = 111;
+ private static final String IFACE_NAME = "eth0";
+ private static final int IFACE_ID = 123;
+ private static final String BD_CTX_NAME = "bd-test-instance";
+ private static final String IFC_CTX_NAME = "ifc-test-instance";
+ private NamingContext bdContext;
+ private NamingContext interfacesContext;
+
+ public L2FibEntryCustomizerTest() {
+ super(L2FibEntry.class, L2FibTableBuilder.class);
+ }
+
+ @Override
+ public void setUp() {
+ bdContext = new NamingContext("generatedBdName", BD_CTX_NAME);
+ defineMapping(mappingContext, BD_NAME, BD_ID, BD_CTX_NAME);
+ interfacesContext = new NamingContext("generatedIfaceName", IFC_CTX_NAME);
+ }
+
+ @Override
+ protected ReaderCustomizer<L2FibEntry, L2FibEntryBuilder> initCustomizer() {
+ return new L2FibEntryCustomizer(api, bdContext, interfacesContext);
+ }
+
+ private static InstanceIdentifier<L2FibEntry> getL2FibEntryId(final String bdName, final PhysAddress address) {
+ return InstanceIdentifier.create(BridgeDomains.class).child(BridgeDomain.class, new BridgeDomainKey(bdName))
+ .child(L2FibTable.class).child(L2FibEntry.class, new L2FibEntryKey(address));
+ }
+
+ private void whenL2FibTableDumpThenReturn(final List<L2FibTableEntry> l2FibTableEntryList)
+ throws ExecutionException, InterruptedException, VppInvocationException {
+ final L2FibTableEntryReplyDump reply = new L2FibTableEntryReplyDump();
+ reply.l2FibTableEntry = l2FibTableEntryList;
+ when(api.l2FibTableDump(any(L2FibTableDump.class))).thenReturn(future(reply));
+ }
+
+ @Test
+ public void testRead() throws Exception {
+ final long address_vpp = 0x0000010203040506L;
+ final PhysAddress address = new PhysAddress("01:02:03:04:05:06");
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME);
+
+ whenL2FibTableDumpThenReturn(Collections.singletonList(generateL2FibEntry(address_vpp)));
+
+ final L2FibEntryBuilder builder = mock(L2FibEntryBuilder.class);
+ getCustomizer().readCurrentAttributes(getL2FibEntryId(BD_NAME, address), builder, ctx);
+
+ verify(builder).setAction(L2FibForward.class);
+ verify(builder).setBridgedVirtualInterface(false);
+ verify(builder).setOutgoingInterface(IFACE_NAME);
+ verify(builder).setStaticConfig(false);
+ verify(builder).setPhysAddress(address);
+ verify(builder).setKey(new L2FibEntryKey(address));
+ }
+
+ private L2FibTableEntry generateL2FibEntry(final long mac) {
+ final L2FibTableEntry entry = new L2FibTableEntry();
+ entry.mac = mac;
+ entry.swIfIndex = IFACE_ID;
+ return entry;
+ }
+
+ @Test
+ public void testGetAllIds() throws Exception {
+ final long address_vpp = 0x0000112233445566L;
+ final PhysAddress address = new PhysAddress("11:22:33:44:55:66");
+
+ whenL2FibTableDumpThenReturn(Collections.singletonList(generateL2FibEntry(address_vpp)));
+
+ final List<L2FibEntryKey> ids = getCustomizer().getAllIds(getL2FibEntryId(BD_NAME, address), ctx);
+ assertEquals(1, ids.size());
+ assertEquals(address, ids.get(0).getPhysAddress());
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/VersionCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/VersionCustomizerTest.java
new file mode 100644
index 000000000..2f12cbde1
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/VersionCustomizerTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.vppstate;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.hc2vpp.common.test.read.ReaderCustomizerTest;
+import io.fd.vpp.jvpp.core.dto.ShowVersion;
+import io.fd.vpp.jvpp.core.dto.ShowVersionReply;
+import io.fd.vpp.jvpp.dto.ControlPing;
+import io.fd.vpp.jvpp.dto.ControlPingReply;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.Version;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.VersionBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VersionCustomizerTest extends ReaderCustomizerTest<Version, VersionBuilder> {
+
+ public VersionCustomizerTest() {
+ super(Version.class, VppStateBuilder.class);
+ }
+
+ @Override
+ protected ReaderCustomizer<Version, VersionBuilder> initCustomizer() {
+ return new VersionCustomizer(api);
+ }
+
+ @Test
+ public void testReadCurrentAttributes() throws Exception {
+ final ShowVersionReply reply = new ShowVersionReply();
+ reply.version = new byte[] {};
+ reply.program = new byte[] {};
+ reply.buildDate = new byte[] {};
+ reply.buildDirectory = new byte[] {};
+
+ when(api.showVersion(any(ShowVersion.class))).thenReturn(future(reply));
+ when(api.send(any(ControlPing.class))).thenReturn(future(new ControlPingReply()));
+ getCustomizer().readCurrentAttributes(InstanceIdentifier.create(Version.class), new VersionBuilder(), ctx);
+ verify(api).showVersion(any(ShowVersion.class));
+ verify(api).send(any(ControlPing.class));
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/VppStateTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/VppStateTest.java
new file mode 100644
index 000000000..7134a595a
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vppstate/VppStateTest.java
@@ -0,0 +1,326 @@
+/*
+ * 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.vppstate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.impl.read.GenericListReader;
+import io.fd.honeycomb.translate.impl.read.GenericReader;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.read.registry.ReaderRegistry;
+import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder;
+import io.fd.hc2vpp.common.test.util.NamingContextHelper;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.test.util.FutureProducer;
+import io.fd.vpp.jvpp.dto.ControlPing;
+import io.fd.vpp.jvpp.dto.ControlPingReply;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.L2FibTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.l2.fib.table.L2FibEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.l2.fib.table.L2FibEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.BridgeDomains;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.BridgeDomainsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.Version;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.VersionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomainKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import io.fd.vpp.jvpp.core.dto.BridgeDomainDetails;
+import io.fd.vpp.jvpp.core.dto.BridgeDomainDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.BridgeDomainDump;
+import io.fd.vpp.jvpp.core.dto.L2FibTableDump;
+import io.fd.vpp.jvpp.core.dto.L2FibTableEntry;
+import io.fd.vpp.jvpp.core.dto.L2FibTableEntryReplyDump;
+import io.fd.vpp.jvpp.core.dto.ShowVersion;
+import io.fd.vpp.jvpp.core.dto.ShowVersionReply;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+
+public class VppStateTest implements FutureProducer, NamingContextHelper {
+
+ private static final String BD_CTX_NAME = "bd-test-instance";
+ @Mock
+ private FutureJVppCore api;
+ @Mock
+ private ReadContext ctx;
+ @Mock
+ private MappingContext mappingContext;
+
+ private NamingContext bdContext;
+
+ private ReaderRegistry readerRegistry;
+
+ private static InstanceIdentifier<BridgeDomains> bridgeDomainsId;
+
+ /**
+ * Create root VppState reader with all its children wired.
+ */
+ private static ReaderRegistry getVppStateReader(@Nonnull final FutureJVppCore jVpp,
+ @Nonnull final NamingContext bdContext) {
+ final CompositeReaderRegistryBuilder registry = new CompositeReaderRegistryBuilder();
+
+ // VppState(Structural)
+ final InstanceIdentifier<VppState> vppStateId = InstanceIdentifier.create(VppState.class);
+ registry.addStructuralReader(vppStateId, VppStateBuilder.class);
+ // Version
+ registry.add(new GenericReader<>(vppStateId.child(Version.class), new VersionCustomizer(jVpp)));
+ // BridgeDomains(Structural)
+ bridgeDomainsId = vppStateId.child(BridgeDomains.class);
+ registry.addStructuralReader(bridgeDomainsId, BridgeDomainsBuilder.class);
+ // BridgeDomain
+ registry.add(getBridgeDomainReader(jVpp, bdContext));
+ return registry.build();
+ }
+
+ private static GenericListReader<BridgeDomain, BridgeDomainKey, BridgeDomainBuilder> getBridgeDomainReader(
+ final @Nonnull FutureJVppCore jVpp, final @Nonnull NamingContext bdContext) {
+ final InstanceIdentifier<BridgeDomain> bridgeDomainId = bridgeDomainsId.child(BridgeDomain.class);
+ return new GenericListReader<>(bridgeDomainId, new BridgeDomainCustomizer(jVpp, bdContext));
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ initMocks(this);
+ final ModificationCache cache = new ModificationCache();
+ doReturn(cache).when(ctx).getModificationCache();
+ doReturn(mappingContext).when(ctx).getMappingContext();
+
+ bdContext = new NamingContext("generatedBdName", BD_CTX_NAME);
+ readerRegistry = getVppStateReader(api, bdContext);
+ }
+
+ private static Version getVersion() {
+ return new VersionBuilder()
+ .setName("test")
+ .setBuildDirectory("1")
+ .setBranch("2")
+ .setBuildDate("3")
+ .setPid(0L)
+ .build();
+ }
+
+ private void whenShowVersionThenReturn(final Version version) {
+ final ShowVersionReply reply = new ShowVersionReply();
+ reply.buildDate = version.getBuildDate().getBytes();
+ reply.program = version.getName().getBytes();
+ reply.version = version.getBranch().getBytes();
+ reply.buildDirectory = version.getBuildDirectory().getBytes();
+ when(api.showVersion(any(ShowVersion.class))).thenReturn(future(reply));
+ // Version Customizer uses ControlPing to obtain PID
+ when(api.send(any(ControlPing.class))).thenReturn(future(new ControlPingReply()));
+ }
+
+ private void whenL2FibTableDumpThenReturn(final List<L2FibTableEntry> entryList) {
+ final L2FibTableEntryReplyDump reply = new L2FibTableEntryReplyDump();
+ reply.l2FibTableEntry = entryList;
+ when(api.l2FibTableDump(any(L2FibTableDump.class))).thenReturn(future(reply));
+ }
+
+ private void whenBridgeDomainDumpThenReturn(final List<BridgeDomainDetails> bdList) {
+ final BridgeDomainDetailsReplyDump reply = new BridgeDomainDetailsReplyDump();
+ reply.bridgeDomainDetails = bdList;
+
+ doAnswer(invocation -> {
+ BridgeDomainDump request = (BridgeDomainDump) invocation.getArguments()[0];
+ if (request.bdId == -1) {
+ reply.bridgeDomainDetails = bdList;
+ } else {
+ reply.bridgeDomainDetails = Collections.singletonList(bdList.get(request.bdId));
+ }
+ return future(reply);
+ }).when(api).bridgeDomainDump(any(BridgeDomainDump.class));
+ }
+
+ @Test
+ public void testReadAll() throws Exception {
+ final Version version = getVersion();
+ whenShowVersionThenReturn(version);
+
+ final BridgeDomainDetails bridgeDomainDetails = new BridgeDomainDetails();
+ final BridgeDomainDetails bridgeDomainDetails2 = new BridgeDomainDetails();
+ bridgeDomainDetails2.bdId = 1;
+
+ final List<BridgeDomainDetails> bdList = Arrays.asList(bridgeDomainDetails, bridgeDomainDetails2);
+ mockBdMapping(bridgeDomainDetails, "bd1");
+ mockBdMapping(bridgeDomainDetails2, "bd2");
+
+ whenBridgeDomainDumpThenReturn(bdList);
+
+ final Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> dataObjects =
+ readerRegistry.readAll(ctx);
+ assertEquals(dataObjects.size(), 1);
+ final VppState dataObject =
+ (VppState) Iterables.getOnlyElement(dataObjects.get(Iterables.getOnlyElement(dataObjects.keySet())));
+ assertEquals(version, dataObject.getVersion());
+ assertEquals(2, dataObject.getBridgeDomains().getBridgeDomain().size());
+ }
+
+ @Test
+ public void testReadSpecific() throws Exception {
+ final Version version = getVersion();
+ whenShowVersionThenReturn(version);
+ whenBridgeDomainDumpThenReturn(Collections.emptyList());
+
+ final Optional<? extends DataObject> read = readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx);
+ assertTrue(read.isPresent());
+ assertEquals(version, ((VppState) read.get()).getVersion());
+ }
+
+ @Test
+ public void testReadBridgeDomains() throws Exception {
+ final Version version = getVersion();
+ whenShowVersionThenReturn(version);
+ final BridgeDomainDetails details = new BridgeDomainDetails();
+ whenBridgeDomainDumpThenReturn(Collections.singletonList(details));
+
+ mockBdMapping(details, "bdn1");
+ VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
+
+ Optional<? extends DataObject> read =
+ readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class), ctx);
+ assertTrue(read.isPresent());
+ assertEquals(readRoot.getBridgeDomains(), read.get());
+ }
+
+ /**
+ * L2fib does not have a dedicated reader, relying on auto filtering
+ */
+ @Test
+ @Ignore("L2 FIB was moved to dedicated customizer. TODO: add infra test that covers such case")
+ @SuppressWarnings("unchecked")
+ public void testReadL2Fib() throws Exception {
+ final BridgeDomainDetails bd = new BridgeDomainDetails();
+ bd.bdId = 0;
+ final String bdName = "bdn1";
+ mockBdMapping(bd, bdName);
+ defineMapping(mappingContext, "eth1", 0, "ifc-test-instance");
+
+ whenBridgeDomainDumpThenReturn(Collections.singletonList(bd));
+ final L2FibTableEntry l2FibEntry = new L2FibTableEntry();
+ l2FibEntry.bdId = 0;
+ l2FibEntry.mac = 0x0605040302010000L;
+ whenL2FibTableDumpThenReturn(Collections.singletonList(l2FibEntry));
+
+ // Deep child without a dedicated reader with specific l2fib key
+ final InstanceIdentifier<? extends DataObject> idExisting =
+ InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
+ BridgeDomain.class, new BridgeDomainKey("bdn1")).child(L2FibTable.class)
+ .child(L2FibEntry.class, new L2FibEntryKey(new PhysAddress("01:02:03:04:05:06")));
+ Optional<? extends DataObject> read =
+ readerRegistry.read(idExisting, ctx);
+ assertTrue(read.isPresent());
+
+ // non existing l2fib
+ final InstanceIdentifier<? extends DataObject> idNonExisting =
+ InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
+ BridgeDomain.class, new BridgeDomainKey("bdn1")).child(L2FibTable.class)
+ .child(L2FibEntry.class, new L2FibEntryKey(new PhysAddress("FF:FF:FF:04:05:06")));
+ read = readerRegistry.read(idNonExisting, ctx);
+ assertFalse(read.isPresent());
+ }
+
+ private void mockBdMapping(final BridgeDomainDetails bd, final String bdName) {
+ defineMapping(mappingContext, bdName, bd.bdId, BD_CTX_NAME);
+ }
+
+ @Test
+ public void testReadBridgeDomainAll() throws Exception {
+ final Version version = getVersion();
+ whenShowVersionThenReturn(version);
+ final BridgeDomainDetails details = new BridgeDomainDetails();
+ whenBridgeDomainDumpThenReturn(Collections.singletonList(details));
+ mockBdMapping(details, "bd2");
+
+ VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
+
+ final GenericListReader<BridgeDomain, BridgeDomainKey, BridgeDomainBuilder> bridgeDomainReader =
+ getBridgeDomainReader(api, bdContext);
+
+ final List<BridgeDomain> read =
+ bridgeDomainReader.readList(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
+ BridgeDomain.class), ctx);
+
+ assertEquals(readRoot.getBridgeDomains().getBridgeDomain(), read);
+ }
+
+ @Test
+ public void testReadBridgeDomain() throws Exception {
+ final BridgeDomainDetails bd = new BridgeDomainDetails();
+ bd.bdId = 0;
+ final String bdName = "bdn1";
+ mockBdMapping(bd, bdName);
+
+ whenBridgeDomainDumpThenReturn(Collections.singletonList(bd));
+ whenShowVersionThenReturn(getVersion());
+
+ VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
+
+ final Optional<? extends DataObject> read =
+ readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
+ BridgeDomain.class, new BridgeDomainKey(bdName)), ctx);
+
+ assertTrue(read.isPresent());
+ assertEquals(readRoot.getBridgeDomains().getBridgeDomain().stream().filter(
+ input -> input.getKey().getName().equals(bdName)).findFirst().get(),
+ read.get());
+ }
+
+ @Test(expected = ReadFailedException.class)
+ public void testReadBridgeDomainNotExisting() throws Exception {
+ final String nonExistingBdName = "NOT EXISTING";
+ noMappingDefined(mappingContext, nonExistingBdName, BD_CTX_NAME);
+
+ readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
+ BridgeDomain.class, new BridgeDomainKey(nonExistingBdName)), ctx);
+ }
+
+ @Test
+ public void testReadVersion() throws Exception {
+ whenShowVersionThenReturn(getVersion());
+ whenBridgeDomainDumpThenReturn(Collections.emptyList());
+ VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
+
+ Optional<? extends DataObject> read =
+ readerRegistry.read(InstanceIdentifier.create(VppState.class).child(Version.class), ctx);
+ assertTrue(read.isPresent());
+ assertEquals(readRoot.getVersion(), read.get());
+ }
+} \ No newline at end of file