2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.stmt;
10 import static org.junit.Assert.assertEquals;
12 import com.google.common.io.Files;
14 import java.io.FileFilter;
15 import java.io.IOException;
16 import java.net.URISyntaxException;
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Collection;
21 import java.util.List;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.common.YangConstants;
25 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
26 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
28 import org.opendaylight.yangtools.yang.model.api.Module;
29 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
30 import org.opendaylight.yangtools.yang.model.api.ModuleLike;
31 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
32 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
34 import org.opendaylight.yangtools.yang.model.api.Submodule;
35 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
36 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
37 import org.opendaylight.yangtools.yang.model.repo.api.YinTextSchemaSource;
38 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
39 import org.opendaylight.yangtools.yang.parser.api.YangSyntaxErrorException;
40 import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.RFC7950Reactors;
41 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource;
42 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YinStatementStreamSource;
43 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YinTextToDomTransformer;
44 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
45 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
46 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
47 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor.BuildAction;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50 import org.xml.sax.SAXException;
52 public final class StmtTestUtils {
54 public static final FileFilter YANG_FILE_FILTER =
55 file -> file.getName().endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION) && file.isFile();
57 public static final FileFilter YIN_FILE_FILTER =
58 file -> file.getName().endsWith(YangConstants.RFC6020_YIN_FILE_EXTENSION) && file.isFile();
60 private static final Logger LOG = LoggerFactory.getLogger(StmtTestUtils.class);
62 private StmtTestUtils() {
66 public static void log(final Throwable exception, final String indent) {
67 LOG.debug("{}{}", indent, exception.getMessage());
69 final Throwable[] suppressed = exception.getSuppressed();
70 for (final Throwable throwable : suppressed) {
71 log(throwable, indent + " ");
75 public static List<Module> findModules(final Collection<? extends Module> modules, final String moduleName) {
76 final List<Module> result = new ArrayList<>();
77 for (final Module module : modules) {
78 if (module.getName().equals(moduleName)) {
85 public static YangStatementStreamSource sourceForResource(final String resourceName) {
87 return YangStatementStreamSource.create(YangTextSchemaSource.forFile(new File(
88 StmtTestUtils.class.getResource(resourceName).toURI())));
89 } catch (IOException | YangSyntaxErrorException | URISyntaxException e) {
90 throw new IllegalArgumentException("Failed to create source", e);
94 public static void printReferences(final ModuleLike module, final boolean isSubmodule, final String indent) {
95 LOG.debug("{}{} {}", indent, isSubmodule ? "Submodule" : "Module", module.getName());
96 for (final Submodule submodule : module.getSubmodules()) {
97 printReferences(submodule, true, indent + " ");
98 printChilds(submodule.getChildNodes(), indent + " ");
102 public static void printChilds(final Collection<? extends DataSchemaNode> childNodes, final String indent) {
104 for (final DataSchemaNode child : childNodes) {
105 LOG.debug("{}{} {}", indent, "Child", child.getQName().getLocalName());
106 if (child instanceof DataNodeContainer) {
107 printChilds(((DataNodeContainer) child).getChildNodes(), indent + " ");
112 public static EffectiveModelContext parseYangSource(final String yangSourcePath) throws ReactorException,
113 URISyntaxException, IOException, YangSyntaxErrorException {
114 return parseYangSource(yangSourcePath, YangParserConfiguration.DEFAULT, null);
117 public static EffectiveModelContext parseYangSource(final String yangSourcePath, final Set<QName> supportedFeatures)
118 throws ReactorException, URISyntaxException, IOException, YangSyntaxErrorException {
119 return parseYangSource(yangSourcePath, YangParserConfiguration.DEFAULT, supportedFeatures);
122 public static EffectiveModelContext parseYangSource(final String yangSourcePath,
123 final YangParserConfiguration config, final Set<QName> supportedFeatures)
124 throws ReactorException, URISyntaxException, IOException, YangSyntaxErrorException {
125 final URL source = StmtTestUtils.class.getResource(yangSourcePath);
126 final File sourceFile = new File(source.toURI());
127 return parseYangSources(config, supportedFeatures, sourceFile);
130 public static EffectiveModelContext parseYangSources(final StatementStreamSource... sources)
131 throws ReactorException {
132 return parseYangSources(YangParserConfiguration.DEFAULT, null, sources);
135 public static EffectiveModelContext parseYangSources(final YangParserConfiguration config,
136 final Set<QName> supportedFeatures, final StatementStreamSource... sources) throws ReactorException {
137 return parseYangSources(config, supportedFeatures, Arrays.asList(sources));
140 public static EffectiveModelContext parseYangSources(final YangParserConfiguration config,
141 final Set<QName> supportedFeatures, final Collection<? extends StatementStreamSource> sources)
142 throws ReactorException {
143 final BuildAction build = getReactor(config).newBuild().addSources(sources);
144 if (supportedFeatures != null) {
145 build.setSupportedFeatures(supportedFeatures);
147 return build.buildEffective();
150 public static EffectiveModelContext parseYangSources(final File... files) throws ReactorException, IOException,
151 YangSyntaxErrorException {
152 return parseYangSources(YangParserConfiguration.DEFAULT, null, files);
155 public static EffectiveModelContext parseYangSources(final YangParserConfiguration config,
156 final Set<QName> supportedFeatures, final File... files) throws ReactorException, IOException,
157 YangSyntaxErrorException {
159 final Collection<YangStatementStreamSource> sources = new ArrayList<>(files.length);
160 for (File file : files) {
161 sources.add(YangStatementStreamSource.create(YangTextSchemaSource.forFile(file)));
164 return parseYangSources(config, supportedFeatures, sources);
167 public static EffectiveModelContext parseYangSources(final Collection<File> files) throws ReactorException,
168 IOException, YangSyntaxErrorException {
169 return parseYangSources(files, YangParserConfiguration.DEFAULT);
172 public static EffectiveModelContext parseYangSources(final Collection<File> files,
173 final YangParserConfiguration config) throws ReactorException, IOException, YangSyntaxErrorException {
174 return parseYangSources(config, null, files.toArray(new File[files.size()]));
177 public static EffectiveModelContext parseYangSources(final String yangSourcesDirectoryPath)
178 throws ReactorException, URISyntaxException, IOException, YangSyntaxErrorException {
179 return parseYangSources(yangSourcesDirectoryPath, YangParserConfiguration.DEFAULT);
182 public static EffectiveModelContext parseYangSources(final String yangSourcesDirectoryPath,
183 final YangParserConfiguration config) throws ReactorException, URISyntaxException, IOException,
184 YangSyntaxErrorException {
185 return parseYangSources(yangSourcesDirectoryPath, null, config);
188 public static EffectiveModelContext parseYangSources(final String yangSourcesDirectoryPath,
189 final Set<QName> supportedFeatures, final YangParserConfiguration config) throws ReactorException,
190 URISyntaxException, IOException, YangSyntaxErrorException {
192 final URL resourceDir = StmtTestUtils.class.getResource(yangSourcesDirectoryPath);
193 final File testSourcesDir = new File(resourceDir.toURI());
195 return parseYangSources(config, supportedFeatures, testSourcesDir.listFiles(YANG_FILE_FILTER));
198 public static EffectiveModelContext parseYangSources(final String yangFilesDirectoryPath,
199 final String yangLibsDirectoryPath)
200 throws URISyntaxException, ReactorException, IOException, YangSyntaxErrorException {
201 return parseYangSources(yangFilesDirectoryPath, yangLibsDirectoryPath, null);
204 public static EffectiveModelContext parseYangSources(final String yangFilesDirectoryPath,
205 final String yangLibsDirectoryPath, final Set<QName> supportedFeatures) throws URISyntaxException,
206 ReactorException, IOException, YangSyntaxErrorException {
207 final File yangsDir = new File(StmtTestUtils.class.getResource(yangFilesDirectoryPath).toURI());
208 final File libsDir = new File(StmtTestUtils.class.getResource(yangLibsDirectoryPath).toURI());
210 return parseYangSources(yangsDir.listFiles(YANG_FILE_FILTER), libsDir.listFiles(YANG_FILE_FILTER),
214 private static EffectiveModelContext parseYangSources(final File[] yangFiles, final File[] libFiles,
215 final Set<QName> supportedFeatures) throws ReactorException, IOException, YangSyntaxErrorException {
216 final StatementStreamSource[] yangSources = new StatementStreamSource[yangFiles.length];
217 for (int i = 0; i < yangFiles.length; i++) {
218 yangSources[i] = YangStatementStreamSource.create(YangTextSchemaSource.forFile(yangFiles[i]));
221 final StatementStreamSource[] libSources = new StatementStreamSource[libFiles.length];
222 for (int i = 0; i < libFiles.length; i++) {
223 libSources[i] = YangStatementStreamSource.create(YangTextSchemaSource.forFile(libFiles[i]));
226 return parseYangSources(yangSources, libSources, supportedFeatures);
229 private static EffectiveModelContext parseYangSources(final StatementStreamSource[] yangSources,
230 final StatementStreamSource[] libSources, final Set<QName> supportedFeatures) throws ReactorException {
232 final BuildAction reactor = RFC7950Reactors.defaultReactor().newBuild()
233 .addSources(yangSources).addLibSources(libSources);
234 if (supportedFeatures != null) {
235 reactor.setSupportedFeatures(supportedFeatures);
238 return reactor.buildEffective();
241 public static EffectiveModelContext parseYinSources(final String yinSourcesDirectoryPath)
242 throws URISyntaxException, SAXException, IOException, ReactorException {
243 return parseYinSources(yinSourcesDirectoryPath, YangParserConfiguration.DEFAULT);
246 public static EffectiveModelContext parseYinSources(final String yinSourcesDirectoryPath,
247 final YangParserConfiguration config) throws URISyntaxException, SAXException, IOException,
249 final URL resourceDir = StmtTestUtils.class.getResource(yinSourcesDirectoryPath);
250 final File[] files = new File(resourceDir.toURI()).listFiles(YIN_FILE_FILTER);
251 final StatementStreamSource[] sources = new StatementStreamSource[files.length];
252 for (int i = 0; i < files.length; i++) {
253 final SourceIdentifier identifier = YinTextSchemaSource.identifierFromFilename(files[i].getName());
255 sources[i] = YinStatementStreamSource.create(YinTextToDomTransformer.transformSource(
256 YinTextSchemaSource.delegateForByteSource(identifier, Files.asByteSource(files[i]))));
259 return parseYinSources(config, sources);
262 public static EffectiveModelContext parseYinSources(final YangParserConfiguration config,
263 final StatementStreamSource... sources) throws ReactorException {
264 return getReactor(config)
270 public static Module findImportedModule(final SchemaContext context, final Module rootModule,
271 final String importedModuleName) {
272 ModuleImport requestedModuleImport = null;
273 for (final ModuleImport moduleImport : rootModule.getImports()) {
274 if (moduleImport.getModuleName().equals(importedModuleName)) {
275 requestedModuleImport = moduleImport;
280 return context.findModule(requestedModuleImport.getModuleName(), requestedModuleImport.getRevision())
285 * Assertion that a {@link SchemaNode} reports expected path. This method deals with {@link SchemaNode#getPath()}
286 * being unavailable by comparing {@link SchemaNode#getQName()} to {@link SchemaPath#getLastComponent()}.
288 * @param expected Expected
289 * @param node Node to examine
290 * @throws AssertionError if the
292 public static void assertPathEquals(final SchemaPath expected, final SchemaNode node) {
293 final SchemaPath actual;
295 actual = node.getPath();
296 } catch (UnsupportedOperationException e) {
297 LOG.trace("Node {} does not support getPath()", node, e);
298 assertEquals(expected.getLastComponent(), node.getQName());
301 assertEquals(expected, actual);
304 private static CrossSourceStatementReactor getReactor(final YangParserConfiguration config) {
305 return YangParserConfiguration.DEFAULT.equals(config) ? RFC7950Reactors.defaultReactor()
306 : RFC7950Reactors.defaultReactorBuilder(config).build();