Add unit test for vxlan-gpe interface
authorHongjun Ni <[email protected]>
Mon, 6 Jun 2016 12:03:14 +0000 (20:03 +0800)
committerHongjun Ni <[email protected]>
Mon, 6 Jun 2016 12:03:14 +0000 (20:03 +0800)
Change-Id: I95f76cbb6f8d79a8a4fd38acaf35b59062e34e5b
Signed-off-by: Hongjun Ni <[email protected]>
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanGpeCustomizer.java
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanGpeCustomizerTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtilsTest.java
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanGpeCustomizerTest.java [new file with mode: 0644]

index be9b347..b031523 100644 (file)
@@ -37,6 +37,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Tap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanGpeTunnel;
 import org.openvpp.jvpp.dto.SwInterfaceDetails;
 import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump;
 import org.openvpp.jvpp.dto.SwInterfaceDump;
@@ -210,6 +211,10 @@ public final class InterfaceUtils {
             return Tap.class;
         }
 
+        if (interfaceName.startsWith("vxlanGpe")) {
+            return VxlanGpeTunnel.class;
+        }
+
         if (interfaceName.startsWith("vxlan")) {
             return VxlanTunnel.class;
         }
index 64a5b89..254b839 100644 (file)
@@ -37,6 +37,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanGpeTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanGpeVni;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanGpeNextProtocol;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VxlanGpe;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VxlanGpeBuilder;
 import org.opendaylight.yangtools.concepts.Builder;
@@ -125,6 +126,7 @@ public class VxlanGpeCustomizer extends FutureJVppCustomizer
             builder.setLocal(new IpAddress(local4));
         }
         builder.setVni(new VxlanGpeVni((long) swInterfaceVxlanGpeDetails.vni));
