cdc352ac5443cf5e7ff7dd29214bc1a4e135e3b9
[honeycomb.git] / v3po / v3po2vpp / src / test / java / io / fd / honeycomb / translate / v3po / vppstate / VppStateTest.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.vppstate;
18
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 import static org.mockito.Matchers.any;
23 import static org.mockito.Mockito.doAnswer;
24 import static org.mockito.Mockito.doReturn;
25 import static org.mockito.Mockito.when;
26 import static org.mockito.MockitoAnnotations.initMocks;
27
28 import com.google.common.base.Optional;
29 import com.google.common.collect.Iterables;
30 import com.google.common.collect.Multimap;
31 import io.fd.honeycomb.translate.MappingContext;
32 import io.fd.honeycomb.translate.ModificationCache;
33 import io.fd.honeycomb.translate.impl.read.GenericListReader;
34 import io.fd.honeycomb.translate.impl.read.GenericReader;
35 import io.fd.honeycomb.translate.read.ReadContext;
36 import io.fd.honeycomb.translate.read.ReadFailedException;
37 import io.fd.honeycomb.translate.read.registry.ReaderRegistry;
38 import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder;
39 import io.fd.honeycomb.vpp.test.util.NamingContextHelper;
40 import io.fd.honeycomb.translate.vpp.util.NamingContext;
41 import io.fd.honeycomb.vpp.test.util.FutureProducer;
42 import io.fd.vpp.jvpp.dto.ControlPing;
43 import io.fd.vpp.jvpp.dto.ControlPingReply;
44 import java.util.Arrays;
45 import java.util.Collections;
46 import java.util.List;
47 import javax.annotation.Nonnull;
48 import org.junit.Before;
49 import org.junit.Ignore;
50 import org.junit.Test;
51 import org.mockito.Mock;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppState;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppStateBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.L2FibTable;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.l2.fib.table.L2FibEntry;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.fib.attributes.l2.fib.table.L2FibEntryKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.BridgeDomains;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.BridgeDomainsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.Version;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.VersionBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomain;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomainBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.state.bridge.domains.BridgeDomainKey;
65 import org.opendaylight.yangtools.yang.binding.DataObject;
66 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
67 import io.fd.vpp.jvpp.core.dto.BridgeDomainDetails;
68 import io.fd.vpp.jvpp.core.dto.BridgeDomainDetailsReplyDump;
69 import io.fd.vpp.jvpp.core.dto.BridgeDomainDump;
70 import io.fd.vpp.jvpp.core.dto.L2FibTableDump;
71 import io.fd.vpp.jvpp.core.dto.L2FibTableEntry;
72 import io.fd.vpp.jvpp.core.dto.L2FibTableEntryReplyDump;
73 import io.fd.vpp.jvpp.core.dto.ShowVersion;
74 import io.fd.vpp.jvpp.core.dto.ShowVersionReply;
75 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
76
77 public class VppStateTest implements FutureProducer, NamingContextHelper {
78
79     private static final String BD_CTX_NAME = "bd-test-instance";
80     @Mock
81     private FutureJVppCore api;
82     @Mock
83     private ReadContext ctx;
84     @Mock
85     private MappingContext mappingContext;
86
87     private NamingContext bdContext;
88
89     private ReaderRegistry readerRegistry;
90
91     private static InstanceIdentifier<BridgeDomains> bridgeDomainsId;
92
93     /**
94      * Create root VppState reader with all its children wired.
95      */
96     private static ReaderRegistry getVppStateReader(@Nonnull final FutureJVppCore jVpp,
97                                             @Nonnull final NamingContext bdContext) {
98         final CompositeReaderRegistryBuilder registry = new CompositeReaderRegistryBuilder();
99
100         // VppState(Structural)
101         final InstanceIdentifier<VppState> vppStateId = InstanceIdentifier.create(VppState.class);
102         registry.addStructuralReader(vppStateId, VppStateBuilder.class);
103         //  Version
104         registry.add(new GenericReader<>(vppStateId.child(Version.class), new VersionCustomizer(jVpp)));
105         //  BridgeDomains(Structural)
106         bridgeDomainsId = vppStateId.child(BridgeDomains.class);
107         registry.addStructuralReader(bridgeDomainsId, BridgeDomainsBuilder.class);
108         //   BridgeDomain
109         registry.add(getBridgeDomainReader(jVpp, bdContext));
110         return registry.build();
111     }
112
113     private static GenericListReader<BridgeDomain, BridgeDomainKey, BridgeDomainBuilder> getBridgeDomainReader(
114         final @Nonnull FutureJVppCore jVpp, final @Nonnull NamingContext bdContext) {
115         final InstanceIdentifier<BridgeDomain> bridgeDomainId = bridgeDomainsId.child(BridgeDomain.class);
116         return new GenericListReader<>(bridgeDomainId, new BridgeDomainCustomizer(jVpp, bdContext));
117     }
118
119     @Before
120     public void setUp() throws Exception {
121         initMocks(this);
122         final ModificationCache cache = new ModificationCache();
123         doReturn(cache).when(ctx).getModificationCache();
124         doReturn(mappingContext).when(ctx).getMappingContext();
125
126         bdContext = new NamingContext("generatedBdName", BD_CTX_NAME);
127         readerRegistry = getVppStateReader(api, bdContext);
128     }
129
130     private static Version getVersion() {
131         return new VersionBuilder()
132             .setName("test")
133             .setBuildDirectory("1")
134             .setBranch("2")
135             .setBuildDate("3")
136             .setPid(0L)
137             .build();
138     }
139
140     private void whenShowVersionThenReturn(final Version version) {
141         final ShowVersionReply reply = new ShowVersionReply();
142         reply.buildDate = version.getBuildDate().getBytes();
143         reply.program = version.getName().getBytes();
144         reply.version = version.getBranch().getBytes();
145         reply.buildDirectory = version.getBuildDirectory().getBytes();
146         when(api.showVersion(any(ShowVersion.class))).thenReturn(future(reply));
147         // Version Customizer uses ControlPing to obtain PID
148         when(api.send(any(ControlPing.class))).thenReturn(future(new ControlPingReply()));
149     }
150
151     private void whenL2FibTableDumpThenReturn(final List<L2FibTableEntry> entryList) {
152         final L2FibTableEntryReplyDump reply = new L2FibTableEntryReplyDump();
153         reply.l2FibTableEntry = entryList;
154         when(api.l2FibTableDump(any(L2FibTableDump.class))).thenReturn(future(reply));
155     }
156
157     private void whenBridgeDomainDumpThenReturn(final List<BridgeDomainDetails> bdList) {
158         final BridgeDomainDetailsReplyDump reply = new BridgeDomainDetailsReplyDump();
159         reply.bridgeDomainDetails = bdList;
160
161         doAnswer(invocation -> {
162             BridgeDomainDump request = (BridgeDomainDump) invocation.getArguments()[0];
163             if (request.bdId == -1) {
164                 reply.bridgeDomainDetails = bdList;
165             } else {
166                 reply.bridgeDomainDetails = Collections.singletonList(bdList.get(request.bdId));
167             }
168             return future(reply);
169         }).when(api).bridgeDomainDump(any(BridgeDomainDump.class));
170     }
171
172     @Test
173     public void testReadAll() throws Exception {
174         final Version version = getVersion();
175         whenShowVersionThenReturn(version);
176
177         final BridgeDomainDetails bridgeDomainDetails = new BridgeDomainDetails();
178         final BridgeDomainDetails bridgeDomainDetails2 = new BridgeDomainDetails();
179         bridgeDomainDetails2.bdId = 1;
180
181         final List<BridgeDomainDetails> bdList = Arrays.asList(bridgeDomainDetails, bridgeDomainDetails2);
182         mockBdMapping(bridgeDomainDetails, "bd1");
183         mockBdMapping(bridgeDomainDetails2, "bd2");
184
185         whenBridgeDomainDumpThenReturn(bdList);
186
187         final Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> dataObjects =
188             readerRegistry.readAll(ctx);
189         assertEquals(dataObjects.size(), 1);
190         final VppState dataObject =
191             (VppState) Iterables.getOnlyElement(dataObjects.get(Iterables.getOnlyElement(dataObjects.keySet())));
192         assertEquals(version, dataObject.getVersion());
193         assertEquals(2, dataObject.getBridgeDomains().getBridgeDomain().size());
194     }
195
196     @Test
197     public void testReadSpecific() throws Exception {
198         final Version version = getVersion();
199         whenShowVersionThenReturn(version);
200         whenBridgeDomainDumpThenReturn(Collections.emptyList());
201
202         final Optional<? extends DataObject> read = readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx);
203         assertTrue(read.isPresent());
204         assertEquals(version, ((VppState) read.get()).getVersion());
205     }
206
207     @Test
208     public void testReadBridgeDomains() throws Exception {
209         final Version version = getVersion();
210         whenShowVersionThenReturn(version);
211         final BridgeDomainDetails details = new BridgeDomainDetails();
212         whenBridgeDomainDumpThenReturn(Collections.singletonList(details));
213
214         mockBdMapping(details, "bdn1");
215         VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
216
217         Optional<? extends DataObject> read =
218             readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class), ctx);
219         assertTrue(read.isPresent());
220         assertEquals(readRoot.getBridgeDomains(), read.get());
221     }
222
223     /**
224      * L2fib does not have a dedicated reader, relying on auto filtering
225      */
226     @Test
227     @Ignore("L2 FIB was moved to dedicated customizer. TODO: add infra test that covers such case")
228     @SuppressWarnings("unchecked")
229     public void testReadL2Fib() throws Exception {
230         final BridgeDomainDetails bd = new BridgeDomainDetails();
231         bd.bdId = 0;
232         final String bdName = "bdn1";
233         mockBdMapping(bd, bdName);
234         defineMapping(mappingContext, "eth1", 0, "ifc-test-instance");
235
236         whenBridgeDomainDumpThenReturn(Collections.singletonList(bd));
237         final L2FibTableEntry l2FibEntry = new L2FibTableEntry();
238         l2FibEntry.bdId = 0;
239         l2FibEntry.mac = 0x0605040302010000L;
240         whenL2FibTableDumpThenReturn(Collections.singletonList(l2FibEntry));
241
242         // Deep child without a dedicated reader with specific l2fib key
243         final InstanceIdentifier<? extends DataObject> idExisting =
244             InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
245                 BridgeDomain.class, new BridgeDomainKey("bdn1")).child(L2FibTable.class)
246                 .child(L2FibEntry.class, new L2FibEntryKey(new PhysAddress("01:02:03:04:05:06")));
247         Optional<? extends DataObject> read =
248             readerRegistry.read(idExisting, ctx);
249         assertTrue(read.isPresent());
250
251         // non existing l2fib
252         final InstanceIdentifier<? extends DataObject> idNonExisting =
253             InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
254                 BridgeDomain.class, new BridgeDomainKey("bdn1")).child(L2FibTable.class)
255                 .child(L2FibEntry.class, new L2FibEntryKey(new PhysAddress("FF:FF:FF:04:05:06")));
256         read = readerRegistry.read(idNonExisting, ctx);
257         assertFalse(read.isPresent());
258     }
259
260     private void mockBdMapping(final BridgeDomainDetails bd, final String bdName) {
261         defineMapping(mappingContext, bdName, bd.bdId, BD_CTX_NAME);
262     }
263
264     @Test
265     public void testReadBridgeDomainAll() throws Exception {
266         final Version version = getVersion();
267         whenShowVersionThenReturn(version);
268         final BridgeDomainDetails details = new BridgeDomainDetails();
269         whenBridgeDomainDumpThenReturn(Collections.singletonList(details));
270         mockBdMapping(details, "bd2");
271
272         VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
273
274         final GenericListReader<BridgeDomain, BridgeDomainKey, BridgeDomainBuilder> bridgeDomainReader =
275             getBridgeDomainReader(api, bdContext);
276
277         final List<BridgeDomain> read =
278             bridgeDomainReader.readList(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
279                 BridgeDomain.class), ctx);
280
281         assertEquals(readRoot.getBridgeDomains().getBridgeDomain(), read);
282     }
283
284     @Test
285     public void testReadBridgeDomain() throws Exception {
286         final BridgeDomainDetails bd = new BridgeDomainDetails();
287         bd.bdId = 0;
288         final String bdName = "bdn1";
289         mockBdMapping(bd, bdName);
290
291         whenBridgeDomainDumpThenReturn(Collections.singletonList(bd));
292         whenShowVersionThenReturn(getVersion());
293
294         VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
295
296         final Optional<? extends DataObject> read =
297             readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
298                 BridgeDomain.class, new BridgeDomainKey(bdName)), ctx);
299
300         assertTrue(read.isPresent());
301         assertEquals(readRoot.getBridgeDomains().getBridgeDomain().stream().filter(
302             input -> input.getKey().getName().equals(bdName)).findFirst().get(),
303             read.get());
304     }
305
306     @Test(expected = ReadFailedException.class)
307     public void testReadBridgeDomainNotExisting() throws Exception {
308         final String nonExistingBdName = "NOT EXISTING";
309         noMappingDefined(mappingContext, nonExistingBdName, BD_CTX_NAME);
310
311         readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
312             BridgeDomain.class, new BridgeDomainKey(nonExistingBdName)), ctx);
313     }
314
315     @Test
316     public void testReadVersion() throws Exception {
317         whenShowVersionThenReturn(getVersion());
318         whenBridgeDomainDumpThenReturn(Collections.emptyList());
319         VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get();
320
321         Optional<? extends DataObject> read =
322             readerRegistry.read(InstanceIdentifier.create(VppState.class).child(Version.class), ctx);
323         assertTrue(read.isPresent());
324         assertEquals(readRoot.getVersion(), read.get());
325     }
326 }