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