453f077bee176524bda8c58f3870394dacd6b8e8
[netconf.git] / restconf / restconf-nb-bierman02 / src / test / java / org / opendaylight / netconf / sal / streams / listeners / ListenerAdapterTest.java
1 /*
2  * Copyright (c) 2017 Red Hat, 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.netconf.sal.streams.listeners;
9
10 import static java.time.Instant.EPOCH;
11
12 import java.io.IOException;
13 import java.net.URISyntaxException;
14 import java.net.URL;
15 import java.nio.charset.StandardCharsets;
16 import java.nio.file.Files;
17 import java.nio.file.Paths;
18 import java.util.Optional;
19 import org.json.JSONObject;
20 import org.junit.Before;
21 import org.junit.BeforeClass;
22 import org.junit.Test;
23 import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
24 import org.opendaylight.mdsal.binding.api.DataBroker;
25 import org.opendaylight.mdsal.binding.api.WriteTransaction;
26 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractConcurrentDataBrokerTest;
27 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
28 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
29 import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService;
30 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
31 import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
32 import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.PatchCont;
33 import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.patch.cont.MyList1;
34 import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.patch.cont.MyList1Builder;
35 import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.patch.cont.MyList1Key;
36 import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
39 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
40 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
41 import org.skyscreamer.jsonassert.JSONAssert;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 public class ListenerAdapterTest extends AbstractConcurrentDataBrokerTest {
46     private static final Logger LOG = LoggerFactory.getLogger(ListenerAdapterTest.class);
47
48     private static final String JSON_NOTIF_LEAVES_CREATE = "/listener-adapter-test/notif-leaves-create.json";
49     private static final String JSON_NOTIF_LEAVES_UPDATE =  "/listener-adapter-test/notif-leaves-update.json";
50     private static final String JSON_NOTIF_LEAVES_DEL =  "/listener-adapter-test/notif-leaves-del.json";
51     private static final String JSON_NOTIF_CREATE = "/listener-adapter-test/notif-create.json";
52     private static final String JSON_NOTIF_UPDATE = "/listener-adapter-test/notif-update.json";
53     private static final String JSON_NOTIF_DEL = "/listener-adapter-test/notif-del.json";
54     private static final String JSON_NOTIF_WITHOUT_DATA_CREATE =
55             "/listener-adapter-test/notif-without-data-create.json";
56     private static final String JSON_NOTIF_WITHOUT_DATA_UPDATE =
57             "/listener-adapter-test/notif-without-data-update.json";
58     private static final String JSON_NOTIF_WITHOUT_DATA_DELETE =
59             "/listener-adapter-test/notif-without-data-del.json";
60
61
62     private static final YangInstanceIdentifier PATCH_CONT_YIID =
63             YangInstanceIdentifier.create(new YangInstanceIdentifier.NodeIdentifier(PatchCont.QNAME));
64
65     private static EffectiveModelContext schemaContext;
66
67     private DataBroker dataBroker;
68     private DOMDataBroker domDataBroker;
69     private ControllerContext controllerContext;
70
71     @BeforeClass
72     public static void init() {
73         schemaContext = YangParserTestUtils.parseYangResource(
74                 "/instanceidentifier/yang/instance-identifier-patch-module.yang");
75     }
76
77     @Before
78     public void setUp() throws Exception {
79         dataBroker = getDataBroker();
80         domDataBroker = getDomBroker();
81         controllerContext = TestRestconfUtils.newControllerContext(schemaContext);
82     }
83
84     class ListenerAdapterTester extends ListenerAdapter {
85
86         private String lastNotification = null;
87
88         ListenerAdapterTester(final YangInstanceIdentifier path, final String streamName,
89                 final NotificationOutputTypeGrouping.NotificationOutputType outputType,
90                 final boolean leafNodesOnly, final boolean skipNotificationData) {
91             super(path, streamName, outputType, controllerContext);
92             setQueryParams(EPOCH, Optional.empty(), Optional.empty(), leafNodesOnly, skipNotificationData);
93         }
94
95         @Override
96         protected void post(final Event event) {
97             this.lastNotification = event.getData();
98         }
99
100         public void assertGot(final String json) throws Exception {
101             long start = System.currentTimeMillis();
102             while (true) {
103                 if (lastNotification != null) {
104                     break;
105                 }
106                 if (System.currentTimeMillis() - start > 1000) {
107                     throw new Exception("TIMED OUT waiting for notification with " + json);
108                 }
109                 Thread.currentThread();
110                 Thread.sleep(200);
111             }
112             LOG.debug("Comparing {} {}", json, lastNotification);
113             JSONAssert.assertEquals(json, withFakeDate(lastNotification), false);
114             this.lastNotification = null;
115         }
116     }
117
118     static String withFakeDate(final String in) {
119         JSONObject doc = new JSONObject(in);
120         JSONObject notification = doc.getJSONObject("notification");
121         if (notification == null) {
122             return in;
123         }
124         notification.put("eventTime", "someDate");
125         return doc.toString();
126     }
127
128     private String getNotifJson(final String path) throws IOException, URISyntaxException {
129         URL url = getClass().getResource(path);
130         byte[] bytes = Files.readAllBytes(Paths.get(url.toURI()));
131         return withFakeDate(new String(bytes, StandardCharsets.UTF_8));
132     }
133
134     @Test
135     public void testJsonNotifsLeaves() throws Exception {
136         ListenerAdapterTester adapter = new ListenerAdapterTester(PATCH_CONT_YIID, "Casey",
137                 NotificationOutputTypeGrouping.NotificationOutputType.JSON, true, false);
138         DOMDataTreeChangeService changeService = domDataBroker.getExtensions()
139                 .getInstance(DOMDataTreeChangeService.class);
140         DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
141         changeService.registerDataTreeChangeListener(root, adapter);
142
143         WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
144         MyList1Builder builder = new MyList1Builder().setMyLeaf11("Jed").setName("Althea");
145         InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
146                 .child(MyList1.class, new MyList1Key("Althea"));
147         writeTransaction.mergeParentStructurePut(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
148         writeTransaction.commit();
149         adapter.assertGot(getNotifJson(JSON_NOTIF_LEAVES_CREATE));
150
151         writeTransaction = dataBroker.newWriteOnlyTransaction();
152         builder = new MyList1Builder().withKey(new MyList1Key("Althea")).setMyLeaf12("Bertha");
153         writeTransaction.mergeParentStructureMerge(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
154         writeTransaction.commit();
155         adapter.assertGot(getNotifJson(JSON_NOTIF_LEAVES_UPDATE));
156
157         writeTransaction = dataBroker.newWriteOnlyTransaction();
158         writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
159         writeTransaction.commit();
160         adapter.assertGot(getNotifJson(JSON_NOTIF_LEAVES_DEL));
161     }
162
163     @Test
164     public void testJsonNotifs() throws Exception {
165         ListenerAdapterTester adapter = new ListenerAdapterTester(PATCH_CONT_YIID, "Casey",
166                 NotificationOutputTypeGrouping.NotificationOutputType.JSON, false, false);
167         DOMDataTreeChangeService changeService = domDataBroker.getExtensions()
168                 .getInstance(DOMDataTreeChangeService.class);
169         DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
170         changeService.registerDataTreeChangeListener(root, adapter);
171
172         WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
173         MyList1Builder builder = new MyList1Builder().setMyLeaf11("Jed").setName("Althea");
174         InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
175                 .child(MyList1.class, new MyList1Key("Althea"));
176         writeTransaction.mergeParentStructurePut(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
177         writeTransaction.commit();
178         adapter.assertGot(getNotifJson(JSON_NOTIF_CREATE));
179
180         writeTransaction = dataBroker.newWriteOnlyTransaction();
181         builder = new MyList1Builder().withKey(new MyList1Key("Althea")).setMyLeaf12("Bertha");
182         writeTransaction.mergeParentStructureMerge(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
183         writeTransaction.commit();
184         adapter.assertGot(getNotifJson(JSON_NOTIF_UPDATE));
185
186         writeTransaction = dataBroker.newWriteOnlyTransaction();
187         writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
188         writeTransaction.commit();
189         adapter.assertGot(getNotifJson(JSON_NOTIF_DEL));
190     }
191
192     @Test
193     public void testJsonNotifsWithoutData() throws Exception {
194         ListenerAdapterTester adapter = new ListenerAdapterTester(PATCH_CONT_YIID, "Casey",
195                 NotificationOutputTypeGrouping.NotificationOutputType.JSON, false, true);
196         DOMDataTreeChangeService changeService = domDataBroker.getExtensions()
197                 .getInstance(DOMDataTreeChangeService.class);
198         DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
199         changeService.registerDataTreeChangeListener(root, adapter);
200
201         WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
202         MyList1Builder builder = new MyList1Builder().setMyLeaf11("Jed").setName("Althea");
203         InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
204                 .child(MyList1.class, new MyList1Key("Althea"));
205         writeTransaction.mergeParentStructurePut(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
206         writeTransaction.commit();
207         adapter.assertGot(getNotifJson(JSON_NOTIF_WITHOUT_DATA_CREATE));
208
209         writeTransaction = dataBroker.newWriteOnlyTransaction();
210         builder = new MyList1Builder().withKey(new MyList1Key("Althea")).setMyLeaf12("Bertha");
211         writeTransaction.mergeParentStructureMerge(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
212         writeTransaction.commit();
213         adapter.assertGot(getNotifJson(JSON_NOTIF_WITHOUT_DATA_UPDATE));
214
215         writeTransaction = dataBroker.newWriteOnlyTransaction();
216         writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
217         writeTransaction.commit();
218         adapter.assertGot(getNotifJson(JSON_NOTIF_WITHOUT_DATA_DELETE));
219     }
220 }