2 * Copyright (c) 2016 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package io.fd.honeycomb.translate.v3po.interfaces;
19 import static io.fd.honeycomb.translate.v3po.test.ContextTestUtils.getMapping;
20 import static io.fd.honeycomb.translate.v3po.test.ContextTestUtils.getMappingIid;
21 import static java.util.Collections.singletonList;
22 import static org.junit.Assert.assertArrayEquals;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26 import static org.mockito.Matchers.any;
27 import static org.mockito.Matchers.anyLong;
28 import static org.mockito.Matchers.eq;
29 import static org.mockito.Mockito.doReturn;
30 import static org.mockito.Mockito.mock;
31 import static org.mockito.Mockito.times;
32 import static org.mockito.Mockito.verify;
33 import static org.mockito.Mockito.when;
34 import static org.mockito.MockitoAnnotations.initMocks;
36 import com.google.common.base.Optional;
37 import com.google.common.net.InetAddresses;
38 import io.fd.honeycomb.translate.MappingContext;
39 import io.fd.honeycomb.translate.ModificationCache;
40 import io.fd.honeycomb.translate.v3po.DisabledInterfacesManager;
41 import io.fd.honeycomb.translate.v3po.test.TestHelperUtils;
42 import io.fd.honeycomb.translate.v3po.util.NamingContext;
43 import io.fd.honeycomb.translate.write.WriteContext;
44 import io.fd.honeycomb.translate.write.WriteFailedException;
45 import java.util.concurrent.CompletableFuture;
46 import java.util.concurrent.CompletionStage;
47 import java.util.concurrent.ExecutionException;
48 import java.util.concurrent.TimeUnit;
49 import java.util.concurrent.TimeoutException;
50 import org.junit.Before;
51 import org.junit.Test;
52 import org.mockito.ArgumentCaptor;
53 import org.mockito.Mock;
54 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings;
55 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder;
56 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanVni;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Vxlan;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VxlanBuilder;
66 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
67 import org.openvpp.jvpp.VppBaseCallException;
68 import org.openvpp.jvpp.VppInvocationException;
69 import org.openvpp.jvpp.core.dto.VxlanAddDelTunnel;
70 import org.openvpp.jvpp.core.dto.VxlanAddDelTunnelReply;
71 import org.openvpp.jvpp.core.future.FutureJVppCore;
73 public class VxlanCustomizerTest {
75 private static final byte ADD_VXLAN = 1;
76 private static final byte DEL_VXLAN = 0;
79 private FutureJVppCore api;
81 private WriteContext writeContext;
83 private MappingContext mappingContext;
85 private DisabledInterfacesManager disableContext;
87 private VxlanCustomizer customizer;
88 private String ifaceName;
89 private InstanceIdentifier<Vxlan> id;
92 public void setUp() throws Exception {
94 InterfaceTypeTestUtils.setupWriteContext(writeContext,
95 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel.class);
96 // TODO HONEYCOMB-116 create base class for tests using vppApi
97 NamingContext namingContext = new NamingContext("generateInterfaceNAme", "test-instance");
98 final ModificationCache toBeReturned = new ModificationCache();
99 doReturn(toBeReturned).when(writeContext).getModificationCache();
100 doReturn(mappingContext).when(writeContext).getMappingContext();
102 customizer = new VxlanCustomizer(api, namingContext, disableContext);
105 id = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(ifaceName))
106 .augmentation(VppInterfaceAugmentation.class).child(Vxlan.class);
109 private void whenVxlanAddDelTunnelThenSuccess()
110 throws ExecutionException, InterruptedException, VppInvocationException, TimeoutException {
111 final CompletionStage<VxlanAddDelTunnelReply> replyCS = mock(CompletionStage.class);
112 final CompletableFuture<VxlanAddDelTunnelReply> replyFuture = mock(CompletableFuture.class);
113 when(replyCS.toCompletableFuture()).thenReturn(replyFuture);
114 final VxlanAddDelTunnelReply reply = new VxlanAddDelTunnelReply();
115 when(replyFuture.get(anyLong(), eq(TimeUnit.SECONDS))).thenReturn(reply);
116 when(api.vxlanAddDelTunnel(any(VxlanAddDelTunnel.class))).thenReturn(replyCS);
120 * Failure response send
122 private void whenVxlanAddDelTunnelThenFailure()
123 throws ExecutionException, InterruptedException, VppInvocationException {
124 doReturn(TestHelperUtils.<VxlanAddDelTunnelReply>createFutureException()).when(api)
125 .vxlanAddDelTunnel(any(VxlanAddDelTunnel.class));
128 private VxlanAddDelTunnel verifyVxlanAddDelTunnelWasInvoked(final Vxlan vxlan) throws VppInvocationException {
129 ArgumentCaptor<VxlanAddDelTunnel> argumentCaptor = ArgumentCaptor.forClass(VxlanAddDelTunnel.class);
130 verify(api).vxlanAddDelTunnel(argumentCaptor.capture());
131 final VxlanAddDelTunnel actual = argumentCaptor.getValue();
132 assertEquals(0, actual.isIpv6);
133 assertEquals(-1, actual.decapNextIndex);
134 assertArrayEquals(InetAddresses.forString(vxlan.getSrc().getIpv4Address().getValue()).getAddress(),
136 assertArrayEquals(InetAddresses.forString(vxlan.getDst().getIpv4Address().getValue()).getAddress(),
138 assertEquals(vxlan.getEncapVrfId().intValue(), actual.encapVrfId);
139 assertEquals(vxlan.getVni().getValue().intValue(), actual.vni);
143 private void verifyVxlanAddWasInvoked(final Vxlan vxlan) throws VppInvocationException {
144 final VxlanAddDelTunnel actual = verifyVxlanAddDelTunnelWasInvoked(vxlan);
145 assertEquals(ADD_VXLAN, actual.isAdd);
148 private void verifyVxlanDeleteWasInvoked(final Vxlan vxlan) throws VppInvocationException {
149 final VxlanAddDelTunnel actual = verifyVxlanAddDelTunnelWasInvoked(vxlan);
150 assertEquals(DEL_VXLAN, actual.isAdd);
153 private static Vxlan generateVxlan(long vni) {
154 final VxlanBuilder builder = new VxlanBuilder();
155 builder.setSrc(new IpAddress(new Ipv4Address("192.168.20.10")));
156 builder.setDst(new IpAddress(new Ipv4Address("192.168.20.11")));
157 builder.setEncapVrfId(Long.valueOf(123));
158 builder.setVni(new VxlanVni(Long.valueOf(vni)));
159 return builder.build();
162 private static Vxlan generateVxlan() {
163 return generateVxlan(Long.valueOf(11));
167 public void testWriteCurrentAttributes() throws Exception {
168 final Vxlan vxlan = generateVxlan();
170 whenVxlanAddDelTunnelThenSuccess();
172 doReturn(Optional.absent())
173 .when(mappingContext).read(getMappingIid(ifaceName, "test-instance").firstIdentifierOf(Mappings.class));
175 customizer.writeCurrentAttributes(id, vxlan, writeContext);
176 verifyVxlanAddWasInvoked(vxlan);
177 verify(mappingContext).put(eq(getMappingIid(ifaceName, "test-instance")), eq(getMapping(ifaceName, 0).get()));
181 public void testWriteCurrentAttributesWithExistingVxlanPlaceholder() throws Exception {
182 final Vxlan vxlan = generateVxlan();
184 whenVxlanAddDelTunnelThenSuccess();
186 doReturn(Optional.absent())
187 .when(mappingContext).read(getMappingIid(ifaceName, "test-instance").firstIdentifierOf(Mappings.class));
188 doReturn(true).when(disableContext).isInterfaceDisabled(0, mappingContext);
190 customizer.writeCurrentAttributes(id, vxlan, writeContext);
191 verifyVxlanAddWasInvoked(vxlan);
192 verify(mappingContext).put(eq(getMappingIid(ifaceName, "test-instance")), eq(getMapping(ifaceName, 0).get()));
193 verify(disableContext).removeDisabledInterface(0, mappingContext);
197 public void testWriteCurrentAttributesMappingAlreadyPresent() throws Exception {
198 final Vxlan vxlan = generateVxlan();
200 whenVxlanAddDelTunnelThenSuccess();
201 final Optional<Mapping> ifcMapping = getMapping(ifaceName, 0);
203 doReturn(Optional.of(new MappingsBuilder().setMapping(singletonList(ifcMapping.get())).build()))
204 .when(mappingContext).read(getMappingIid(ifaceName, "test-instance").firstIdentifierOf(Mappings.class));
206 customizer.writeCurrentAttributes(id, vxlan, writeContext);
207 verifyVxlanAddWasInvoked(vxlan);
209 // Remove the first mapping before putting in the new one
210 verify(mappingContext).delete(eq(getMappingIid(ifaceName, "test-instance")));
211 verify(mappingContext).put(eq(getMappingIid(ifaceName, "test-instance")), eq(ifcMapping.get()));
215 public void testWriteCurrentAttributesFailed() throws Exception {
216 final Vxlan vxlan = generateVxlan();
218 whenVxlanAddDelTunnelThenFailure();
221 customizer.writeCurrentAttributes(id, vxlan, writeContext);
222 } catch (WriteFailedException.CreateFailedException e) {
223 assertTrue(e.getCause() instanceof VppBaseCallException);
224 verifyVxlanAddWasInvoked(vxlan);
225 // Mapping not stored due to failure
226 verify(mappingContext, times(0)).put(eq(getMappingIid(ifaceName, "test-instance")), eq(getMapping(ifaceName, 0).get()));
229 fail("WriteFailedException.CreateFailedException was expected");
233 public void testUpdateCurrentAttributes() throws Exception {
235 customizer.updateCurrentAttributes(id, generateVxlan(10), generateVxlan(11), writeContext);
236 } catch (WriteFailedException.UpdateFailedException e) {
237 assertEquals(UnsupportedOperationException.class, e.getCause().getClass());
240 fail("WriteFailedException.UpdateFailedException was expected");
244 public void testDeleteCurrentAttributes() throws Exception {
245 final Vxlan vxlan = generateVxlan();
247 whenVxlanAddDelTunnelThenSuccess();
248 doReturn(getMapping(ifaceName, 1)).when(mappingContext).read(getMappingIid(ifaceName, "test-instance"));
250 customizer.deleteCurrentAttributes(id, vxlan, writeContext);
251 verifyVxlanDeleteWasInvoked(vxlan);
252 verify(mappingContext).delete(eq(getMappingIid(ifaceName, "test-instance")));
253 verify(disableContext).disableInterface(1, mappingContext);
257 public void testDeleteCurrentAttributesaFailed() throws Exception {
258 final Vxlan vxlan = generateVxlan();
260 whenVxlanAddDelTunnelThenFailure();
261 doReturn(getMapping(ifaceName, 1)).when(mappingContext).read(getMappingIid(ifaceName, "test-instance"));
264 customizer.deleteCurrentAttributes(id, vxlan, writeContext);
265 } catch (WriteFailedException.DeleteFailedException e) {
266 assertTrue(e.getCause() instanceof VppBaseCallException);
267 verifyVxlanDeleteWasInvoked(vxlan);
268 verify(mappingContext, times(0)).delete(eq(getMappingIid(ifaceName, "test-instance")));
271 fail("WriteFailedException.DeleteFailedException was expected");