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.Mockito.mock;
12 import static org.mockito.Mockito.when;
14 import java.time.Instant;
15 import java.util.ArrayList;
16 import java.util.Collection;
18 import org.junit.AfterClass;
19 import org.junit.BeforeClass;
20 import org.junit.Test;
21 import org.junit.runner.RunWith;
22 import org.mockito.junit.MockitoJUnitRunner;
23 import org.opendaylight.mdsal.dom.api.DOMNotification;
24 import org.opendaylight.restconf.nb.rfc8040.TestUtils;
25 import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.common.QNameModule;
28 import org.opendaylight.yangtools.yang.common.Revision;
29 import org.opendaylight.yangtools.yang.common.XMLNamespace;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
33 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
36 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
38 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
39 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
40 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
41 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
42 import org.xmlunit.assertj.XmlAssert;
44 @RunWith(MockitoJUnitRunner.StrictStubs.class)
45 public class XmlNotificationListenerTest {
46 private static final QNameModule MODULE =
47 QNameModule.create(XMLNamespace.of("notifi:mod"), Revision.of("2016-11-23"));
49 private static EffectiveModelContext SCHEMA_CONTEXT;
52 public static void beforeClass() throws Exception {
53 SCHEMA_CONTEXT = TestUtils.loadSchemaContext("/notifications");
57 public static void afterClass() {
58 SCHEMA_CONTEXT = null;
62 public void notifi_leafTest() throws Exception {
63 final Absolute schemaPathNotifi = Absolute.of(QName.create(MODULE, "notifi-leaf"));
65 final DOMNotification notificationData = mock(DOMNotification.class);
67 final LeafNode<String> leaf = mockLeaf(QName.create(MODULE, "lf"));
68 final ContainerNode notifiBody = mockCont(schemaPathNotifi.lastNodeIdentifier(), leaf);
70 when(notificationData.getType()).thenReturn(schemaPathNotifi);
71 when(notificationData.getBody()).thenReturn(notifiBody);
73 final String result = prepareXmlResult(notificationData, schemaPathNotifi);
75 final String control = "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">"
76 + "<eventTime>2020-06-29T14:23:46.086855+02:00</eventTime><notifi-leaf xmlns=\"notifi:mod\">"
77 + "<lf>value</lf></notifi-leaf></notification>";
79 assertXmlMatches(result, control);
83 public void notifi_cont_leafTest() throws Exception {
84 final Absolute schemaPathNotifi = Absolute.of(QName.create(MODULE, "notifi-cont"));
86 final DOMNotification notificationData = mock(DOMNotification.class);
88 final LeafNode<String> leaf = mockLeaf(QName.create(MODULE, "lf"));
89 final ContainerNode cont = mockCont(QName.create(MODULE, "cont"), leaf);
90 final ContainerNode notifiBody = mockCont(schemaPathNotifi.lastNodeIdentifier(), cont);
92 when(notificationData.getType()).thenReturn(schemaPathNotifi);
93 when(notificationData.getBody()).thenReturn(notifiBody);
95 final String result = prepareXmlResult(notificationData, schemaPathNotifi);
97 final String control = "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">"
98 + "<eventTime>2020-06-29T14:23:46.086855+02:00</eventTime><notifi-cont xmlns=\"notifi:mod\">"
99 + "<cont><lf>value</lf></cont></notifi-cont></notification>";
101 assertXmlMatches(result, control);
105 public void notifi_list_Test() throws Exception {
106 final Absolute schemaPathNotifi = Absolute.of(QName.create(MODULE, "notifi-list"));
108 final DOMNotification notificationData = mock(DOMNotification.class);
110 final LeafNode<String> leaf = mockLeaf(QName.create(MODULE, "lf"));
111 final MapEntryNode entry = mockMapEntry(QName.create(MODULE, "lst"), leaf);
112 final ContainerNode notifiBody = mockCont(schemaPathNotifi.lastNodeIdentifier(), Builders.mapBuilder()
113 .withNodeIdentifier(NodeIdentifier.create(QName.create(MODULE, "lst")))
117 when(notificationData.getType()).thenReturn(schemaPathNotifi);
118 when(notificationData.getBody()).thenReturn(notifiBody);
120 final String result = prepareXmlResult(notificationData, schemaPathNotifi);
122 final String control = "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">"
123 + "<eventTime>2020-06-29T14:23:46.086855+02:00</eventTime><notifi-list xmlns=\"notifi:mod\">"
124 + "<lst><lf>value</lf></lst></notifi-list></notification>";
126 assertXmlMatches(result, control);
130 public void notifi_grpTest() throws Exception {
131 final Absolute schemaPathNotifi = Absolute.of(QName.create(MODULE, "notifi-grp"));
133 final DOMNotification notificationData = mock(DOMNotification.class);
135 final LeafNode<String> leaf = mockLeaf(QName.create(MODULE, "lf"));
136 final ContainerNode notifiBody = mockCont(schemaPathNotifi.lastNodeIdentifier(), leaf);
138 when(notificationData.getType()).thenReturn(schemaPathNotifi);
139 when(notificationData.getBody()).thenReturn(notifiBody);
141 final String result = prepareXmlResult(notificationData, schemaPathNotifi);
143 final String control = "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">"
144 + "<eventTime>2020-06-29T14:23:46.086855+02:00</eventTime><notifi-grp xmlns=\"notifi:mod\">"
145 + "<lf>value</lf></notifi-grp></notification>";
147 assertXmlMatches(result, control);
151 public void notifi_augmTest() throws Exception {
152 final Absolute schemaPathNotifi = Absolute.of(QName.create(MODULE, "notifi-augm"));
154 final DOMNotification notificationData = mock(DOMNotification.class);
156 final LeafNode<String> leaf = mockLeaf(QName.create(MODULE, "lf-augm"));
157 final AugmentationNode augm = mockAugm(leaf);
158 final ContainerNode notifiBody = mockCont(schemaPathNotifi.lastNodeIdentifier(), augm);
160 when(notificationData.getType()).thenReturn(schemaPathNotifi);
161 when(notificationData.getBody()).thenReturn(notifiBody);
163 final String result = prepareXmlResult(notificationData, schemaPathNotifi);
165 final String control = "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">"
166 + "<eventTime>2020-06-29T14:23:46.086855+02:00</eventTime><notifi-augm xmlns=\"notifi:mod\">"
167 + "<lf-augm>value</lf-augm></notifi-augm></notification>";
169 assertXmlMatches(result, control);
172 private static void assertXmlMatches(final String result, final String control) {
173 XmlAssert.assertThat(result).and(control)
174 // text values have localName null but we want to compare those, ignore only nodes that have localName
175 // with eventTime value
176 .withNodeFilter(node -> node.getLocalName() == null || !node.getLocalName().equals("eventTime"))
180 private static AugmentationNode mockAugm(final LeafNode<String> leaf) {
181 final AugmentationNode augm = mock(AugmentationNode.class);
182 final AugmentationIdentifier augmId = new AugmentationIdentifier(Set.of(leaf.getIdentifier().getNodeType()));
183 when(augm.getIdentifier()).thenReturn(augmId);
185 final Collection<DataContainerChild> childs = new ArrayList<>();
188 when(augm.body()).thenReturn(childs);
192 private static MapEntryNode mockMapEntry(final QName entryQName, final LeafNode<String> leaf) {
193 return Builders.mapEntryBuilder()
194 .withNodeIdentifier(NodeIdentifierWithPredicates.of(entryQName, leaf.getIdentifier().getNodeType(),
200 private static ContainerNode mockCont(final QName contQName, final DataContainerChild child) {
201 return Builders.containerBuilder()
202 .withNodeIdentifier(NodeIdentifier.create(contQName))
207 private static LeafNode<String> mockLeaf(final QName leafQName) {
208 return ImmutableNodes.leafNode(leafQName, "value");
211 private static String prepareXmlResult(final DOMNotification notificationData, final Absolute schemaPathNotifi)
213 final NotificationListenerAdapter notifiAdapter = ListenersBroker.getInstance().registerNotificationListener(
214 schemaPathNotifi, "xml-stream", NotificationOutputTypeGrouping.NotificationOutputType.XML);
215 return notifiAdapter.formatter().eventData(SCHEMA_CONTEXT, notificationData, Instant.now(), false, false).get();