Fixed reading whole list/leaf-list using GET/GET-CONFIG RPC 21/94921/7
authorJaroslav Tóth <jtoth@frinx.io>
Mon, 25 Jan 2021 15:00:20 +0000 (16:00 +0100)
committerRobert Varga <nite@hq.sk>
Sun, 21 Feb 2021 17:19:19 +0000 (17:19 +0000)
- The source of the issue was in skipping of empty list/leaf-list
  nodes in XMLStreamNormalizedNodeStreamWriter - the NETCONF
  filter structure was created correctly, but it wasn't correctly
  serialized into XML. However, in NETCONF, it is valid to read
  whole list/leaf-list - we must be able to build NormalizedNode
  structure from subtree-filter which "ends" by list/leaf-list.
- Fixed by introduction EmptyListXmlWriter which is responsible
  for serialization of empty list/leaf-list. Other operations
  are delegated to XMLStreamNormalizedNodeStreamWriter
  implementation.

JIRA: NETCONF-744
Change-Id: Id4b665aa45a397ab25a53e12f4eb7c1a6539d428
Signed-off-by: Jaroslav Tóth <jtoth@frinx.io>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/EmptyListXmlWriter.java [new file with mode: 0644]
netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/NetconfUtil.java
netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/StreamingContext.java
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/schema/mapping/NetconfMessageTransformerTest.java

