Rename yang-system-test module to yang-model-validator
[yangtools.git] / yang / yang-model-validator / src / main / java / org / opendaylight / yangtools / yang / validator / Main.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.validator;
9
10 import ch.qos.logback.classic.Level;
11 import com.google.common.base.Stopwatch;
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.Collection;
15 import java.util.HashSet;
16 import java.util.List;
17 import org.apache.commons.cli.BasicParser;
18 import org.apache.commons.cli.CommandLine;
19 import org.apache.commons.cli.CommandLineParser;
20 import org.apache.commons.cli.HelpFormatter;
21 import org.apache.commons.cli.Option;
22 import org.apache.commons.cli.Options;
23 import org.apache.commons.cli.ParseException;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 /**
30  * Main class of Yang parser system test.
31  *
32  * <p>
33  * yang-system-test [-f features] [-h help] [-p path] [-v verbose] yangFiles...
34  *  -f,--features &lt;arg&gt;   features is a string in the form
35  *                        [feature(,feature)*] and feature is a string in the form
36  *                        [($namespace?revision=$revision)$local_name].
37  *                        This option is used to prune the data model by removing
38  *                        all nodes that are defined with a "if-feature".
39  *  -h,--help             print help message and exit.
40  *  -p,--path &lt;arg&gt;       path is a colon (:) separated list of directories
41  *                        to search for yang modules.
42  *  -r, --recursive       recursive search of directories specified by -p option
43  *  -v,--verbose          shows details about the results of test running.
44  *
45  */
46 public class Main {
47     private static final Logger LOG = LoggerFactory.getLogger(Main.class);
48     private static final int MB = 1024 * 1024;
49
50     private static Options createOptions() {
51         final Options options = new Options();
52
53         final Option help = new Option("h", "help", false, "print help message and exit.");
54         help.setRequired(false);
55         options.addOption(help);
56
57         final Option path = new Option("p", "path", true,
58                 "path is a colon (:) separated list of directories to search for yang modules.");
59         path.setRequired(false);
60         options.addOption(path);
61
62         final Option recursiveSearch = new Option("r", "recursive", false,
63                 "recursive search of directories specified by -p option.");
64         recursiveSearch.setRequired(false);
65         options.addOption(recursiveSearch);
66
67         final Option verbose = new Option("v", "verbose", false, "shows details about the results of test running.");
68         verbose.setRequired(false);
69         options.addOption(verbose);
70
71         final Option feature = new Option(
72                 "f",
73                 "features",
74                 true,
75                 "features is a string in the form [feature(,feature)*] and feature is a string in the form "
76                         + "[($namespace?revision=$revision)$local_name]. This option is used to prune the data model "
77                         + "by removing all nodes that are defined with a \"if-feature\".");
78         feature.setRequired(false);
79         options.addOption(feature);
80         return options;
81     }
82
83     public static void main(final String[] args) {
84         final HelpFormatter formatter = new HelpFormatter();
85         final Options options = createOptions();
86         final CommandLine arguments = parseArguments(args, options, formatter);
87
88         if (arguments.hasOption("help")) {
89             printHelp(options, formatter);
90             return;
91         }
92
93         if (arguments.hasOption("verbose")) {
94             setLoggingLevel(Level.DEBUG);
95         } else {
96             setLoggingLevel(Level.ERROR);
97         }
98
99         final List<String> yangLibDirs = initYangDirsPath(arguments);
100         final List<String> yangFiles = Arrays.asList(arguments.getArgs());
101         final HashSet<QName> supportedFeatures = initSupportedFeatures(arguments);
102
103         runSystemTest(yangLibDirs, yangFiles, supportedFeatures, arguments.hasOption("recursive"));
104     }
105
106     private static void setLoggingLevel(final Level level) {
107         ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(
108                 ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
109         root.setLevel(level);
110     }
111
112     @SuppressWarnings("checkstyle:illegalCatch")
113     private static void runSystemTest(final List<String> yangLibDirs, final List<String> yangFiles,
114             final HashSet<QName> supportedFeatures, final boolean recursiveSearch) {
115         LOG.info("Yang model dirs: {} ", yangLibDirs);
116         LOG.info("Yang model files: {} ", yangFiles);
117         LOG.info("Supported features: {} ", supportedFeatures);
118
119         SchemaContext context = null;
120
121         printMemoryInfo("start");
122         final Stopwatch stopWatch = Stopwatch.createStarted();
123
124         try {
125             context = SystemTestUtils.parseYangSources(yangLibDirs, yangFiles, supportedFeatures, recursiveSearch);
126         } catch (final Exception e) {
127             LOG.error("Failed to create SchemaContext.", e);
128             System.exit(1);
129         }
130
131         stopWatch.stop();
132         LOG.info("Elapsed time: {}", stopWatch);
133         printMemoryInfo("end");
134         LOG.info("SchemaContext resolved Successfully. {}", context);
135         Runtime.getRuntime().gc();
136         printMemoryInfo("after gc");
137     }
138
139     private static List<String> initYangDirsPath(final CommandLine arguments) {
140         final List<String> yangDirs = new ArrayList<>();
141         if (arguments.hasOption("path")) {
142             for (final String pathArg : arguments.getOptionValues("path")) {
143                 yangDirs.addAll(Arrays.asList(pathArg.split(":")));
144             }
145         }
146         return yangDirs;
147     }
148
149     private static HashSet<QName> initSupportedFeatures(final CommandLine arguments) {
150         HashSet<QName> supportedFeatures = null;
151         if (arguments.hasOption("features")) {
152             supportedFeatures = new HashSet<>();
153             for (final String pathArg : arguments.getOptionValues("features")) {
154                 supportedFeatures.addAll(createQNames(pathArg.split(",")));
155             }
156         }
157         return supportedFeatures;
158     }
159
160     private static Collection<? extends QName> createQNames(final String[] featuresArg) {
161         final HashSet<QName> qnames = new HashSet<>();
162         for (final String featureStr : featuresArg) {
163             qnames.add(QName.create(featureStr));
164         }
165
166         return qnames;
167     }
168
169     private static CommandLine parseArguments(final String[] args, final Options options,
170             final HelpFormatter formatter) {
171         final CommandLineParser parser = new BasicParser();
172
173         CommandLine cmd = null;
174         try {
175             cmd = parser.parse(options, args);
176         } catch (final ParseException e) {
177             LOG.error("Failed to parse command line options.", e);
178             printHelp(options, formatter);
179
180             System.exit(1);
181         }
182
183         return cmd;
184     }
185
186     private static void printHelp(final Options options, final HelpFormatter formatter) {
187         formatter.printHelp("yang-system-test [-f features] [-h help] [-p path] [-v verbose] yangFiles...", options);
188     }
189
190     private static void printMemoryInfo(final String info) {
191         LOG.info("Memory INFO [{}]: free {}MB, used {}MB, total {}MB, max {}MB", info,
192             Runtime.getRuntime().freeMemory() / MB,
193             (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / MB,
194             Runtime.getRuntime().totalMemory() / MB, Runtime.getRuntime().maxMemory() / MB);
195     }
196 }