Enrich YangParserTestUtils with parseYang(String) 41/105541/7
authormatus.matok <matus.matok@pantheon.tech>
Thu, 20 Apr 2023 10:13:56 +0000 (12:13 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 12 May 2023 17:17:02 +0000 (19:17 +0200)
Added a new static method parseYang() to YangParserTestUtils which allows for
parsing a yang file directly from s string input. This allows for higher
flexibility as we do not need to deal with resource accessibility across
modules. Additionally, it is sometimes more convenient to prefer this new form
of input rather than the old one.

JIRA: YANGTOOLS-1483
Change-Id: I4865b73ba8770669a54dd5be167b2ca2d63f3585
Signed-off-by: matus.matok <matus.matok@pantheon.tech>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
parser/yang-test-util/pom.xml
parser/yang-test-util/src/main/java/org/opendaylight/yangtools/yang/test/util/LiteralYangTextSchemaSource.java [new file with mode: 0644]
parser/yang-test-util/src/main/java/org/opendaylight/yangtools/yang/test/util/YangParserTestUtils.java
parser/yang-test-util/src/test/java/org/opendaylight/yangtools/yang/test/util/YT1483Test.java [new file with mode: 0644]
parser/yang-test-util/src/test/resources/root-conflict.yang [new file with mode: 0644]

index 12ab7759baca957ff84e47290b43d61eda3a0087..886044e5dbcb482b4bd3addbfb03e9d329a1a3aa 100644 (file)
@@ -42,7 +42,6 @@
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-repo-api</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-parser-impl</artifactId>
diff --git a/parser/yang-test-util/src/main/java/org/opendaylight/yangtools/yang/test/util/LiteralYangTextSchemaSource.java b/parser/yang-test-util/src/main/java/org/opendaylight/yangtools/yang/test/util/LiteralYangTextSchemaSource.java
new file mode 100644 (file)
index 0000000..4334751
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 PANTHEON.tech 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.yangtools.yang.test.util;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.io.CharSource;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.UnresolvedQName;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+
+/**
+ * A {@link YangTextSchemaSource} backed by a string literal.
+ */
+final class LiteralYangTextSchemaSource extends YangTextSchemaSource {
+    private final @NonNull String sourceString;
+
+    private LiteralYangTextSchemaSource(final SourceIdentifier identifier, final String sourceString,
+            final String symbolicName) {
+        super(identifier);
+        this.sourceString = requireNonNull(sourceString);
+    }
+
+    /**
+     * Create a new {@link YangTextSchemaSource} backed by a String input.
+     *
+     * @param sourceString YANG file as a String
+     * @return A new instance.
+     * @throws NullPointerException if {@code sourceString} is {@code null}
+     * @throws IllegalArgumentException if {@code sourceString} does not a valid YANG body, given a rather restrictive
+     *         view of what is valid.
+     */
+    static @NonNull LiteralYangTextSchemaSource ofLiteral(final String sourceString) {
+        // First line of a YANG file looks as follows:
+        //   `module module-name {`
+        // therefore in order to extract the name of the module from a plain string, we are interested in the second
+        // word of the first line
+        final String[] firstLine = sourceString.substring(0, sourceString.indexOf("{")).strip().split(" ");
+        final String moduleOrSubmoduleString = firstLine[0].strip();
+        checkArgument(moduleOrSubmoduleString.equals("module") || moduleOrSubmoduleString.equals("submodule"));
+
+        final String arg = firstLine[1].strip();
+        final var localName = UnresolvedQName.tryLocalName(arg);
+        checkArgument(localName != null);
+        return new LiteralYangTextSchemaSource(new SourceIdentifier(localName), sourceString, arg);
+    }
+
+    @Override
+    public InputStream openStream() throws IOException {
+        return CharSource.wrap(sourceString).asByteSource(StandardCharsets.UTF_8).openStream();
+    }
+
+    @Override
+    public Optional<String> getSymbolicName() {
+        return Optional.of(getIdentifier().name().getLocalName());
+    }
+}
index f4e3b9608bbade264061d3416f843253a970cb4b..0aac1c47c64a30bd4763b0f64fd92c762d759e3b 100644 (file)
@@ -369,6 +369,17 @@ public final class YangParserTestUtils {
         }
     }
 
+    /**
+     * Creates a new effective schema context containing the specified YANG sources.
+     *
+     * @param sources list of yang sources in plain string
+     * @return effective schema context
+     */
+    public static EffectiveModelContext parseYang(final String... sources) {
+        return parseSources(YangParserConfiguration.DEFAULT, null,
+            Arrays.stream(sources).map(LiteralYangTextSchemaSource::ofLiteral).toList());
+    }
+
     @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Wrong inferent on listFiles")
     private static Collection<File> getYangFiles(final String resourcePath) {
         final URI directoryPath;
diff --git a/parser/yang-test-util/src/test/java/org/opendaylight/yangtools/yang/test/util/YT1483Test.java b/parser/yang-test-util/src/test/java/org/opendaylight/yangtools/yang/test/util/YT1483Test.java
new file mode 100644 (file)
index 0000000..6c957a8
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2023 PANTHEON.tech 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.yangtools.yang.test.util;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public class YT1483Test {
+    private static final String TEST_YANG = """
+        module root-conflict { // results in RootConflictData
+              namespace root-conflict;
+              prefix rc;
+
+              container root-conflict-data; // results in RootConflictData as well
+            }""";
+    private static final String INCORRECT_YANG1 = """
+        /*a comment*/ module /*another comment*/ fail {
+            namespace fail-namespace;
+            prefix ff;
+        }""";
+    private static final String INCORRECT_YANG2 = """
+        module /*a comment*/ fail {
+            namespace fail-namespace;
+            prefix ff;
+        }""";
+    private static final String INCORRECT_YANG3 = """
+        /*comment*/ module fail {
+            namespace fail-namespace;
+            prefix ff;
+        }""";
+
+    @Test
+    public void testParseYang() {
+        final var fromLiteral = YangParserTestUtils.parseYang(TEST_YANG);
+        final var fromResources = YangParserTestUtils.parseYangResourceDirectory("/");
+        final var qname = QName.create("root-conflict", "root-conflict");
+        assertTrue(fromResources.findModule(qname.getModule()).isPresent());
+        assertTrue(fromLiteral.findModule(qname.getModule()).isPresent());
+    }
+
+    @Test
+    public void testIncorrectYang() {
+        assertThrows(IllegalArgumentException.class, () -> YangParserTestUtils.parseYang(INCORRECT_YANG1));
+        assertThrows(IllegalArgumentException.class, () -> YangParserTestUtils.parseYang(INCORRECT_YANG2));
+        assertThrows(IllegalArgumentException.class, () -> YangParserTestUtils.parseYang(INCORRECT_YANG3));
+    }
+}
diff --git a/parser/yang-test-util/src/test/resources/root-conflict.yang b/parser/yang-test-util/src/test/resources/root-conflict.yang
new file mode 100644 (file)
index 0000000..980e0f4
--- /dev/null
@@ -0,0 +1,6 @@
+module root-conflict { // results in RootConflictData
+  namespace root-conflict;
+  prefix rc;
+
+  container root-conflict-data; // results in RootConflictData as well
+}
\ No newline at end of file