diff --git a/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/EmptyListXmlWriter.java b/netconf/netconf-util/src/main/java/org/opendaylight/netconf/util/EmptyListXmlWriter.java
new file mode 100644 (file)
index 0000000..ad85a54
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2021 FRINX s.r.o. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netconf.util;
+
+import java.io.IOException;
+import javax.xml.XMLConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+
+/**
+ * Proxy {@link NormalizedNodeStreamWriter} that is responsible for serialization of empty leaf-list and list
+ * nodes to output {@link XMLStreamWriter} as empty XML elements. Other operations are proxied
+ * to delegated {@link NormalizedNodeStreamWriter}.
+ */
+final class EmptyListXmlWriter extends ForwardingNormalizedNodeStreamWriter {
+    private final NormalizedNodeStreamWriter delegatedWriter;
+    private final XMLStreamWriter xmlStreamWriter;
+
+    private boolean isInsideEmptyList = false;
+
+    EmptyListXmlWriter(final NormalizedNodeStreamWriter delegatedWriter, final XMLStreamWriter xmlStreamWriter) {
+        this.delegatedWriter = delegatedWriter;
+        this.xmlStreamWriter = xmlStreamWriter;
+    }
+
+    @Override
+    protected NormalizedNodeStreamWriter delegate() {
+        return delegatedWriter;
+    }
+
+    @Override
+    public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        if (childSizeHint == 0) {
+            writeEmptyElement(name);
+        } else {
+            super.startUnkeyedList(name, childSizeHint);
+        }
+    }
+
+    @Override
+    public void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        if (childSizeHint == 0) {
+            writeEmptyElement(name);
+        } else {
+            super.startMapNode(name, childSizeHint);
+        }
+    }
+
+    @Override
+    public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        if (childSizeHint == 0) {
+            writeEmptyElement(name);
+        } else {
+            super.startOrderedMapNode(name, childSizeHint);
+        }
+    }
+
+    @Override
+    public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        if (childSizeHint == 0) {
+            writeEmptyElement(name);
+        } else {
+            super.startLeafSet(name, childSizeHint);
+        }
+    }
+
+    @Override
+    public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        if (childSizeHint == 0) {
+            writeEmptyElement(name);
+        } else {
+            super.startOrderedLeafSet(name, childSizeHint);
+        }
+    }
+
+    @Override
+    public void endNode() throws IOException {
+        if (isInsideEmptyList) {
+            isInsideEmptyList = false;
+        } else {
+            super.endNode();
+        }
+    }
+
+    private void writeEmptyElement(final NodeIdentifier identifier) throws IOException {
+        final QName nodeType = identifier.getNodeType();
+        try {
+            xmlStreamWriter.writeEmptyElement(XMLConstants.DEFAULT_NS_PREFIX, nodeType.getLocalName(),
+                    nodeType.getNamespace().toString());
+        } catch (XMLStreamException e) {
+            throw new IOException("Failed to serialize empty element to XML: " + identifier, e);
+        }
+        isInsideEmptyList = true;
+    }
+}
\ No newline at end of file
index 5d5b65c1b588ebe976d95693daac27b1126a5ecd..24d73643ea86a6317ef7f2b2140218b2fe10cc80 100644 (file)
@@ -210,8 +210,9 @@ public final class NetconfUtil {
 
         final XMLStreamWriter xmlWriter = XML_FACTORY.createXMLStreamWriter(result);
         try {
-            try (NormalizedNodeStreamWriter writer =
-                    XMLStreamNormalizedNodeStreamWriter.create(xmlWriter, context, schemaPath)) {
+            try (NormalizedNodeStreamWriter streamWriter =
+                    XMLStreamNormalizedNodeStreamWriter.create(xmlWriter, context, schemaPath);
+                 EmptyListXmlWriter writer = new EmptyListXmlWriter(streamWriter, xmlWriter)) {
                 final Iterator<PathArgument> it = query.getPathArguments().iterator();
                 final PathArgument first = it.next();
                 StreamingContext.fromSchemaAndQNameChecked(context, first.getNodeType()).streamToWriter(writer, first,
@@ -247,8 +248,9 @@ public final class NetconfUtil {
 
         final XMLStreamWriter xmlWriter = XML_FACTORY.createXMLStreamWriter(result);
         try {
-            try (NormalizedNodeStreamWriter writer = XMLStreamNormalizedNodeStreamWriter.create(
-                    xmlWriter, context, schemaPath)) {
+            try (NormalizedNodeStreamWriter streamWriter =
+                    XMLStreamNormalizedNodeStreamWriter.create(xmlWriter, context, schemaPath);
+                 EmptyListXmlWriter writer = new EmptyListXmlWriter(streamWriter, xmlWriter)) {
                 final PathArgument first = rootNode.element();
                 StreamingContext.fromSchemaAndQNameChecked(context, first.getNodeType())
                         .streamToWriter(writer, first, rootNode);
index 82172f2c9b7e1d11a0acb368e2aa33055738bb4d..023ce4d0ae122d8bd298826811080d2097656a52 100644 (file)
@@ -8,11 +8,11 @@
 package org.opendaylight.netconf.util;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter.UNKNOWN_SIZE;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import java.io.IOException;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -160,7 +160,7 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
                 final Iterator<PathArgument> others) throws IOException {
             verifyActualPathArgument(first);
 
-            emitElementStart(writer, first);
+            emitElementStart(writer, first, others.hasNext() ? 1 : 0);
             if (others.hasNext()) {
                 final PathArgument childPath = others.next();
                 final StreamingContext<?> childOp = getChildOperation(childPath);
@@ -174,7 +174,8 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
                                   final PathNode subtree) throws IOException {
             verifyActualPathArgument(first);
 
-            emitElementStart(writer, first);
+            final Collection<PathNode> children = subtree.children();
+            emitElementStart(writer, first, children.size());
             for (final PathNode node : subtree.children()) {
                 emitChildTreeNode(writer, node);
             }
@@ -194,7 +195,8 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
             }
         }
 
-        abstract void emitElementStart(NormalizedNodeStreamWriter writer, PathArgument arg) throws IOException;
+        abstract void emitElementStart(NormalizedNodeStreamWriter writer, PathArgument arg,
+                                       int childSizeHint) throws IOException;
 
         @SuppressWarnings("checkstyle:illegalCatch")
         StreamingContext<?> getChildOperation(final PathArgument childPath) {
@@ -342,8 +344,9 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
         }
 
         @Override
-        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg) throws IOException {
-            writer.startChoiceNode(getIdentifier(), UNKNOWN_SIZE);
+        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg,
+                              final int childSizeHint) throws IOException {
+            writer.startChoiceNode(getIdentifier(), childSizeHint);
         }
     }
 
@@ -388,9 +391,10 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
         }
 
         @Override
-        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg) throws IOException {
+        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg,
+                              final int childSizeHint) throws IOException {
             final NodeIdentifierWithPredicates identifier = (NodeIdentifierWithPredicates) arg;
-            writer.startMapEntryNode(identifier, UNKNOWN_SIZE);
+            writer.startMapEntryNode(identifier, childSizeHint);
 
             for (Entry<QName, Object> entry : identifier.entrySet()) {
                 writer.startLeafNode(new NodeIdentifier(entry.getKey()));
@@ -411,8 +415,9 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
         }
 
         @Override
-        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg) throws IOException {
-            writer.startUnkeyedListItem(getIdentifier(), UNKNOWN_SIZE);
+        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg,
+                              final int childSizeHint) throws IOException {
+            writer.startUnkeyedListItem(getIdentifier(), childSizeHint);
         }
     }
 
@@ -427,8 +432,9 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
         }
 
         @Override
-        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg) throws IOException {
-            writer.startContainerNode(getIdentifier(), UNKNOWN_SIZE);
+        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg,
+                              final int childSizeHint) throws IOException {
+            writer.startContainerNode(getIdentifier(), childSizeHint);
         }
     }
 
