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