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