@@ -457,8 +463,9 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
         }
 
         @Override
-        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg) throws IOException {
-            writer.startOrderedLeafSet(getIdentifier(), UNKNOWN_SIZE);
+        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg,
+                              final int childSizeHint) throws IOException {
+            writer.startOrderedLeafSet(getIdentifier(), childSizeHint);
         }
     }
 
@@ -468,8 +475,9 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
         }
 
         @Override
-        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg) throws IOException {
-            writer.startLeafSet(getIdentifier(), UNKNOWN_SIZE);
+        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg,
+                              final int childSizeHint) throws IOException {
+            writer.startLeafSet(getIdentifier(), childSizeHint);
         }
     }
 
@@ -485,7 +493,8 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
         }
 
         @Override
-        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg) throws IOException {
+        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg,
+                              final int childSizeHint) throws IOException {
             writer.startAugmentationNode(getIdentifier());
         }
     }
@@ -496,8 +505,9 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
         }
 
         @Override
-        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg) throws IOException {
-            writer.startMapNode(getIdentifier(), UNKNOWN_SIZE);
+        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg,
+                              final int childSizeHint) throws IOException {
+            writer.startMapNode(getIdentifier(), childSizeHint);
         }
     }
 
@@ -507,8 +517,9 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
         }
 
         @Override
-        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg) throws IOException {
-            writer.startOrderedMapNode(getIdentifier(), UNKNOWN_SIZE);
+        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg,
+                              final int childSizeHint) throws IOException {
+            writer.startOrderedMapNode(getIdentifier(), childSizeHint);
         }
     }
 
@@ -531,8 +542,9 @@ abstract class StreamingContext<T extends PathArgument> implements Identifiable<
         }
 
         @Override
-        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg) throws IOException {
-            writer.startUnkeyedList(getIdentifier(), UNKNOWN_SIZE);
+        void emitElementStart(final NormalizedNodeStreamWriter writer, final PathArgument arg,
+                              final int childSizeHint) throws IOException {
+            writer.startUnkeyedList(getIdentifier(), childSizeHint);
         }
     }
 }
index 9a19d7f4275e9aa7e0c4ef1aac2f8cefe18bf2b7..dc5d85d5afe8dd3af0c400adb5615f0477c5a2c8 100644 (file)
@@ -32,7 +32,6 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -476,6 +475,52 @@ public class NetconfMessageTransformerTest extends AbstractBaseSchemasTest {
                 + "</rpc>");
     }
 
