Use FilterParameter for communicating its value
[netconf.git] / restconf / restconf-nb-rfc8040 / src / test / java / org / opendaylight / restconf / nb / rfc8040 / streams / listeners / ListenerAdapterTest.java
index 34116da78c9a5aac3f91056091f00db67b001afc..aa1bab668206a88070252ff53c12ce50fe2b6317 100644 (file)
@@ -7,8 +7,9 @@
  */
 package org.opendaylight.restconf.nb.rfc8040.streams.listeners;
 
-import static java.time.Instant.EPOCH;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
 
 import com.google.common.util.concurrent.Uninterruptibles;
 import java.io.IOException;
@@ -19,10 +20,12 @@ import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import org.json.JSONException;
 import org.json.JSONObject;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
-import org.mockito.Mockito;
 import org.opendaylight.mdsal.binding.api.DataBroker;
 import org.opendaylight.mdsal.binding.api.WriteTransaction;
 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractConcurrentDataBrokerTest;
@@ -31,8 +34,8 @@ import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
+import org.opendaylight.restconf.nb.rfc8040.StartTimeParameter;
 import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
-import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
 import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.PatchCont;
 import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.patch.cont.MyList1;
 import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.patch.cont.MyList1Builder;
@@ -40,11 +43,13 @@ import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.p
 import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 import org.skyscreamer.jsonassert.JSONAssert;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.xmlunit.assertj.XmlAssert;
 
 public class ListenerAdapterTest extends AbstractConcurrentDataBrokerTest {
     private static final Logger LOG = LoggerFactory.getLogger(ListenerAdapterTest.class);
@@ -55,26 +60,55 @@ public class ListenerAdapterTest extends AbstractConcurrentDataBrokerTest {
     private static final String JSON_NOTIF_CREATE = "/listener-adapter-test/notif-create.json";
     private static final String JSON_NOTIF_UPDATE = "/listener-adapter-test/notif-update.json";
     private static final String JSON_NOTIF_DEL = "/listener-adapter-test/notif-del.json";
+    private static final String JSON_NOTIF_WITHOUT_DATA_CREATE =
+            "/listener-adapter-test/notif-without-data-create.json";
+    private static final String JSON_NOTIF_WITHOUT_DATA_UPDATE =
+            "/listener-adapter-test/notif-without-data-update.json";
+    private static final String JSON_NOTIF_WITHOUT_DATA_DELETE =
+            "/listener-adapter-test/notif-without-data-del.json";
 
-    private static YangInstanceIdentifier PATCH_CONT_YIID =
-            YangInstanceIdentifier.create(new YangInstanceIdentifier.NodeIdentifier(PatchCont.QNAME));
+    private static final String XML_NOTIF_CREATE = "/listener-adapter-test/notif-create.xml";
+    private static final String XML_NOTIF_UPDATE =  "/listener-adapter-test/notif-update.xml";
+    private static final String XML_NOTIF_DEL =  "/listener-adapter-test/notif-delete.xml";
+
+    private static final String XML_NOTIF_LEAVES_CREATE = "/listener-adapter-test/notif-leaves-create.xml";
+    private static final String XML_NOTIF_LEAVES_UPDATE =  "/listener-adapter-test/notif-leaves-update.xml";
+    private static final String XML_NOTIF_LEAVES_DEL =  "/listener-adapter-test/notif-leaves-delete.xml";
+
+    private static final String XML_NOTIF_WITHOUT_DATA_CREATE =
+            "/listener-adapter-test/notif-without-data-create.xml";
+    private static final String XML_NOTIF_WITHOUT_DATA_UPDATE =
+            "/listener-adapter-test/notif-without-data-update.xml";
+    private static final String XML_NOTIF_WITHOUT_DATA_DELETE =
+            "/listener-adapter-test/notif-without-data-delete.xml";
+
+    private static final YangInstanceIdentifier PATCH_CONT_YIID =
+            YangInstanceIdentifier.create(new NodeIdentifier(PatchCont.QNAME));
+
+    private static EffectiveModelContext SCHEMA_CONTEXT;
 
     private DataBroker dataBroker;
     private DOMDataBroker domDataBroker;
-    private TransactionChainHandler transactionChainHandler;
     private SchemaContextHandler schemaContextHandler;
 
+    @BeforeClass
+    public static void beforeClass() {
+        SCHEMA_CONTEXT = YangParserTestUtils.parseYangResource(
+                "/instanceidentifier/yang/instance-identifier-patch-module.yang");
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        SCHEMA_CONTEXT = null;
+    }
+
     @Before
     public void setUp() throws Exception {
         dataBroker = getDataBroker();
         domDataBroker = getDomBroker();
-        SchemaContext sc = YangParserTestUtils.parseYangResource(
-                "/instanceidentifier/yang/instance-identifier-patch-module.yang");
 
-        transactionChainHandler = new TransactionChainHandler(domDataBroker);
-        schemaContextHandler = SchemaContextHandler.newInstance(transactionChainHandler,
-                Mockito.mock(DOMSchemaService.class));
-        schemaContextHandler.onGlobalContextUpdated(sc);
+        schemaContextHandler = new SchemaContextHandler(domDataBroker, mock(DOMSchemaService.class));
+        schemaContextHandler.onModelContextUpdated(SCHEMA_CONTEXT);
     }
 
     class ListenerAdapterTester extends ListenerAdapter {
@@ -84,70 +118,108 @@ public class ListenerAdapterTest extends AbstractConcurrentDataBrokerTest {
 
         ListenerAdapterTester(final YangInstanceIdentifier path, final String streamName,
                               final NotificationOutputTypeGrouping.NotificationOutputType outputType,
-                              final boolean leafNodesOnly) {
+                              final boolean leafNodesOnly, final boolean skipNotificationData) {
             super(path, streamName, outputType);
-            setQueryParams(EPOCH, null, null, leafNodesOnly);
+            setQueryParams(StartTimeParameter.forUriValue("1970-01-01T00:00:00Z"), null, null, leafNodesOnly,
+                skipNotificationData);
         }
 
         @Override
         protected void post(final String data) {
-            this.lastNotification = data;
+            lastNotification = data;
             notificationLatch.countDown();
         }
 
-        public void assertGot(final String json) {
-            if (!Uninterruptibles.awaitUninterruptibly(notificationLatch, 5, TimeUnit.SECONDS)) {
+        public void assertGot(final String json) throws JSONException {
+            // FIXME: use awaitility
+            if (!Uninterruptibles.awaitUninterruptibly(notificationLatch, 500, TimeUnit.SECONDS)) {
                 fail("Timed out waiting for notification for: " + json);
             }
 
             LOG.info("lastNotification: {}", lastNotification);
-            String withFakeDate = withFakeDate(lastNotification);
+            final String withFakeDate = withFakeDate(lastNotification);
             LOG.info("Comparing: \n{}\n{}", json, withFakeDate);
 
             JSONAssert.assertEquals(json, withFakeDate, false);
-            this.lastNotification = null;
+            lastNotification = null;
+            notificationLatch = new CountDownLatch(1);
+        }
+
+        public void assertXmlSimilar(final String xml) {
+            awaitUntillNotification(xml);
+
+            LOG.info("lastNotification: {}", lastNotification);
+            final String withFakeDate = withFakeXmlDate(lastNotification);
+            LOG.info("Comparing: \n{}\n{}", xml, withFakeDate);
+
+            XmlAssert.assertThat(xml).and(withFakeDate).ignoreWhitespace().ignoreChildNodesOrder().areSimilar();
+            lastNotification = null;
+            notificationLatch = new CountDownLatch(1);
+        }
+
+        public String awaitUntillNotification(final String xml) {
+            // FIXME: use awaitility
+            if (!Uninterruptibles.awaitUninterruptibly(notificationLatch, 500, TimeUnit.SECONDS)) {
+                fail("Timed out waiting for notification for: " + xml);
+            }
+            return lastNotification;
+        }
+
+        public void resetLatch() {
             notificationLatch = new CountDownLatch(1);
         }
     }
 
-    static String withFakeDate(final String in) {
-        JSONObject doc = new JSONObject(in);
-        JSONObject notification = doc.getJSONObject("notification");
+    static String withFakeDate(final String in) throws JSONException {
+        final JSONObject doc = new JSONObject(in);
+        final JSONObject notification =
+                doc.getJSONObject("urn-ietf-params-xml-ns-netconf-notification-1.0:notification");
         if (notification == null) {
             return in;
         }
-        notification.put("eventTime", "someDate");
+        notification.put("event-time", "someDate");
         return doc.toString();
     }
 
-    private String getNotifJson(final String path) throws IOException, URISyntaxException {
-        URL url = getClass().getResource(path);
-        byte[] bytes = Files.readAllBytes(Paths.get(url.toURI()));
+    static String withFakeXmlDate(final String in) {
+        return in.replaceAll("<eventTime>.*</eventTime>", "<eventTime>someDate</eventTime>");
+    }
+
+    private String getNotifJson(final String path) throws IOException, URISyntaxException, JSONException {
+        final URL url = getClass().getResource(path);
+        final byte[] bytes = Files.readAllBytes(Paths.get(url.toURI()));
         return withFakeDate(new String(bytes, StandardCharsets.UTF_8));
     }
 
+    private String getResultXml(final String path) throws IOException, URISyntaxException, JSONException {
+        final URL url = getClass().getResource(path);
+        final byte[] bytes = Files.readAllBytes(Paths.get(url.toURI()));
+        return withFakeXmlDate(new String(bytes, StandardCharsets.UTF_8));
+    }
+
     @Test
     public void testJsonNotifsLeaves() throws Exception {
         ListenerAdapterTester adapter = new ListenerAdapterTester(PATCH_CONT_YIID, "Casey",
-                                        NotificationOutputTypeGrouping.NotificationOutputType.JSON, true);
-        adapter.setCloseVars(transactionChainHandler, schemaContextHandler);
+                NotificationOutputTypeGrouping.NotificationOutputType.JSON, true, false);
+        adapter.setCloseVars(domDataBroker, schemaContextHandler);
 
-        DOMDataTreeChangeService changeService = domDataBroker.getExtensions()
+        final DOMDataTreeChangeService changeService = domDataBroker.getExtensions()
                 .getInstance(DOMDataTreeChangeService.class);
-        DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
+        final DOMDataTreeIdentifier root =
+                new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
         changeService.registerDataTreeChangeListener(root, adapter);
 
         WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
         MyList1Builder builder = new MyList1Builder().setMyLeaf11("Jed").setName("Althea");
-        InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
+        final InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
                 .child(MyList1.class, new MyList1Key("Althea"));
-        writeTransaction.put(LogicalDatastoreType.CONFIGURATION, iid, builder.build(), true);
+        writeTransaction.mergeParentStructurePut(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
         writeTransaction.commit();
         adapter.assertGot(getNotifJson(JSON_NOTIF_LEAVES_CREATE));
 
         writeTransaction = dataBroker.newWriteOnlyTransaction();
         builder = new MyList1Builder().withKey(new MyList1Key("Althea")).setMyLeaf12("Bertha");
-        writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, iid, builder.build(), true);
+        writeTransaction.mergeParentStructureMerge(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
         writeTransaction.commit();
         adapter.assertGot(getNotifJson(JSON_NOTIF_LEAVES_UPDATE));
 
@@ -160,25 +232,26 @@ public class ListenerAdapterTest extends AbstractConcurrentDataBrokerTest {
     @Test
     public void testJsonNotifs() throws Exception {
         ListenerAdapterTester adapter = new ListenerAdapterTester(PATCH_CONT_YIID, "Casey",
-                NotificationOutputTypeGrouping.NotificationOutputType.JSON, false);
-        adapter.setCloseVars(transactionChainHandler, schemaContextHandler);
+                NotificationOutputTypeGrouping.NotificationOutputType.JSON, false, false);
+        adapter.setCloseVars(domDataBroker, schemaContextHandler);
 
-        DOMDataTreeChangeService changeService = domDataBroker.getExtensions()
+        final DOMDataTreeChangeService changeService = domDataBroker.getExtensions()
                 .getInstance(DOMDataTreeChangeService.class);
-        DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
+        final DOMDataTreeIdentifier root =
+                new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
         changeService.registerDataTreeChangeListener(root, adapter);
 
         WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
         MyList1Builder builder = new MyList1Builder().setMyLeaf11("Jed").setName("Althea");
-        InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
+        final InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
                 .child(MyList1.class, new MyList1Key("Althea"));
-        writeTransaction.put(LogicalDatastoreType.CONFIGURATION, iid, builder.build(), true);
+        writeTransaction.mergeParentStructurePut(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
         writeTransaction.commit();
         adapter.assertGot(getNotifJson(JSON_NOTIF_CREATE));
 
         writeTransaction = dataBroker.newWriteOnlyTransaction();
         builder = new MyList1Builder().withKey(new MyList1Key("Althea")).setMyLeaf12("Bertha");
-        writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, iid, builder.build(), true);
+        writeTransaction.mergeParentStructureMerge(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
         writeTransaction.commit();
         adapter.assertGot(getNotifJson(JSON_NOTIF_UPDATE));
 
@@ -187,4 +260,129 @@ public class ListenerAdapterTest extends AbstractConcurrentDataBrokerTest {
         writeTransaction.commit();
         adapter.assertGot(getNotifJson(JSON_NOTIF_DEL));
     }
+
+    @Test
+    public void testJsonNotifsWithoutData() throws Exception {
+        ListenerAdapterTester adapter = new ListenerAdapterTester(PATCH_CONT_YIID, "Casey",
+                NotificationOutputTypeGrouping.NotificationOutputType.JSON, false, true);
+        adapter.setCloseVars(domDataBroker, schemaContextHandler);
+
+        DOMDataTreeChangeService changeService = domDataBroker.getExtensions()
+                .getInstance(DOMDataTreeChangeService.class);
+        DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
+        changeService.registerDataTreeChangeListener(root, adapter);
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+        MyList1Builder builder = new MyList1Builder().setMyLeaf11("Jed").setName("Althea");
+        InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
+                .child(MyList1.class, new MyList1Key("Althea"));
+        writeTransaction.mergeParentStructurePut(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
+        writeTransaction.commit();
+        adapter.assertGot(getNotifJson(JSON_NOTIF_WITHOUT_DATA_CREATE));
+
+        writeTransaction = dataBroker.newWriteOnlyTransaction();
+        builder = new MyList1Builder().withKey(new MyList1Key("Althea")).setMyLeaf12("Bertha");
+        writeTransaction.mergeParentStructureMerge(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
+        writeTransaction.commit();
+        adapter.assertGot(getNotifJson(JSON_NOTIF_WITHOUT_DATA_UPDATE));
+
+        writeTransaction = dataBroker.newWriteOnlyTransaction();
+        writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
+        writeTransaction.commit();
+        adapter.assertGot(getNotifJson(JSON_NOTIF_WITHOUT_DATA_DELETE));
+    }
+
+    @Test
+    public void testXmlNotifications() throws Exception {
+        ListenerAdapterTester adapter = new ListenerAdapterTester(PATCH_CONT_YIID, "Casey",
+                NotificationOutputTypeGrouping.NotificationOutputType.XML, false, false);
+        adapter.setCloseVars(domDataBroker, schemaContextHandler);
+
+        DOMDataTreeChangeService changeService = domDataBroker.getExtensions()
+                .getInstance(DOMDataTreeChangeService.class);
+        DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
+        changeService.registerDataTreeChangeListener(root, adapter);
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+        MyList1Builder builder = new MyList1Builder().setMyLeaf11("Jed").setName("Althea");
+        InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
+                .child(MyList1.class, new MyList1Key("Althea"));
+        writeTransaction.mergeParentStructurePut(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
+        writeTransaction.commit();
+        adapter.assertXmlSimilar(getResultXml(XML_NOTIF_CREATE));
+
+        writeTransaction = dataBroker.newWriteOnlyTransaction();
+        builder = new MyList1Builder().withKey(new MyList1Key("Althea")).setMyLeaf12("Bertha");
+        writeTransaction.mergeParentStructureMerge(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
+        writeTransaction.commit();
+        adapter.assertXmlSimilar(getResultXml(XML_NOTIF_UPDATE));
+
+        writeTransaction = dataBroker.newWriteOnlyTransaction();
+        writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
+        writeTransaction.commit();
+        adapter.assertXmlSimilar(getResultXml(XML_NOTIF_DEL));
+    }
+
+    @Test
+    public void testXmlSkipData() throws Exception {
+        ListenerAdapterTester adapter = new ListenerAdapterTester(PATCH_CONT_YIID, "Casey",
+                NotificationOutputTypeGrouping.NotificationOutputType.XML, false, true);
+        adapter.setCloseVars(domDataBroker, schemaContextHandler);
+
+        DOMDataTreeChangeService changeService = domDataBroker.getExtensions()
+                .getInstance(DOMDataTreeChangeService.class);
+        DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
+        changeService.registerDataTreeChangeListener(root, adapter);
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+        MyList1Builder builder = new MyList1Builder().setMyLeaf11("Jed").setName("Althea");
+        InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
+                .child(MyList1.class, new MyList1Key("Althea"));
+        writeTransaction.mergeParentStructurePut(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
+        writeTransaction.commit();
+        adapter.assertXmlSimilar(getResultXml(XML_NOTIF_WITHOUT_DATA_CREATE));
+
+        writeTransaction = dataBroker.newWriteOnlyTransaction();
+        builder = new MyList1Builder().withKey(new MyList1Key("Althea")).setMyLeaf12("Bertha");
+        writeTransaction.mergeParentStructureMerge(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
+        writeTransaction.commit();
+        adapter.assertXmlSimilar(getResultXml(XML_NOTIF_WITHOUT_DATA_UPDATE));
+
+        writeTransaction = dataBroker.newWriteOnlyTransaction();
+        writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
+        writeTransaction.commit();
+        adapter.assertXmlSimilar(getResultXml(XML_NOTIF_WITHOUT_DATA_DELETE));
+    }
+
+    @Test
+    public void testXmlLeavesOnly() throws Exception {
+        ListenerAdapterTester adapter = new ListenerAdapterTester(PATCH_CONT_YIID, "Casey",
+                NotificationOutputTypeGrouping.NotificationOutputType.XML, true, false);
+        adapter.setCloseVars(domDataBroker, schemaContextHandler);
+
+        DOMDataTreeChangeService changeService = domDataBroker.getExtensions()
+                .getInstance(DOMDataTreeChangeService.class);
+        DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, PATCH_CONT_YIID);
+        changeService.registerDataTreeChangeListener(root, adapter);
+        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+        MyList1Builder builder = new MyList1Builder().setMyLeaf11("Jed").setName("Althea");
+        InstanceIdentifier<MyList1> iid = InstanceIdentifier.create(PatchCont.class)
+                .child(MyList1.class, new MyList1Key("Althea"));
+        writeTransaction.mergeParentStructurePut(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
+        writeTransaction.commit();
+        adapter.assertXmlSimilar(getResultXml(XML_NOTIF_LEAVES_CREATE));
+
+        writeTransaction = dataBroker.newWriteOnlyTransaction();
+        builder = new MyList1Builder().withKey(new MyList1Key("Althea")).setMyLeaf12("Bertha");
+        writeTransaction.mergeParentStructureMerge(LogicalDatastoreType.CONFIGURATION, iid, builder.build());
+        writeTransaction.commit();
+        adapter.assertXmlSimilar(getResultXml(XML_NOTIF_LEAVES_UPDATE));
+
+        writeTransaction = dataBroker.newWriteOnlyTransaction();
+        writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
+        writeTransaction.commit();
+
+        // xmlunit cannot compare deeper children it seems out of the box so just check the iid encoding
+        final String notification = adapter.awaitUntillNotification("");
+        assertTrue(notification.contains("instance-identifier-patch-module:my-leaf12"));
+        assertTrue(notification.contains("instance-identifier-patch-module:my-leaf11"));
+        assertTrue(notification.contains("instance-identifier-patch-module:name"));
+    }
 }