2 * Copyright (c) 2020 Pantheon.tech, s.r.o. 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
9 package org.opendaylight.restconf.nb.rfc8040.streams.listeners;
11 import static org.mockito.ArgumentMatchers.any;
12 import static org.mockito.Mockito.mock;
13 import static org.mockito.Mockito.when;
14 import static org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
15 import static org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
16 import static org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
17 import static org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
19 import com.google.common.collect.Lists;
21 import java.time.Instant;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Optional;
25 import org.junit.AfterClass;
26 import org.junit.BeforeClass;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.mockito.junit.MockitoJUnitRunner;
30 import org.opendaylight.mdsal.dom.api.DOMNotification;
31 import org.opendaylight.restconf.nb.rfc8040.TestUtils;
32 import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping;
33 import org.opendaylight.yangtools.util.SingletonSet;
34 import org.opendaylight.yangtools.yang.common.QName;
35 import org.opendaylight.yangtools.yang.common.QNameModule;
36 import org.opendaylight.yangtools.yang.common.Revision;
37 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
40 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
43 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
44 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
45 import org.xmlunit.assertj.XmlAssert;
47 @RunWith(MockitoJUnitRunner.StrictStubs.class)
48 public class XmlNotificationListenerTest {
49 private static final QNameModule MODULE = QNameModule.create(URI.create("notifi:mod"), Revision.of("2016-11-23"));
51 private static EffectiveModelContext SCHEMA_CONTEXT;
54 public static void beforeClass() throws Exception {
55 SCHEMA_CONTEXT = TestUtils.loadSchemaContext("/notifications");
59 public static void afterClass() {
60 SCHEMA_CONTEXT = null;
64 public void notifi_leafTest() throws Exception {
65 final Absolute schemaPathNotifi = Absolute.of(QName.create(MODULE, "notifi-leaf"));
67 final DOMNotification notificationData = mock(DOMNotification.class);
69 final LeafNode<String> leaf = mockLeaf(QName.create(MODULE, "lf"));
70 final ContainerNode notifiBody = mockCont(schemaPathNotifi.lastNodeIdentifier(), leaf);
72 when(notificationData.getType()).thenReturn(schemaPathNotifi);
73 when(notificationData.getBody()).thenReturn(notifiBody);
75 final String result = prepareXmlResult(notificationData, schemaPathNotifi);
77 final String control = "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">"
78 + "<eventTime>2020-06-29T14:23:46.086855+02:00</eventTime><notifi-leaf xmlns=\"notifi:mod\">"
79 + "<lf>value</lf></notifi-leaf></notification>";
81 assertXmlMatches(result, control);
85 public void notifi_cont_leafTest() throws Exception {
86 final Absolute schemaPathNotifi = Absolute.of(QName.create(MODULE, "notifi-cont"));
88 final DOMNotification notificationData = mock(DOMNotification.class);
90 final LeafNode<String> leaf = mockLeaf(QName.create(MODULE, "lf"));
91 final ContainerNode cont = mockCont(QName.create(MODULE, "cont"), leaf);
92 final ContainerNode notifiBody = mockCont(schemaPathNotifi.lastNodeIdentifier(), cont);
94 when(notificationData.getType()).thenReturn(schemaPathNotifi);
95 when(notificationData.getBody()).thenReturn(notifiBody);
97 final String result = prepareXmlResult(notificationData, schemaPathNotifi);
99 final String control = "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">"
100 + "<eventTime>2020-06-29T14:23:46.086855+02:00</eventTime><notifi-cont xmlns=\"notifi:mod\">"
101 + "<cont><lf>value</lf></cont></notifi-cont></notification>";
103 assertXmlMatches(result, control);
107 public void notifi_list_Test() throws Exception {
108 final Absolute schemaPathNotifi = Absolute.of(QName.create(MODULE, "notifi-list"));
110 final DOMNotification notificationData = mock(DOMNotification.class);
112 final LeafNode<String> leaf = mockLeaf(QName.create(MODULE, "lf"));
113 final MapEntryNode entry = mockMapEntry(QName.create(MODULE, "lst"), leaf);
114 final MapNode list = mockList(QName.create(MODULE, "lst"), entry);
115 final ContainerNode cont = mockCont(QName.create(MODULE, "cont"), list);
116 final ContainerNode notifiBody = mockCont(schemaPathNotifi.lastNodeIdentifier(), cont);
118 when(notificationData.getType()).thenReturn(schemaPathNotifi);
119 when(notificationData.getBody()).thenReturn(notifiBody);
121 final String result = prepareXmlResult(notificationData, schemaPathNotifi);
123 final String control = "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">"
124 + "<eventTime>2020-06-29T14:23:46.086855+02:00</eventTime><notifi-list xmlns=\"notifi:mod\">"
125 + "<notifi-list><lf><lf>value</lf></lf></notifi-list></notifi-list></notification>";
127 assertXmlMatches(result, control);
131 public void notifi_grpTest() throws Exception {
132 final Absolute schemaPathNotifi = Absolute.of(QName.create(MODULE, "notifi-grp"));
134 final DOMNotification notificationData = mock(DOMNotification.class);
136 final LeafNode<String> leaf = mockLeaf(QName.create(MODULE, "lf"));
137 final ContainerNode notifiBody = mockCont(schemaPathNotifi.lastNodeIdentifier(), leaf);
139 when(notificationData.getType()).thenReturn(schemaPathNotifi);
140 when(notificationData.getBody()).thenReturn(notifiBody);
142 final String result = prepareXmlResult(notificationData, schemaPathNotifi);
144 final String control = "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">"
145 + "<eventTime>2020-06-29T14:23:46.086855+02:00</eventTime><notifi-grp xmlns=\"notifi:mod\">"
146 + "<lf>value</lf></notifi-grp></notification>";
148 assertXmlMatches(result, control);
152 public void notifi_augmTest() throws Exception {
153 final Absolute schemaPathNotifi = Absolute.of(QName.create(MODULE, "notifi-augm"));
155 final DOMNotification notificationData = mock(DOMNotification.class);
157 final LeafNode<String> leaf = mockLeaf(QName.create(MODULE, "lf-augm"));
158 final AugmentationNode augm = mockAugm(leaf);
159 final ContainerNode notifiBody = mockCont(schemaPathNotifi.lastNodeIdentifier(), augm);
161 when(notificationData.getType()).thenReturn(schemaPathNotifi);
162 when(notificationData.getBody()).thenReturn(notifiBody);
164 final String result = prepareXmlResult(notificationData, schemaPathNotifi);
166 final String control = "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">"
167 + "<eventTime>2020-06-29T14:23:46.086855+02:00</eventTime><notifi-augm xmlns=\"notifi:mod\">"
168 + "<lf-augm>value</lf-augm></notifi-augm></notification>";
170 assertXmlMatches(result, control);
173 private static void assertXmlMatches(String result, String control) {
174 XmlAssert.assertThat(result).and(control)
175 // text values have localName null but we want to compare those, ignore only nodes that have localName
176 // with eventTime value
177 .withNodeFilter(node -> node.getLocalName() == null || !node.getLocalName().equals("eventTime"))
181 private static AugmentationNode mockAugm(final LeafNode<String> leaf) {
182 final AugmentationNode augm = mock(AugmentationNode.class);
183 final AugmentationIdentifier augmId = new AugmentationIdentifier(SingletonSet.of(leaf.getNodeType()));
184 when(augm.getIdentifier()).thenReturn(augmId);
186 final Collection<DataContainerChild<? extends PathArgument, ?>> childs = new ArrayList<>();
189 when(augm.getValue()).thenReturn(childs);
193 private static MapEntryNode mockMapEntry(final QName entryQName, final LeafNode<String> leaf) {
194 final MapEntryNode entry = mock(MapEntryNode.class);
195 final NodeIdentifierWithPredicates nodeId = NodeIdentifierWithPredicates.of(leaf.getNodeType(),
196 leaf.getNodeType(), "value");
197 when(entry.getIdentifier()).thenReturn(nodeId);
198 when(entry.getChild(any())).thenReturn(Optional.of(leaf));
200 final Collection<DataContainerChild<? extends PathArgument, ?>> childs = new ArrayList<>();
203 when(entry.getValue()).thenReturn(childs);
207 private static MapNode mockList(final QName listQName, final MapEntryNode... entries) {
208 final MapNode list = mock(MapNode.class);
209 when(list.getIdentifier()).thenReturn(NodeIdentifier.create(listQName));
210 when(list.getValue()).thenReturn(Lists.newArrayList(entries));
214 private static ContainerNode mockCont(final QName contQName,
215 final DataContainerChild<? extends PathArgument, ?> child) {
216 final ContainerNode cont = mock(ContainerNode.class);
217 when(cont.getIdentifier()).thenReturn(NodeIdentifier.create(contQName));
219 final Collection<DataContainerChild<? extends PathArgument, ?>> childs = new ArrayList<>();
221 when(cont.getValue()).thenReturn(childs);
225 private static LeafNode<String> mockLeaf(final QName leafQName) {
226 final LeafNode<String> child = mock(LeafNode.class);
227 when(child.getNodeType()).thenReturn(leafQName);
228 when(child.getIdentifier()).thenReturn(NodeIdentifier.create(leafQName));
229 when(child.getValue()).thenReturn("value");
233 private static String prepareXmlResult(final DOMNotification notificationData, final Absolute schemaPathNotifi)
235 final NotificationListenerAdapter notifiAdapter = ListenersBroker.getInstance().registerNotificationListener(
236 schemaPathNotifi, "xml-stream", NotificationOutputTypeGrouping.NotificationOutputType.XML);
237 return notifiAdapter.formatter.eventData(SCHEMA_CONTEXT, notificationData, Instant.now(), false, false).get();