2 * Copyright (c) 2017 Red Hat, 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
9 package org.opendaylight.restconf.nb.rfc8040.streams.listeners;
11 import static java.time.Instant.EPOCH;
12 import static org.junit.Assert.fail;
14 import com.google.common.util.concurrent.Uninterruptibles;
15 import java.io.IOException;
16 import java.net.URISyntaxException;
18 import java.nio.charset.StandardCharsets;
19 import java.nio.file.Files;
20 import java.nio.file.Paths;
21 import java.util.Optional;
22 import java.util.concurrent.CountDownLatch;
23 import java.util.concurrent.TimeUnit;
24 import org.json.JSONObject;
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.mockito.Mockito;
28 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
29 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
30 import org.opendaylight.controller.md.sal.binding.test.AbstractConcurrentDataBrokerTest;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
33 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
34 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
35 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
36 import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
37 import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
38 import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.PatchCont;
39 import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.patch.cont.MyList1;
40 import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.patch.cont.MyList1Builder;
41 import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.patch.cont.MyList1Key;
42 import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
45 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
46 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
47 import org.skyscreamer.jsonassert.JSONAssert;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
51 public class ListenerAdapterTest extends AbstractConcurrentDataBrokerTest {
52 private static final Logger LOG = LoggerFactory.getLogger(ListenerAdapterTest.class);
54 private static final String JSON_NOTIF_LEAVES_CREATE = "/listener-adapter-test/notif-leaves-create.json";
55 private static final String JSON_NOTIF_LEAVES_UPDATE = "/listener-adapter-test/notif-leaves-update.json";
56 private static final String JSON_NOTIF_LEAVES_DEL = "/listener-adapter-test/notif-leaves-del.json";
57 private static final String JSON_NOTIF_CREATE = "/listener-adapter-test/notif-create.json";
58 private static final String JSON_NOTIF_UPDATE = "/listener-adapter-test/notif-update.json";
59 private static final String JSON_NOTIF_DEL = "/listener-adapter-test/notif-del.json";
61 private static YangInstanceIdentifier PATCH_CONT_YIID =
62 YangInstanceIdentifier.create(new YangInstanceIdentifier.NodeIdentifier(PatchCont.QNAME));
64 private DataBroker dataBroker;
65 private DOMDataBroker domDataBroker;
66 private TransactionChainHandler transactionChainHandler;
67 private SchemaContextHandler schemaContextHandler;
70 public void setUp() throws Exception {
71 dataBroker = getDataBroker();
72 domDataBroker = getDomBroker();
73 SchemaContext sc = YangParserTestUtils.parseYangResource(
74 "/instanceidentifier/yang/instance-identifier-patch-module.yang");
76 transactionChainHandler = new TransactionChainHandler(domDataBroker.createTransactionChain(
77 Mockito.mock(TransactionChainListener.class)));
78 schemaContextHandler = new SchemaContextHandler(transactionChainHandler);
79 SchemaContextHandler.setSchemaContext(sc);
82 class ListenerAdapterTester extends ListenerAdapter {
84 private volatile String lastNotification;
85 private CountDownLatch notificationLatch = new CountDownLatch(1);
87 ListenerAdapterTester(final YangInstanceIdentifier path, final String streamName,
88 final NotificationOutputTypeGrouping.NotificationOutputType outputType,
89 final boolean leafNodesOnly) {
90 super(path, streamName, outputType);
91 setQueryParams(EPOCH, Optional.empty(), Optional.empty(), leafNodesOnly);
95 protected void post(final Event event) {
96 this.lastNotification = event.getData();
97 notificationLatch.countDown();
100 public void assertGot(final String json) {
101 if (!Uninterruptibles.awaitUninterruptibly(notificationLatch, 5, TimeUnit.SECONDS)) {
102 fail("Timed out waiting for notification for: " + json);
105 LOG.info("lastNotification: {}", lastNotification);
106 String withFakeDate = withFakeDate(lastNotification);
107 LOG.info("Comparing: \n{}\n{}", json, withFakeDate);
109 JSONAssert.assertEquals(json, withFakeDate, false);
110 this.lastNotification = null;
111 notificationLatch = new CountDownLatch(1);
115 static String withFakeDate(final String in) {
116 JSONObject doc = new JSONObject(in);
117 JSONObject notification = doc.getJSONObject("notification");
118 if (notification == null) {
121 notification.put("eventTime", "someDate");
122 return doc.toString();
125 private String getNotifJson(final String path) throws IOException, URISyntaxException {
126 URL url = getClass().getResource(path);
127 byte[] bytes = Files.readAllBytes(Paths.get(url.toURI()));
128 return withFakeDate(new String(bytes, StandardCharsets.UTF_8));
132 public void testJsonNotifsLeaves() throws Exception {
133 ListenerAdapterTester adapter = new ListenerAdapterTester(PATCH_CONT_YIID, "Casey",
134 NotificationOutputTypeGrouping.NotificationOutputType.JSON, true);
135 adapter.setCloseVars(transactionChainHandler, schemaContextHandler);
137 DOMDataTreeChangeService changeService = (DOMDataTreeChangeService)
138 domDataBroker.getSupportedExtensions().get(DOMDataTreeChangeService.class);
139 DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
140 changeService.registerDataTreeChangeListener(root, adapter);
142 WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
143 MyList1Builder builder = new MyList1Builder().setMyLeaf11("Jed").setName("Althea");
144 InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
145 .child(MyList1.class, new MyList1Key("Althea"));
146 writeTransaction.put(LogicalDatastoreType.CONFIGURATION, iid, builder.build(), true);
147 writeTransaction.submit();
148 adapter.assertGot(getNotifJson(JSON_NOTIF_LEAVES_CREATE));
150 writeTransaction = dataBroker.newWriteOnlyTransaction();
151 builder = new MyList1Builder().setKey(new MyList1Key("Althea")).setMyLeaf12("Bertha");
152 writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, iid, builder.build(), true);
153 writeTransaction.submit();
154 adapter.assertGot(getNotifJson(JSON_NOTIF_LEAVES_UPDATE));
156 writeTransaction = dataBroker.newWriteOnlyTransaction();
157 writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
158 writeTransaction.submit();
159 adapter.assertGot(getNotifJson(JSON_NOTIF_LEAVES_DEL));
163 public void testJsonNotifs() throws Exception {
164 ListenerAdapterTester adapter = new ListenerAdapterTester(PATCH_CONT_YIID, "Casey",
165 NotificationOutputTypeGrouping.NotificationOutputType.JSON, false);
166 adapter.setCloseVars(transactionChainHandler, schemaContextHandler);
168 DOMDataTreeChangeService changeService = (DOMDataTreeChangeService)
169 domDataBroker.getSupportedExtensions().get(DOMDataTreeChangeService.class);
170 DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
171 changeService.registerDataTreeChangeListener(root, adapter);
173 WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
174 MyList1Builder builder = new MyList1Builder().setMyLeaf11("Jed").setName("Althea");
175 InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
176 .child(MyList1.class, new MyList1Key("Althea"));
177 writeTransaction.put(LogicalDatastoreType.CONFIGURATION, iid, builder.build(), true);
178 writeTransaction.submit();
179 adapter.assertGot(getNotifJson(JSON_NOTIF_CREATE));
181 writeTransaction = dataBroker.newWriteOnlyTransaction();
182 builder = new MyList1Builder().setKey(new MyList1Key("Althea")).setMyLeaf12("Bertha");
183 writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, iid, builder.build(), true);
184 writeTransaction.submit();
185 adapter.assertGot(getNotifJson(JSON_NOTIF_UPDATE));
187 writeTransaction = dataBroker.newWriteOnlyTransaction();
188 writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
189 writeTransaction.submit();
190 adapter.assertGot(getNotifJson(JSON_NOTIF_DEL));