2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.restconf.nb.rfc8040.utils.mapping;
10 import static org.hamcrest.CoreMatchers.equalTo;
11 import static org.hamcrest.MatcherAssert.assertThat;
12 import static org.hamcrest.Matchers.containsInAnyOrder;
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertNotNull;
15 import static org.junit.Assert.assertTrue;
18 import java.time.Instant;
19 import java.time.OffsetDateTime;
20 import java.time.ZoneId;
21 import java.time.format.DateTimeFormatter;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.List;
27 import org.junit.BeforeClass;
28 import org.junit.Test;
29 import org.opendaylight.restconf.nb.rfc8040.Rfc8040.IetfYangLibrary;
30 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
31 import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
32 import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.RestconfState;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.restconf.state.Capabilities;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.module.Deviation;
36 import org.opendaylight.yangtools.yang.common.QName;
37 import org.opendaylight.yangtools.yang.common.Revision;
38 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
39 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
41 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
43 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
44 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
45 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
46 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
47 import org.opendaylight.yangtools.yang.model.api.Module;
48 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
53 * Unit tests for {@link RestconfMappingNodeUtil}.
55 public class RestconfMappingNodeUtilTest {
56 private static final Logger LOG = LoggerFactory.getLogger(RestconfMappingNodeUtilTest.class);
58 private static Collection<? extends Module> modules;
59 private static EffectiveModelContext schemaContext;
60 private static EffectiveModelContext schemaContextMonitoring;
61 private static Collection<? extends Module> modulesRest;
64 public static void loadTestSchemaContextAndModules() throws Exception {
65 // FIXME: assemble these from dependencies
67 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/modules/restconf-module-testing"));
68 schemaContextMonitoring = YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/modules"));
69 modules = schemaContextMonitoring.getModules();
70 modulesRest = YangParserTestUtils
71 .parseYangFiles(TestRestconfUtils.loadFiles("/modules/restconf-module-testing")).getModules();
75 * Test of writing modules into {@link RestconfModule#MODULE_LIST_SCHEMA_NODE} and checking if modules were
79 public void restconfMappingNodeTest() {
80 // write modules into list module in Restconf
81 final ContainerNode mods = SchemaContextHandler.mapModulesByIetfYangLibraryYang(
82 RestconfMappingNodeUtilTest.modules, schemaContext, "1");
84 // verify loaded modules
85 verifyLoadedModules(mods);
87 verifyDeviations(mods);
91 public void restconfStateCapabilitesTest() {
92 final Module monitoringModule = schemaContextMonitoring.findModule(RestconfState.QNAME.getModule()).get();
93 final ContainerNode normNode = RestconfMappingNodeUtil.mapCapabilites(monitoringModule);
94 assertNotNull(normNode);
95 final List<Object> listOfValues = new ArrayList<>();
97 for (final DataContainerChild child : normNode.body()) {
98 if (child.getIdentifier().getNodeType().equals(Capabilities.QNAME)) {
99 for (final DataContainerChild dataContainerChild : ((ContainerNode) child).body()) {
100 for (final Object entry : ((LeafSetNode<?>) dataContainerChild).body()) {
101 listOfValues.add(((LeafSetEntryNode<?>) entry).body());
107 assertThat(listOfValues, containsInAnyOrder(
108 equalTo("urn:ietf:params:restconf:capability:depth:1.0"),
109 equalTo("urn:ietf:params:restconf:capability:fields:1.0"),
110 equalTo("urn:ietf:params:restconf:capability:filter:1.0"),
111 equalTo("urn:ietf:params:restconf:capability:replay:1.0"),
112 equalTo("urn:ietf:params:restconf:capability:with-defaults:1.0")));
116 public void toStreamEntryNodeTest() throws Exception {
117 final YangInstanceIdentifier path = ParserIdentifier.toInstanceIdentifier(
118 "nested-module:depth1-cont/depth2-leaf1", schemaContextMonitoring, null).getInstanceIdentifier();
119 final Instant start = Instant.now();
120 final String outputType = "XML";
121 final URI uri = new URI("uri");
122 final String streamName = "/nested-module:depth1-cont/depth2-leaf1";
124 final Map<QName, Object> map = prepareMap(streamName, uri, start, outputType);
125 final MapEntryNode mappedData = RestconfMappingNodeUtil.mapDataChangeNotificationStreamByIetfRestconfMonitoring(
126 path, start, outputType, uri, schemaContextMonitoring, streamName);
127 assertMappedData(map, mappedData);
131 public void toStreamEntryNodeNotifiTest() throws Exception {
132 final Instant start = Instant.now();
133 final String outputType = "JSON";
134 final URI uri = new URI("uri");
136 final Map<QName, Object> map = prepareMap("notifi", uri, start, outputType);
137 map.put(RestconfMappingNodeUtil.DESCRIPTION_QNAME, "Notifi");
139 final QName notifiQName = QName.create("urn:nested:module", "2014-06-03", "notifi");
140 final MapEntryNode mappedData = RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring(
141 notifiQName, schemaContextMonitoring.getNotifications(), start, outputType, uri);
142 assertMappedData(map, mappedData);
145 private static Map<QName, Object> prepareMap(final String name, final URI uri, final Instant start,
146 final String outputType) {
147 final Map<QName, Object> map = new HashMap<>();
148 map.put(RestconfMappingNodeUtil.NAME_QNAME, name);
149 map.put(RestconfMappingNodeUtil.LOCATION_QNAME, uri.toString());
150 map.put(RestconfMappingNodeUtil.REPLAY_SUPPORT_QNAME, Boolean.TRUE);
151 map.put(RestconfMappingNodeUtil.REPLAY_LOG_CREATION_TIME, DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(
152 OffsetDateTime.ofInstant(start, ZoneId.systemDefault())));
153 map.put(RestconfMappingNodeUtil.ENCODING_QNAME, outputType);
157 private static void assertMappedData(final Map<QName, Object> map, final MapEntryNode mappedData) {
158 assertNotNull(mappedData);
159 for (final DataContainerChild child : mappedData.body()) {
160 if (child instanceof LeafNode) {
161 final LeafNode<?> leaf = (LeafNode<?>) child;
162 assertTrue(map.containsKey(leaf.getIdentifier().getNodeType()));
163 assertEquals(map.get(leaf.getIdentifier().getNodeType()), leaf.body());
169 * Verify whether the loaded modules contain any deviations.
171 * @param containerNode
174 private static void verifyDeviations(final ContainerNode containerNode) {
175 int deviationsFound = 0;
176 for (final DataContainerChild child : containerNode.body()) {
177 if (child instanceof MapNode) {
178 for (final MapEntryNode mapEntryNode : ((MapNode) child).body()) {
179 for (final DataContainerChild dataContainerChild : mapEntryNode.body()) {
180 if (dataContainerChild.getIdentifier().getNodeType().equals(Deviation.QNAME)) {
187 assertTrue(deviationsFound > 0);
191 * Verify loaded modules.
193 * @param containerNode
196 private static void verifyLoadedModules(final ContainerNode containerNode) {
197 final Map<String, String> loadedModules = new HashMap<>();
199 for (final DataContainerChild child : containerNode.body()) {
200 if (child instanceof LeafNode) {
201 assertEquals(IetfYangLibrary.MODULE_SET_ID_LEAF_QNAME, child.getIdentifier().getNodeType());
203 if (child instanceof MapNode) {
204 assertEquals(IetfYangLibrary.MODULE_QNAME_LIST, child.getIdentifier().getNodeType());
205 for (final MapEntryNode mapEntryNode : ((MapNode) child).body()) {
207 String revision = "";
208 for (final DataContainerChild dataContainerChild : mapEntryNode.body()) {
209 switch (dataContainerChild.getIdentifier().getNodeType().getLocalName()) {
211 name = String.valueOf(dataContainerChild.body());
214 revision = String.valueOf(dataContainerChild.body());
217 LOG.info("Unknown local name '{}' of node.",
218 dataContainerChild.getIdentifier().getNodeType().getLocalName());
222 loadedModules.put(name, revision);
227 verifyLoadedModules(RestconfMappingNodeUtilTest.modulesRest, loadedModules);
231 * Verify if correct modules were loaded into Restconf module by comparison with modules from
232 * <code>SchemaContext</code>.
233 * @param expectedModules Modules from <code>SchemaContext</code>
234 * @param loadedModules Loaded modules into Restconf module
236 private static void verifyLoadedModules(final Collection<? extends Module> expectedModules,
237 final Map<String, String> loadedModules) {
238 assertEquals("Number of loaded modules is not as expected", expectedModules.size(), loadedModules.size());
239 for (final Module m : expectedModules) {
240 final String name = m.getName();
242 final String revision = loadedModules.get(name);
243 assertNotNull("Expected module not found", revision);
244 assertEquals("Incorrect revision of loaded module", Revision.ofNullable(revision), m.getRevision());
246 loadedModules.remove(name);