+        builder.setNextProtocol(VxlanGpeNextProtocol.forValue(swInterfaceVxlanGpeDetails.protocol));
         builder.setEncapVrfId((long) swInterfaceVxlanGpeDetails.encapVrfId);
         builder.setDecapVrfId((long) swInterfaceVxlanGpeDetails.decapVrfId);
         LOG.debug("VxlanGpe tunnel: {}, id: {} attributes read as: {}", key.getName(), index, builder);
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanGpeCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanGpeCustomizerTest.java
new file mode 100644 (file)
index 0000000..7e1d9e9
--- /dev/null
@@ -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.honeycomb.v3po.translate.v3po.interfaces;
+
+import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping;
+import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid;
+import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+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.mock;
+import static org.mockito.Mockito.times;
+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 com.google.common.net.InetAddresses;
+import io.fd.honeycomb.v3po.translate.MappingContext;
+import io.fd.honeycomb.v3po.translate.ModificationCache;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException;
+import io.fd.honeycomb.v3po.translate.write.WriteContext;
+import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping;
+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.rev150105.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanGpeVni;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanGpeNextProtocol;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VxlanGpe;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VxlanGpeBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.dto.VxlanGpeAddDelTunnel;
+import org.openvpp.jvpp.dto.VxlanGpeAddDelTunnelReply;
+import org.openvpp.jvpp.future.FutureJVpp;
+
+public class VxlanGpeCustomizerTest {
+
+    private static final byte ADD_VXLAN_GPE = 1;
+    private static final byte DEL_VXLAN_GPE = 0;
+
+    @Mock
+    private FutureJVpp api;
+    @Mock
+    private WriteContext writeContext;
+    @Mock
+    private MappingContext mappingContext;
+
+    private VxlanGpeCustomizer customizer;
+    private String ifaceName;
+    private InstanceIdentifier<VxlanGpe> id;
+
+    @Before
+    public void setUp() throws Exception {
+        initMocks(this);
+        InterfaceTypeTestUtils.setupWriteContext(writeContext,
+            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanGpeTunnel.class);
+        // TODO create base class for tests using vppApi
+        NamingContext namingContext = new NamingContext("generateInterfaceNAme", "test-instance");
+        final ModificationCache toBeReturned = new ModificationCache();
+        doReturn(toBeReturned).when(writeContext).getModificationCache();
+        doReturn(mappingContext).when(writeContext).getMappingContext();
+
+        customizer = new VxlanGpeCustomizer(api, namingContext);
+
+        ifaceName = "eth0";
+        id = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(ifaceName))
+                        .augmentation(VppInterfaceAugmentation.class).child(VxlanGpe.class);
+    }
+
+    private void whenVxlanGpeAddDelTunnelThen(final int retval) throws ExecutionException, InterruptedException {
+        final CompletionStage<VxlanGpeAddDelTunnelReply> replyCS = mock(CompletionStage.class);
+        final CompletableFuture<VxlanGpeAddDelTunnelReply> replyFuture = mock(CompletableFuture.class);
+        when(replyCS.toCompletableFuture()).thenReturn(replyFuture);
+        final VxlanGpeAddDelTunnelReply reply = new VxlanGpeAddDelTunnelReply();
+        reply.retval = retval;
+        when(replyFuture.get()).thenReturn(reply);
+        when(api.vxlanGpeAddDelTunnel(any(VxlanGpeAddDelTunnel.class))).thenReturn(replyCS);
+    }
+
+    private void whenVxlanGpeAddDelTunnelThenSuccess() throws ExecutionException, InterruptedException {
+        whenVxlanGpeAddDelTunnelThen(0);
+    }
+
+    private void whenVxlanGpeAddDelTunnelThenFailure() throws ExecutionException, InterruptedException {
+        whenVxlanGpeAddDelTunnelThen(-1);
+    }
+
+    private VxlanGpeAddDelTunnel verifyVxlanGpeAddDelTunnelWasInvoked(final VxlanGpe vxlanGpe) {
+        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) {
+        final VxlanGpeAddDelTunnel actual = verifyVxlanGpeAddDelTunnelWasInvoked(vxlanGpe);
+        assertEquals(ADD_VXLAN_GPE, actual.isAdd);
+    }
+
+    private void verifyVxlanGpeDeleteWasInvoked(final VxlanGpe vxlanGpe) {
+        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();
+
+        doReturn(Optional.absent())
+            .when(mappingContext).read(getMappingIid(ifaceName, "test-instance").firstIdentifierOf(Mappings.class));
+
+        customizer.writeCurrentAttributes(id, vxlanGpe, writeContext);
+        verifyVxlanGpeAddWasInvoked(vxlanGpe);
+        verify(mappingContext).put(eq(getMappingIid(ifaceName, "test-instance")), eq(getMapping(ifaceName, 0).get()));
+    }
+
+    @Test
+    public void testWriteCurrentAttributesMappingAlreadyPresent() throws Exception {
+        final VxlanGpe vxlanGpe = generateVxlanGpe();
+
+        whenVxlanGpeAddDelTunnelThenSuccess();
+        final Optional<Mapping> ifcMapping = getMapping(ifaceName, 0);
+
+        doReturn(Optional.of(new MappingsBuilder().setMapping(singletonList(ifcMapping.get())).build()))
+            .when(mappingContext).read(getMappingIid(ifaceName, "test-instance").firstIdentifierOf(Mappings.class));
+
+        customizer.writeCurrentAttributes(id, vxlanGpe, writeContext);
+        verifyVxlanGpeAddWasInvoked(vxlanGpe);
+
+        // Remove the first mapping before putting in the new one
+        verify(mappingContext).delete(eq(getMappingIid(ifaceName, "test-instance")));
+        verify(mappingContext).put(eq(getMappingIid(ifaceName, "test-instance")), eq(ifcMapping.get()));
+    }
+
+    @Test
+    public void testWriteCurrentAttributesFailed() throws Exception {
+        final VxlanGpe vxlanGpe = generateVxlanGpe();
+
+        whenVxlanGpeAddDelTunnelThenFailure();
+
+        try {
+            customizer.writeCurrentAttributes(id, vxlanGpe, writeContext);
+        } catch (WriteFailedException.CreateFailedException e) {
+            assertEquals(VppApiInvocationException.class, e.getCause().getClass());
+            verifyVxlanGpeAddWasInvoked(vxlanGpe);
+            // Mapping not stored due to failure
+            verify(mappingContext, times(0)).put(eq(getMappingIid(ifaceName, "test-instance")), eq(getMapping(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();
+        doReturn(getMapping(ifaceName, 1)).when(mappingContext).read(getMappingIid(ifaceName, "test-instance"));
+
+        customizer.deleteCurrentAttributes(id, vxlanGpe, writeContext);
+        verifyVxlanGpeDeleteWasInvoked(vxlanGpe);
+        verify(mappingContext).delete(eq(getMappingIid(ifaceName, "test-instance")));
+    }
+
+    @Test
+    public void testDeleteCurrentAttributesaFailed() throws Exception {
+        final VxlanGpe vxlanGpe = generateVxlanGpe();
+
+        whenVxlanGpeAddDelTunnelThenFailure();
+        doReturn(getMapping(ifaceName, 1)).when(mappingContext).read(getMappingIid(ifaceName, "test-instance"));
+
+        try {
+            customizer.deleteCurrentAttributes(id, vxlanGpe, writeContext);
+        } catch (WriteFailedException.DeleteFailedException e) {
+            assertEquals(VppApiInvocationException.class, e.getCause().getClass());
+            verifyVxlanGpeDeleteWasInvoked(vxlanGpe);
+            verify(mappingContext, times(0)).delete(eq(getMappingIid(ifaceName, "test-instance")));
+            return;
+        }
+        fail("WriteFailedException.DeleteFailedException was expected");
+    }
+}
\ No newline at end of file
index 6832fe0..c1bbd8e 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Tap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanGpeTunnel;
 
 public class InterfaceUtilsTest {
 
@@ -47,6 +48,7 @@ public class InterfaceUtilsTest {
     public void testGetInterfaceType() {
         assertEquals(Tap.class, InterfaceUtils.getInterfaceType("tap0"));
         assertEquals(VxlanTunnel.class, InterfaceUtils.getInterfaceType("vxlan0"));
+        assertEquals(VxlanGpeTunnel.class, InterfaceUtils.getInterfaceType("vxlanGpe0"));
         assertEquals(VhostUser.class, InterfaceUtils.getInterfaceType("VirtualEthernet0/0/0"));
         assertEquals(SubInterface.class, InterfaceUtils.getInterfaceType("eth0.0"));
         assertEquals(EthernetCsmacd.class, InterfaceUtils.getInterfaceType("local0"));
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanGpeCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanGpeCustomizerTest.java
new file mode 100644 (file)
index 0000000..4f4ac9e
--- /dev/null
@@ -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.honeycomb.v3po.translate.v3po.interfacesstate;
+
+import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping;
+import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid;
+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.v3po.translate.spi.read.RootReaderCustomizer;
+import io.fd.honeycomb.v3po.translate.v3po.test.ChildReaderCustomizerTest;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+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.rev150105.VppInterfaceStateAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VxlanGpe;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VxlanGpeBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.openvpp.jvpp.dto.SwInterfaceDetails;
+import org.openvpp.jvpp.dto.VxlanGpeTunnelDetails;
+import org.openvpp.jvpp.dto.VxlanGpeTunnelDetailsReplyDump;
+import org.openvpp.jvpp.dto.VxlanGpeTunnelDump;
+
+public class VxlanGpeCustomizerTest extends ChildReaderCustomizerTest<VxlanGpe, VxlanGpeBuilder> {
+
+    private NamingContext interfacesContext;
+    static final InstanceIdentifier<VxlanGpe> VXLAN_GPE_ID =
+        InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey("ifc2"))
+            .augmentation(VppInterfaceStateAugmentation.class).child(VxlanGpe.class);
+
+    public VxlanGpeCustomizerTest() {
+        super(VxlanGpe.class);
+    }
+
+    @Override
+    public void setUpBefore() {
+        interfacesContext = new NamingContext("vxlanGpe-tunnel", "test-instance");
+        doReturn(getMapping("ifc2", 0)).when(mappingContext).read(getMappingIid("ifc2", "test-instance"));
+
+        final SwInterfaceDetails v = new SwInterfaceDetails();
+        v.interfaceName = "vxlanGpe-tunnel2".getBytes();
+        final Map<Integer, SwInterfaceDetails> map = new HashMap<>();
+        map.put(0, v);
+        cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map);
+    }
+
+    @Override
+    protected void setUpAfter() throws UnknownHostException {
+        final CompletableFuture<VxlanGpeTunnelDetailsReplyDump> vxlanGpeTunnelDetailsReplyDumpCompletionStage =
+            new CompletableFuture<>();
+
+        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);
+        vxlanGpeTunnelDetailsReplyDumpCompletionStage.complete(value);
+
+        doReturn(vxlanGpeTunnelDetailsReplyDumpCompletionStage).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 RootReaderCustomizer<VxlanGpe, VxlanGpeBuilder> initCustomizer() {
+        return new VxlanGpeCustomizer(api, interfacesContext);
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+