+    @Test
+    public void testGetLeafList() throws IOException, SAXException {
+        final YangInstanceIdentifier path = YangInstanceIdentifier.create(
+                toId(NetconfState.QNAME),
+                toId(Capabilities.QNAME),
+                toId(QName.create(Capabilities.QNAME, "capability")));
+        final DataContainerChild<?, ?> filter = toFilterStructure(path, SCHEMA);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
+                NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filter));
+
+        assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+                + "<get>\n"
+                + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
+                + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
+                + "<capabilities>\n"
+                + "<capability/>\n"
+                + "</capabilities>\n"
+                + "</netconf-state>\n"
+                + "</filter>\n"
+                + "</get>\n"
+                + "</rpc>\n");
+    }
+
+    @Test
+    public void testGetList() throws IOException, SAXException {
+        final YangInstanceIdentifier path = YangInstanceIdentifier.create(
+                toId(NetconfState.QNAME),
+                toId(Datastores.QNAME),
+                toId(QName.create(Datastores.QNAME, "datastore")));
+        final DataContainerChild<?, ?> filter = toFilterStructure(path, SCHEMA);
+        final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
+                NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filter));
+
+        assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+                + "<get>\n"
+                + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
+                + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
+                + "<datastores>\n"
+                + "<datastore/>\n"
+                + "</datastores>\n"
+                + "</netconf-state>\n"
+                + "</filter>\n"
+                + "</get>\n"
+                + "</rpc>\n");
+    }
+
     private static NetconfMessageTransformer getTransformer(final EffectiveModelContext schema) {
         return new NetconfMessageTransformer(new EmptyMountPointContext(schema), true, BASE_SCHEMAS.getBaseSchema());
     }
