From: matus.matok Date: Thu, 20 Apr 2023 10:13:56 +0000 (+0200) Subject: Enrich YangParserTestUtils with parseYang(String) X-Git-Tag: v11.0.0~169 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=a0e551c041c426eecd6c6ee6456abe3fa6922a6f;hp=9271a35377ab3b41ee3ae1a32935494d32917e96;p=yangtools.git Enrich YangParserTestUtils with parseYang(String) 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 Signed-off-by: Robert Varga --- diff --git a/parser/yang-test-util/pom.xml b/parser/yang-test-util/pom.xml index 12ab7759ba..886044e5db 100644 --- a/parser/yang-test-util/pom.xml +++ b/parser/yang-test-util/pom.xml @@ -42,7 +42,6 @@ org.opendaylight.yangtools yang-repo-api - org.opendaylight.yangtools yang-parser-impl 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 index 0000000000..43347516b3 --- /dev/null +++ b/parser/yang-test-util/src/main/java/org/opendaylight/yangtools/yang/test/util/LiteralYangTextSchemaSource.java @@ -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 getSymbolicName() { + return Optional.of(getIdentifier().name().getLocalName()); + } +} diff --git a/parser/yang-test-util/src/main/java/org/opendaylight/yangtools/yang/test/util/YangParserTestUtils.java b/parser/yang-test-util/src/main/java/org/opendaylight/yangtools/yang/test/util/YangParserTestUtils.java index f4e3b9608b..0aac1c47c6 100644 --- a/parser/yang-test-util/src/main/java/org/opendaylight/yangtools/yang/test/util/YangParserTestUtils.java +++ b/parser/yang-test-util/src/main/java/org/opendaylight/yangtools/yang/test/util/YangParserTestUtils.java @@ -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 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 index 0000000000..6c957a8ae6 --- /dev/null +++ b/parser/yang-test-util/src/test/java/org/opendaylight/yangtools/yang/test/util/YT1483Test.java @@ -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 index 0000000000..980e0f4272 --- /dev/null +++ b/parser/yang-test-util/src/test/resources/root-conflict.yang @@ -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