f26f40e853be9a0d34f013c0b72294345ad76be2
[netconf.git] /
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.restconf.nb.rfc8040.monitoring;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertTrue;
13
14 import java.net.URI;
15 import java.time.Instant;
16 import java.time.OffsetDateTime;
17 import java.time.ZoneId;
18 import java.time.format.DateTimeFormatter;
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.Map;
22 import org.junit.BeforeClass;
23 import org.junit.Test;
24 import org.opendaylight.restconf.nb.rfc8040.Rfc8040.IetfYangLibrary;
25 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
26 import org.opendaylight.restconf.nb.rfc8040.legacy.SchemaContextHandler;
27 import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.module.Deviation;
29 import org.opendaylight.yangtools.yang.common.QName;
30 import org.opendaylight.yangtools.yang.common.Revision;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
32 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
36 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
37 import org.opendaylight.yangtools.yang.model.api.Module;
38 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 /**
43  * Unit tests for {@link RestconfStateStreams}.
44  */
45 public class RestconfStateStreamsTest {
46     private static final Logger LOG = LoggerFactory.getLogger(RestconfStateStreamsTest.class);
47
48     private static Collection<? extends Module> modules;
49     private static EffectiveModelContext schemaContext;
50     private static EffectiveModelContext schemaContextMonitoring;
51     private static Collection<? extends Module> modulesRest;
52
53     @BeforeClass
54     public static void loadTestSchemaContextAndModules() throws Exception {
55         // FIXME: assemble these from dependencies
56         schemaContext =
57                 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/modules/restconf-module-testing"));
58         schemaContextMonitoring = YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/modules"));
59         modules = schemaContextMonitoring.getModules();
60         modulesRest = YangParserTestUtils
61                 .parseYangFiles(TestRestconfUtils.loadFiles("/modules/restconf-module-testing")).getModules();
62     }
63
64     /**
65      * Test of writing modules into {@link RestconfModule#MODULE_LIST_SCHEMA_NODE} and checking if modules were
66      * correctly written.
67      */
68     @Test
69     public void restconfMappingNodeTest() {
70         // write modules into list module in Restconf
71         final ContainerNode mods = SchemaContextHandler.mapModulesByIetfYangLibraryYang(modules, schemaContext, "1");
72
73         // verify loaded modules
74         verifyLoadedModules(mods);
75         // verify deviations
76         verifyDeviations(mods);
77     }
78
79     @Test
80     public void toStreamEntryNodeTest() throws Exception {
81         final YangInstanceIdentifier path = ParserIdentifier.toInstanceIdentifier(
82                 "nested-module:depth1-cont/depth2-leaf1", schemaContextMonitoring, null).getInstanceIdentifier();
83         final Instant start = Instant.now();
84         final String outputType = "XML";
85         final URI uri = new URI("uri");
86         final String streamName = "/nested-module:depth1-cont/depth2-leaf1";
87
88         final Map<QName, Object> map = prepareMap(streamName, uri, start, outputType);
89         final MapEntryNode mappedData = RestconfStateStreams.dataChangeStreamEntry(path, start, outputType, uri,
90             schemaContextMonitoring, streamName);
91         assertMappedData(map, mappedData);
92     }
93
94     @Test
95     public void toStreamEntryNodeNotifiTest() throws Exception {
96         final Instant start = Instant.now();
97         final String outputType = "JSON";
98         final URI uri = new URI("uri");
99
100         final Map<QName, Object> map = prepareMap("notifi", uri, start, outputType);
101         map.put(RestconfStateStreams.DESCRIPTION_QNAME, "Notifi");
102
103         final MapEntryNode mappedData = RestconfStateStreams.notificationStreamEntry(schemaContextMonitoring,
104             QName.create("urn:nested:module", "2014-06-03", "notifi"), start, outputType, uri);
105         assertMappedData(map, mappedData);
106     }
107
108     private static Map<QName, Object> prepareMap(final String name, final URI uri, final Instant start,
109             final String outputType) {
110         final Map<QName, Object> map = new HashMap<>();
111         map.put(RestconfStateStreams.NAME_QNAME, name);
112         map.put(RestconfStateStreams.LOCATION_QNAME, uri.toString());
113         map.put(RestconfStateStreams.REPLAY_SUPPORT_QNAME, Boolean.TRUE);
114         map.put(RestconfStateStreams.REPLAY_LOG_CREATION_TIME, DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(
115             OffsetDateTime.ofInstant(start, ZoneId.systemDefault())));
116         map.put(RestconfStateStreams.ENCODING_QNAME, outputType);
117         return map;
118     }
119
120     private static void assertMappedData(final Map<QName, Object> map, final MapEntryNode mappedData) {
121         assertNotNull(mappedData);
122         for (var child : mappedData.body()) {
123             if (child instanceof LeafNode<?> leaf) {
124                 assertTrue(map.containsKey(leaf.name().getNodeType()));
125                 assertEquals(map.get(leaf.name().getNodeType()), leaf.body());
126             }
127         }
128     }
129
130     /**
131      * Verify whether the loaded modules contain any deviations.
132      *
133      * @param containerNode
134      *             modules
135      */
136     private static void verifyDeviations(final ContainerNode containerNode) {
137         int deviationsFound = 0;
138         for (var child : containerNode.body()) {
139             if (child instanceof MapNode mapChild) {
140                 for (var mapEntryNode : mapChild.body()) {
141                     for (var dataContainerChild : mapEntryNode.body()) {
142                         if (dataContainerChild.name().getNodeType().equals(Deviation.QNAME)) {
143                             deviationsFound++;
144                         }
145                     }
146                 }
147             }
148         }
149         assertTrue(deviationsFound > 0);
150     }
151
152     /**
153      * Verify loaded modules.
154      *
155      * @param containerNode
156      *             modules
157      */
158     private static void verifyLoadedModules(final ContainerNode containerNode) {
159         final Map<String, String> loadedModules = new HashMap<>();
160
161         for (var child : containerNode.body()) {
162             if (child instanceof LeafNode) {
163                 assertEquals(IetfYangLibrary.MODULE_SET_ID_LEAF_QNAME, child.name().getNodeType());
164             }
165             if (child instanceof MapNode mapChild) {
166                 assertEquals(IetfYangLibrary.MODULE_QNAME_LIST, child.name().getNodeType());
167                 for (var mapEntryNode : mapChild.body()) {
168                     String name = "";
169                     String revision = "";
170                     for (var dataContainerChild : mapEntryNode.body()) {
171                         switch (dataContainerChild.name().getNodeType().getLocalName()) {
172                             case "name":
173                                 name = String.valueOf(dataContainerChild.body());
174                                 break;
175                             case "revision":
176                                 revision = String.valueOf(dataContainerChild.body());
177                                 break;
178                             default :
179                                 LOG.info("Unknown local name '{}' of node.",
180                                     dataContainerChild.name().getNodeType().getLocalName());
181                                 break;
182                         }
183                     }
184                     loadedModules.put(name, revision);
185                 }
186             }
187         }
188
189         verifyLoadedModules(modulesRest, loadedModules);
190     }
191
192     /**
193      * Verify if correct modules were loaded into Restconf module by comparison with modules from
194      * <code>SchemaContext</code>.
195      * @param expectedModules Modules from <code>SchemaContext</code>
196      * @param loadedModules Loaded modules into Restconf module
197      */
198     private static void verifyLoadedModules(final Collection<? extends Module> expectedModules,
199             final Map<String, String> loadedModules) {
200         assertEquals("Number of loaded modules is not as expected", expectedModules.size(), loadedModules.size());
201         for (final Module m : expectedModules) {
202             final String name = m.getName();
203
204             final String revision = loadedModules.get(name);
205             assertNotNull("Expected module not found", revision);
206             assertEquals("Incorrect revision of loaded module", Revision.ofNullable(revision), m.getRevision());
207
208             loadedModules.remove(name);
209         }
210     }
211 }