@@ -543,7 +588,7 @@ public class NetconfMessageTransformerTest extends AbstractBaseSchemasTest {
 
     @Test
     public void toActionRequestContainerTopLevelTest() {
-        List<PathArgument> nodeIdentifiers = Collections.singletonList(NodeIdentifier.create(DEVICE_QNAME));
+        List<PathArgument> nodeIdentifiers = List.of(NodeIdentifier.create(DEVICE_QNAME));
         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
 
         NormalizedNode<?, ?> payload = initInputAction(QName.create(DEVICE_QNAME, "start-at"), "now");
@@ -624,7 +669,7 @@ public class NetconfMessageTransformerTest extends AbstractBaseSchemasTest {
         List<PathArgument> nodeIdentifiers = new ArrayList<>();
         nodeIdentifiers.add(NodeIdentifier.create(SERVER_QNAME));
         nodeIdentifiers.add(NodeIdentifierWithPredicates.of(SERVER_QNAME, serverNameQname, "testServer"));
-        nodeIdentifiers.add(new AugmentationIdentifier(Collections.singleton(APPLICATIONS_QNAME)));
+        nodeIdentifiers.add(new AugmentationIdentifier(Set.of(APPLICATIONS_QNAME)));
         nodeIdentifiers.add(NodeIdentifier.create(APPLICATIONS_QNAME));
         nodeIdentifiers.add(NodeIdentifier.create(APPLICATION_QNAME));
         nodeIdentifiers.add(NodeIdentifierWithPredicates.of(APPLICATION_QNAME,
@@ -829,8 +874,8 @@ public class NetconfMessageTransformerTest extends AbstractBaseSchemasTest {
         final YangInstanceIdentifier datastoresField = YangInstanceIdentifier.create(toId(Datastores.QNAME));
 
         // building filter structure and NETCONF message
-        final DataContainerChild<?, ?> filterStructure = toFilterStructure(Collections.singletonList(FieldsFilter.of(
-                parentYiid, List.of(netconfStartTimeField, datastoresField))), SCHEMA);
+        final DataContainerChild<?, ?> filterStructure = toFilterStructure(
+            List.of(FieldsFilter.of(parentYiid, List.of(netconfStartTimeField, datastoresField))), SCHEMA);
         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
                 NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
 
@@ -861,8 +906,10 @@ public class NetconfMessageTransformerTest extends AbstractBaseSchemasTest {
                 toId(Datastore.QNAME), NodeIdentifierWithPredicates.of(Datastore.QNAME), toId(Locks.QNAME));
 
         // building filter structure and NETCONF message
-        final DataContainerChild<?, ?> filterStructure = toFilterStructure(Collections.singletonList(FieldsFilter.of(
-                parentYiid, List.of(capabilitiesField, capabilityField, datastoreField, locksFields))), SCHEMA);
+        final DataContainerChild<?, ?> filterStructure = toFilterStructure(
+                List.of(FieldsFilter.of(parentYiid,
+                    List.of(capabilitiesField, capabilityField, datastoreField, locksFields))),
+                SCHEMA);
         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
                 NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
 
@@ -886,8 +933,9 @@ public class NetconfMessageTransformerTest extends AbstractBaseSchemasTest {
         final YangInstanceIdentifier capabilitiesField = YangInstanceIdentifier.create(toId(Capabilities.QNAME));
 
         // building filter structure and NETCONF message
-        final DataContainerChild<?, ?> filterStructure = toFilterStructure(Collections.singletonList(FieldsFilter.of(
-                parentYiid, List.of(capabilitiesField, YangInstanceIdentifier.empty()))), SCHEMA);
+        final DataContainerChild<?, ?> filterStructure = toFilterStructure(
+                List.of(FieldsFilter.of(parentYiid, List.of(capabilitiesField, YangInstanceIdentifier.empty()))),
+                SCHEMA);
         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
                 NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
 
@@ -912,8 +960,8 @@ public class NetconfMessageTransformerTest extends AbstractBaseSchemasTest {
                 toId(QName.create(Schema.QNAME, "namespace").intern()));
 
         // building filter structure and NETCONF message
-        final DataContainerChild<?, ?> filterStructure = toFilterStructure(Collections.singletonList(FieldsFilter.of(
-                parentYiid, List.of(versionField, identifierField))), SCHEMA);
+        final DataContainerChild<?, ?> filterStructure = toFilterStructure(
+            List.of(FieldsFilter.of(parentYiid, List.of(versionField, identifierField))), SCHEMA);
         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
                 NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
 
@@ -991,8 +1039,8 @@ public class NetconfMessageTransformerTest extends AbstractBaseSchemasTest {
                 toId(Session.QNAME), NodeIdentifierWithPredicates.of(Session.QNAME));
 
         // building filter structure and NETCONF message
-        final DataContainerChild<?, ?> filterStructure = toFilterStructure(Collections.singletonList(FieldsFilter.of(
-                parentYiid, List.of(datastoreListField, sessionListField))), SCHEMA);
+        final DataContainerChild<?, ?> filterStructure = toFilterStructure(
+                List.of(FieldsFilter.of(parentYiid, List.of(datastoreListField, sessionListField))), SCHEMA);
         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
                 NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));
 
@@ -1026,8 +1074,8 @@ public class NetconfMessageTransformerTest extends AbstractBaseSchemasTest {
                 toId(QName.create(Session.QNAME, "transport").intern()));
 
         // building filter structure and NETCONF message
-        final DataContainerChild<?, ?> filterStructure = toFilterStructure(Collections.singletonList(FieldsFilter.of(
-                parentYiid, List.of(session1Field, session2TransportField))), SCHEMA);
+        final DataContainerChild<?, ?> filterStructure = toFilterStructure(
+                List.of(FieldsFilter.of(parentYiid, List.of(session1Field, session2TransportField))), SCHEMA);
         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(NETCONF_GET_QNAME,
                 NetconfMessageTransformUtil.wrap(toId(NETCONF_GET_QNAME), filterStructure));