HONEYCOMB-83: Add Gre Feature within HC
[honeycomb.git] / v3po / v3po2vpp / src / test / java / io / fd / honeycomb / translate / v3po / interfaces / GreCustomizerTest.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  *
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:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package io.fd.honeycomb.translate.v3po.interfaces;
18
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;
35
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.test.TestHelperUtils;
41 import io.fd.honeycomb.translate.v3po.util.NamingContext;
42 import io.fd.honeycomb.translate.write.WriteContext;
43 import io.fd.honeycomb.translate.write.WriteFailedException;
44 import java.util.concurrent.CompletableFuture;
45 import java.util.concurrent.CompletionStage;
46 import java.util.concurrent.ExecutionException;
47 import java.util.concurrent.TimeUnit;
48 import java.util.concurrent.TimeoutException;
49 import org.junit.Before;
50 import org.junit.Test;
51 import org.mockito.ArgumentCaptor;
52 import org.mockito.Mock;
53 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings;
54 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder;
55 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Gre;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.GreBuilder;
64 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
65 import org.openvpp.jvpp.VppBaseCallException;
66 import org.openvpp.jvpp.VppInvocationException;
67 import org.openvpp.jvpp.dto.GreAddDelTunnel;
68 import org.openvpp.jvpp.dto.GreAddDelTunnelReply;
69 import org.openvpp.jvpp.future.FutureJVpp;
70
71 public class GreCustomizerTest {
72
73     private static final byte ADD_GRE = 1;
74     private static final byte DEL_GRE = 0;
75
76     @Mock
77     private FutureJVpp api;
78     @Mock
79     private WriteContext writeContext;
80     @Mock
81     private MappingContext mappingContext;
82
83     private GreCustomizer customizer;
84     private String ifaceName;
85     private InstanceIdentifier<Gre> id;
86
87     @Before
88     public void setUp() throws Exception {
89         initMocks(this);
90         InterfaceTypeTestUtils.setupWriteContext(writeContext,
91             org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.GreTunnel.class);
92         // TODO create base class for tests using vppApi
93         NamingContext namingContext = new NamingContext("generateInterfaceNAme", "test-instance");
94         final ModificationCache toBeReturned = new ModificationCache();
95         doReturn(toBeReturned).when(writeContext).getModificationCache();
96         doReturn(mappingContext).when(writeContext).getMappingContext();
97
98         customizer = new GreCustomizer(api, namingContext);
99
100         ifaceName = "eth0";
101         id = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(ifaceName))
102                         .augmentation(VppInterfaceAugmentation.class).child(Gre.class);
103     }
104
105     private void whenGreAddDelTunnelThenSuccess()
106         throws ExecutionException, InterruptedException, VppInvocationException, TimeoutException {
107         final CompletionStage<GreAddDelTunnelReply> replyCS = mock(CompletionStage.class);
108         final CompletableFuture<GreAddDelTunnelReply> replyFuture = mock(CompletableFuture.class);
109         when(replyCS.toCompletableFuture()).thenReturn(replyFuture);
110         final GreAddDelTunnelReply reply = new GreAddDelTunnelReply();
111         when(replyFuture.get(anyLong(), eq(TimeUnit.SECONDS))).thenReturn(reply);
112         when(api.greAddDelTunnel(any(GreAddDelTunnel.class))).thenReturn(replyCS);
113     }
114
115     /**
116      * Failure response send
117      */
118     private void whenGreAddDelTunnelThenFailure()
119             throws ExecutionException, InterruptedException, VppInvocationException {
120         doReturn(TestHelperUtils.<GreAddDelTunnelReply>createFutureException()).when(api)
121                 .greAddDelTunnel(any(GreAddDelTunnel.class));
122     }
123
124     private GreAddDelTunnel verifyGreAddDelTunnelWasInvoked(final Gre gre) throws VppInvocationException {
125         ArgumentCaptor<GreAddDelTunnel> argumentCaptor = ArgumentCaptor.forClass(GreAddDelTunnel.class);
126         verify(api).greAddDelTunnel(argumentCaptor.capture());
127         final GreAddDelTunnel actual = argumentCaptor.getValue();
128         assertEquals(0, actual.isIpv6);
129         assertArrayEquals(InetAddresses.forString(gre.getSrc().getIpv4Address().getValue()).getAddress(),
130                 actual.srcAddress);
131         assertArrayEquals(InetAddresses.forString(gre.getDst().getIpv4Address().getValue()).getAddress(),
132                 actual.dstAddress);
133         assertEquals(gre.getOuterFibId().intValue(), actual.outerFibId);
134         return actual;
135     }
136
137     private void verifyGreAddWasInvoked(final Gre gre) throws VppInvocationException {
138         final GreAddDelTunnel actual = verifyGreAddDelTunnelWasInvoked(gre);
139         assertEquals(ADD_GRE, actual.isAdd);
140     }
141
142     private void verifyGreDeleteWasInvoked(final Gre gre) throws VppInvocationException {
143         final GreAddDelTunnel actual = verifyGreAddDelTunnelWasInvoked(gre);
144         assertEquals(DEL_GRE, actual.isAdd);
145     }
146
147     private static Gre generateGre(long vni) {
148         final GreBuilder builder = new GreBuilder();
149         builder.setSrc(new IpAddress(new Ipv4Address("192.168.20.10")));
150         builder.setDst(new IpAddress(new Ipv4Address("192.168.20.11")));
151         builder.setOuterFibId(Long.valueOf(123));
152         return builder.build();
153     }
154
155     private static Gre generateGre() {
156         return generateGre(Long.valueOf(11));
157     }
158
159     @Test
160     public void testWriteCurrentAttributes() throws Exception {
161         final Gre gre = generateGre();
162
163         whenGreAddDelTunnelThenSuccess();
164
165         doReturn(Optional.absent())
166             .when(mappingContext).read(getMappingIid(ifaceName, "test-instance").firstIdentifierOf(Mappings.class));
167
168         customizer.writeCurrentAttributes(id, gre, writeContext);
169         verifyGreAddWasInvoked(gre);
170         verify(mappingContext).put(eq(getMappingIid(ifaceName, "test-instance")), eq(getMapping(ifaceName, 0).get()));
171     }
172
173     @Test
174     public void testWriteCurrentAttributesMappingAlreadyPresent() throws Exception {
175         final Gre gre = generateGre();
176
177         whenGreAddDelTunnelThenSuccess();
178         final Optional<Mapping> ifcMapping = getMapping(ifaceName, 0);
179
180         doReturn(Optional.of(new MappingsBuilder().setMapping(singletonList(ifcMapping.get())).build()))
181             .when(mappingContext).read(getMappingIid(ifaceName, "test-instance").firstIdentifierOf(Mappings.class));
182
183         customizer.writeCurrentAttributes(id, gre, writeContext);
184         verifyGreAddWasInvoked(gre);
185
186         // Remove the first mapping before putting in the new one
187         verify(mappingContext).delete(eq(getMappingIid(ifaceName, "test-instance")));
188         verify(mappingContext).put(eq(getMappingIid(ifaceName, "test-instance")), eq(ifcMapping.get()));
189     }
190
191     @Test
192     public void testWriteCurrentAttributesFailed() throws Exception {
193         final Gre gre = generateGre();
194
195         whenGreAddDelTunnelThenFailure();
196
197         try {
198             customizer.writeCurrentAttributes(id, gre, writeContext);
199         } catch (WriteFailedException.CreateFailedException e) {
200             assertTrue(e.getCause() instanceof VppBaseCallException);
201             verifyGreAddWasInvoked(gre);
202             // Mapping not stored due to failure
203             verify(mappingContext, times(0)).put(eq(getMappingIid(ifaceName, "test-instance")), eq(getMapping(ifaceName, 0).get()));
204             return;
205         }
206         fail("WriteFailedException.CreateFailedException was expected");
207     }
208
209     @Test
210     public void testUpdateCurrentAttributes() throws Exception {
211         try {
212             customizer.updateCurrentAttributes(id, generateGre(10), generateGre(11), writeContext);
213         } catch (WriteFailedException.UpdateFailedException e) {
214             assertEquals(UnsupportedOperationException.class, e.getCause().getClass());
215             return;
216         }
217         fail("WriteFailedException.UpdateFailedException was expected");
218     }
219
220     @Test
221     public void testDeleteCurrentAttributes() throws Exception {
222         final Gre gre = generateGre();
223
224         whenGreAddDelTunnelThenSuccess();
225         doReturn(getMapping(ifaceName, 1)).when(mappingContext).read(getMappingIid(ifaceName, "test-instance"));
226
227         customizer.deleteCurrentAttributes(id, gre, writeContext);
228         verifyGreDeleteWasInvoked(gre);
229         verify(mappingContext).delete(eq(getMappingIid(ifaceName, "test-instance")));
230     }
231
232     @Test
233     public void testDeleteCurrentAttributesaFailed() throws Exception {
234         final Gre gre = generateGre();
235
236         whenGreAddDelTunnelThenFailure();
237         doReturn(getMapping(ifaceName, 1)).when(mappingContext).read(getMappingIid(ifaceName, "test-instance"));
238
239         try {
240             customizer.deleteCurrentAttributes(id, gre, writeContext);
241         } catch (WriteFailedException.DeleteFailedException e) {
242             assertTrue(e.getCause() instanceof VppBaseCallException);
243             verifyGreDeleteWasInvoked(gre);
244             verify(mappingContext, times(0)).delete(eq(getMappingIid(ifaceName, "test-instance")));
245             return;
246         }
247         fail("WriteFailedException.DeleteFailedException was expected");
248     }
249 }