507b43f9c6a6e4247e3d1e2e29d84e39bf99f4e6
[hc2vpp.git] /
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 org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertTrue;
21 import static org.junit.Assert.fail;
22 import static org.mockito.Matchers.any;
23 import static org.mockito.Matchers.eq;
24 import static org.mockito.Mockito.doReturn;
25 import static org.mockito.Mockito.times;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.MockitoAnnotations.initMocks;
28
29 import com.google.common.base.Optional;
30 import io.fd.honeycomb.translate.MappingContext;
31 import io.fd.honeycomb.translate.v3po.test.ContextTestUtils;
32 import io.fd.honeycomb.translate.v3po.test.TestHelperUtils;
33 import io.fd.honeycomb.translate.v3po.util.NamingContext;
34 import io.fd.honeycomb.translate.write.WriteContext;
35 import io.fd.honeycomb.translate.write.WriteFailedException;
36 import java.util.Arrays;
37 import java.util.List;
38 import java.util.concurrent.CompletableFuture;
39 import java.util.concurrent.ExecutionException;
40 import org.junit.Before;
41 import org.junit.Test;
42 import org.mockito.ArgumentCaptor;
43 import org.mockito.Mock;
44 import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping;
45 import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.CVlan;
46 import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qTagVlanType;
47 import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qVlanId;
48 import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.SVlan;
49 import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTag;
50 import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTagBuilder;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.SubinterfaceAugmentation;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527._802dot1ad;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.SubInterfaces;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.match.attributes.match.type.vlan.tagged.VlanTaggedBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Match;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.MatchBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.TagsBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.tags.Tag;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.tags.TagBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.tags.TagKey;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.openvpp.jvpp.VppBaseCallException;
69 import org.openvpp.jvpp.core.dto.CreateSubif;
70 import org.openvpp.jvpp.core.dto.CreateSubifReply;
71 import org.openvpp.jvpp.core.dto.SwInterfaceSetFlags;
72 import org.openvpp.jvpp.core.dto.SwInterfaceSetFlagsReply;
73 import org.openvpp.jvpp.core.future.FutureJVppCore;
74
75 public class SubInterfaceCustomizerTest {
76
77     @Mock
78     private FutureJVppCore api;
79     @Mock
80     private WriteContext writeContext;
81     @Mock
82     private MappingContext mappingContext;
83
84     private NamingContext namingContext;
85     private SubInterfaceCustomizer customizer;
86
87     public static final String SUPER_IF_NAME = "local0";
88     public static final int SUPER_IF_ID = 1;
89     private static final String SUB_IFACE_NAME = "local0.11";
90     private static final int SUBIF_INDEX = 11;
91
92     private static final short STAG_ID = 100;
93     private static final short CTAG_ID = 200;
94     private static final short CTAG_ANY_ID = 0; // only the *IdAny flag is set
95
96     private final Tag STAG_100;
97     private final Tag CTAG_200;
98     private final Tag CTAG_ANY;
99
100     public SubInterfaceCustomizerTest() {
101         STAG_100 = generateTag((short) 0, SVlan.class, new Dot1qTag.VlanId(new Dot1qVlanId((int) STAG_ID)));
102         CTAG_200 = generateTag((short) 1, CVlan.class, new Dot1qTag.VlanId(new Dot1qVlanId(200)));
103         CTAG_ANY = generateTag((short) 1, CVlan.class, new Dot1qTag.VlanId(Dot1qTag.VlanId.Enumeration.Any));
104     }
105
106     @Before
107     public void setUp() throws Exception {
108         initMocks(this);
109         namingContext = new NamingContext("generatedSubInterfaceName", "test-instance");
110         doReturn(mappingContext).when(writeContext).getMappingContext();
111         // TODO HONEYCOMB-116 create base class for tests using vppApi
112         customizer = new SubInterfaceCustomizer(api, namingContext);
113         doReturn(ContextTestUtils.getMapping(SUPER_IF_NAME, SUPER_IF_ID)).when(mappingContext)
114             .read(ContextTestUtils.getMappingIid(SUPER_IF_NAME, "test-instance"));
115     }
116
117     private SubInterface generateSubInterface(final boolean enabled, final List<Tag> tagList) {
118         SubInterfaceBuilder builder = new SubInterfaceBuilder();
119         builder.setVlanType(_802dot1ad.class);
120         builder.setIdentifier(11L);
121         final TagsBuilder tags = new TagsBuilder();
122
123         tags.setTag(tagList);
124
125         builder.setTags(tags.build());
126
127         builder.setMatch(generateMatch());
128         builder.setEnabled(enabled);
129         return builder.build();
130     }
131
132     private static Tag generateTag(final short index, final Class<? extends Dot1qTagVlanType> tagType,
133                                    final Dot1qTag.VlanId vlanId) {
134         TagBuilder tag = new TagBuilder();
135         tag.setIndex(index);
136         tag.setKey(new TagKey(index));
137         final Dot1qTagBuilder dtag = new Dot1qTagBuilder();
138         dtag.setTagType(tagType);
139         dtag.setVlanId(vlanId);
140         tag.setDot1qTag(dtag.build());
141         return tag.build();
142     }
143
144     private static Match generateMatch() {
145         final MatchBuilder match = new MatchBuilder();
146         final VlanTaggedBuilder tagged = new VlanTaggedBuilder();
147         tagged.setMatchExactTags(true);
148         match.setMatchType(
149             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.match.attributes.match.type.VlanTaggedBuilder()
150                 .setVlanTagged(tagged.build()).build());
151         return match.build();
152     }
153
154     private CreateSubif generateSubInterfaceRequest(final int superIfId, final short innerVlanId,
155                                                     final boolean isInnerAny) {
156         CreateSubif request = new CreateSubif();
157         request.subId = 11;
158         request.swIfIndex = superIfId;
159         request.twoTags = 1;
160         request.innerVlanId = innerVlanId;
161         request.innerVlanIdAny = (byte) (isInnerAny
162             ? 1
163             : 0);
164         request.dot1Ad = 1;
165         request.outerVlanId = STAG_ID;
166         return request;
167     }
168
169     private SwInterfaceSetFlags generateSwInterfaceEnableRequest(final int swIfIndex) {
170         SwInterfaceSetFlags request = new SwInterfaceSetFlags();
171         request.swIfIndex = swIfIndex;
172         request.adminUpDown = 1;
173         return request;
174     }
175
176     private InstanceIdentifier<SubInterface> getSubInterfaceId(final String name, final long index) {
177         return InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(name)).augmentation(
178             SubinterfaceAugmentation.class).child(SubInterfaces.class)
179             .child(SubInterface.class, new SubInterfaceKey(index));
180     }
181
182     private void whenCreateSubifThenSuccess() throws ExecutionException, InterruptedException, VppBaseCallException {
183         final CompletableFuture<CreateSubifReply> replyFuture = new CompletableFuture<>();
184         final CreateSubifReply reply = new CreateSubifReply();
185         replyFuture.complete(reply);
186         doReturn(replyFuture).when(api).createSubif(any(CreateSubif.class));
187     }
188
189     /**
190      * Failure response send
191      */
192     private void whenCreateSubifThenFailure() throws ExecutionException, InterruptedException, VppBaseCallException {
193         doReturn(TestHelperUtils.<CreateSubifReply>createFutureException()).when(api)
194             .createSubif(any(CreateSubif.class));
195     }
196
197     private void whenSwInterfaceSetFlagsThenSuccess()
198         throws ExecutionException, InterruptedException, VppBaseCallException {
199         final CompletableFuture<SwInterfaceSetFlagsReply> replyFuture = new CompletableFuture<>();
200         final SwInterfaceSetFlagsReply reply = new SwInterfaceSetFlagsReply();
201         replyFuture.complete(reply);
202         doReturn(replyFuture).when(api).swInterfaceSetFlags(any(SwInterfaceSetFlags.class));
203     }
204
205     private CreateSubif verifyCreateSubifWasInvoked(final CreateSubif expected) throws VppBaseCallException {
206         ArgumentCaptor<CreateSubif> argumentCaptor = ArgumentCaptor.forClass(CreateSubif.class);
207         verify(api).createSubif(argumentCaptor.capture());
208         final CreateSubif actual = argumentCaptor.getValue();
209
210         assertEquals(expected.swIfIndex, actual.swIfIndex);
211         assertEquals(expected.subId, actual.subId);
212         assertEquals(expected.noTags, actual.noTags);
213         assertEquals(expected.oneTag, actual.oneTag);
214         assertEquals(expected.twoTags, actual.twoTags);
215         assertEquals(expected.dot1Ad, actual.dot1Ad);
216         assertEquals(expected.exactMatch, actual.exactMatch);
217         assertEquals(expected.defaultSub, actual.defaultSub);
218         assertEquals(expected.outerVlanIdAny, actual.outerVlanIdAny);
219         assertEquals(expected.innerVlanIdAny, actual.innerVlanIdAny);
220         assertEquals(expected.outerVlanId, actual.outerVlanId);
221         assertEquals(expected.innerVlanId, actual.innerVlanId);
222         return actual;
223     }
224
225     private SwInterfaceSetFlags verifySwInterfaceSetFlagsWasInvoked(final SwInterfaceSetFlags expected)
226         throws VppBaseCallException {
227         ArgumentCaptor<SwInterfaceSetFlags> argumentCaptor = ArgumentCaptor.forClass(SwInterfaceSetFlags.class);
228         verify(api).swInterfaceSetFlags(argumentCaptor.capture());
229         final SwInterfaceSetFlags actual = argumentCaptor.getValue();
230
231         assertEquals(expected.swIfIndex, actual.swIfIndex);
232         assertEquals(expected.adminUpDown, actual.adminUpDown);
233         return actual;
234     }
235
236     @Test
237     public void testCreateTwoTags() throws Exception {
238         final SubInterface subInterface = generateSubInterface(false, Arrays.asList(STAG_100, CTAG_200));
239         final InstanceIdentifier<SubInterface> id = getSubInterfaceId(SUPER_IF_NAME, SUBIF_INDEX);
240
241         whenCreateSubifThenSuccess();
242         whenSwInterfaceSetFlagsThenSuccess();
243
244         customizer.writeCurrentAttributes(id, subInterface, writeContext);
245
246         verifyCreateSubifWasInvoked(generateSubInterfaceRequest(SUPER_IF_ID, CTAG_ID, false));
247         verify(mappingContext)
248             .put(eq(ContextTestUtils.getMappingIid(SUB_IFACE_NAME, "test-instance")), eq(
249                     ContextTestUtils.getMapping(SUB_IFACE_NAME, 0).get()));
250     }
251
252     @Test
253     public void testCreateDot1qAnyTag() throws Exception {
254         final SubInterface subInterface = generateSubInterface(false, Arrays.asList(STAG_100, CTAG_ANY));
255         final InstanceIdentifier<SubInterface> id = getSubInterfaceId(SUPER_IF_NAME, SUBIF_INDEX);
256
257         whenCreateSubifThenSuccess();
258         whenSwInterfaceSetFlagsThenSuccess();
259
260         customizer.writeCurrentAttributes(id, subInterface, writeContext);
261
262         verifyCreateSubifWasInvoked(generateSubInterfaceRequest(SUPER_IF_ID, CTAG_ANY_ID, true));
263         verify(mappingContext)
264             .put(eq(ContextTestUtils.getMappingIid(SUB_IFACE_NAME, "test-instance")), eq(
265                     ContextTestUtils.getMapping(SUB_IFACE_NAME, 0).get()));
266     }
267
268     @Test
269     public void testCreateFailed() throws Exception {
270         final SubInterface subInterface = generateSubInterface(false, Arrays.asList(STAG_100, CTAG_200));
271         final InstanceIdentifier<SubInterface> id = getSubInterfaceId(SUPER_IF_NAME, SUBIF_INDEX);
272
273         whenCreateSubifThenFailure();
274
275         try {
276             customizer.writeCurrentAttributes(id, subInterface, writeContext);
277         } catch (WriteFailedException.CreateFailedException e) {
278             assertTrue(e.getCause() instanceof VppBaseCallException);
279             verifyCreateSubifWasInvoked(generateSubInterfaceRequest(SUPER_IF_ID, CTAG_ID, false));
280             verify(mappingContext, times(0)).put(
281                 eq(ContextTestUtils.getMappingIid(SUPER_IF_NAME, "test-instance")),
282                 eq(ContextTestUtils.getMapping(SUPER_IF_NAME, 0).get()));
283             return;
284         }
285         fail("WriteFailedException.CreateFailedException was expected");
286     }
287
288     @Test
289     public void testUpdate() throws Exception {
290         final List<Tag> tags = Arrays.asList(STAG_100, CTAG_200);
291         final SubInterface before = generateSubInterface(false, tags);
292         final SubInterface after = generateSubInterface(true, tags);
293         final InstanceIdentifier<SubInterface> id = getSubInterfaceId(SUPER_IF_NAME, SUBIF_INDEX);
294
295         whenSwInterfaceSetFlagsThenSuccess();
296         final Optional<Mapping> ifcMapping = ContextTestUtils.getMapping(SUPER_IF_NAME, SUBIF_INDEX);
297         doReturn(ifcMapping).when(mappingContext).read(any());
298
299         customizer.updateCurrentAttributes(id, before, after, writeContext);
300
301         verifySwInterfaceSetFlagsWasInvoked(generateSwInterfaceEnableRequest(SUBIF_INDEX));
302     }
303
304     @Test(expected = UnsupportedOperationException.class)
305     public void testDelete() throws Exception {
306         final SubInterface subInterface = generateSubInterface(false, Arrays.asList(STAG_100, CTAG_200));
307         customizer.deleteCurrentAttributes(null, subInterface, writeContext);
308     }
309 }