/* * Copyright (c) 2016 Cisco Systems, Inc. and others. 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.parser.system.test; import com.google.common.base.Stopwatch; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.log4j.BasicConfigurator; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.SchemaContext; /** * Main class of Yang parser system test. * * yang-system-test [-f features] [-h help] [-p path] [-v verbose] yangFiles... * -f,--features <arg> features is a string in the form * [feature(,feature)*] and feature is a string in the form * [($namespace?revision=$revision)$local_name]. * This option is used to prune the data model by removing * all nodes that are defined with a "if-feature". * -h,--help print help message and exit. * -p,--path <arg> path is a colon (:) separated list of directories * to search for yang modules. * -r, --recursive recursive search of directories specified by -p option * -v,--verbose shows details about the results of test running. * */ public class Main { private static final Logger LOG = Logger.getLogger(Main.class.getName()); private static final int MB = 1024 * 1024; private static Options createOptions() { final Options options = new Options(); final Option help = new Option("h", "help", false, "print help message and exit."); help.setRequired(false); options.addOption(help); final Option path = new Option("p", "path", true, "path is a colon (:) separated list of directories to search for yang modules."); path.setRequired(false); options.addOption(path); final Option recursiveSearch = new Option("r", "recursive", false, "recursive search of directories specified by -p option."); recursiveSearch.setRequired(false); options.addOption(recursiveSearch); final Option verbose = new Option("v", "verbose", false, "shows details about the results of test running."); verbose.setRequired(false); options.addOption(verbose); final Option feature = new Option( "f", "features", true, "features is a string in the form [feature(,feature)*] and feature is a string in the form " + "[($namespace?revision=$revision)$local_name]. This option is used to prune the data model by removing " + "all nodes that are defined with a \"if-feature\"."); feature.setRequired(false); options.addOption(feature); return options; } public static void main(final String[] args) { BasicConfigurator.configure(); final HelpFormatter formatter = new HelpFormatter(); final Options options = createOptions(); final CommandLine arguments = parseArguments(args, options, formatter); if (arguments.hasOption("help")) { printHelp(options, formatter); return; } if (arguments.hasOption("verbose")) { LOG.setLevel(Level.CONFIG); } else { LOG.setLevel(Level.SEVERE); } final List<String> yangLibDirs = initYangDirsPath(arguments); final List<String> yangFiles = Arrays.asList(arguments.getArgs()); final HashSet<QName> supportedFeatures = initSupportedFeatures(arguments); runSystemTest(yangLibDirs, yangFiles, supportedFeatures, arguments.hasOption("recursive")); } private static void runSystemTest(final List<String> yangLibDirs, final List<String> yangFiles, final HashSet<QName> supportedFeatures, final boolean recursiveSearch) { LOG.log(Level.INFO, "Yang model dirs: {0} ", yangLibDirs); LOG.log(Level.INFO, "Yang model files: {0} ", yangFiles); LOG.log(Level.INFO, "Supported features: {0} ", supportedFeatures); SchemaContext context = null; printMemoryInfo("start"); final Stopwatch stopWatch = Stopwatch.createStarted(); try { context = SystemTestUtils.parseYangSources(yangLibDirs, yangFiles, supportedFeatures, recursiveSearch); } catch (final Exception e) { LOG.log(Level.SEVERE, "Failed to create SchemaContext.", e); System.exit(1); } stopWatch.stop(); LOG.log(Level.INFO, "Elapsed time: {0}", stopWatch); printMemoryInfo("end"); LOG.log(Level.INFO, "SchemaContext resolved Successfully. {0}", context); Runtime.getRuntime().gc(); printMemoryInfo("after gc"); } private static List<String> initYangDirsPath(final CommandLine arguments) { final List<String> yangDirs = new ArrayList<>(); if (arguments.hasOption("path")) { for (final String pathArg : arguments.getOptionValues("path")) { yangDirs.addAll(Arrays.asList(pathArg.split(":"))); } } return yangDirs; } private static HashSet<QName> initSupportedFeatures(final CommandLine arguments) { HashSet<QName> supportedFeatures = null; if (arguments.hasOption("features")) { supportedFeatures = new HashSet<>(); for (final String pathArg : arguments.getOptionValues("features")) { supportedFeatures.addAll(createQNames(pathArg.split(","))); } } return supportedFeatures; } private static Collection<? extends QName> createQNames(final String[] featuresArg) { final HashSet<QName> qnames = new HashSet<>(); for (final String featureStr : featuresArg) { qnames.add(QName.create(featureStr)); } return qnames; } private static CommandLine parseArguments(final String[] args, final Options options, final HelpFormatter formatter) { final CommandLineParser parser = new BasicParser(); CommandLine cmd = null; try { cmd = parser.parse(options, args); } catch (final ParseException e) { LOG.log(Level.SEVERE, "Failed to parse command line options.", e); printHelp(options, formatter); System.exit(1); } return cmd; } private static void printHelp(final Options options, final HelpFormatter formatter) { formatter.printHelp("yang-system-test [-f features] [-h help] [-p path] [-v verbose] yangFiles...", options); } private static void printMemoryInfo(final String info) { LOG.log(Level.INFO, "Memory INFO [{0}]: free {1}MB, used {2}MB, total {3}MB, max {4}MB", new Object[] { info, Runtime.getRuntime().freeMemory() / MB, (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / MB, Runtime.getRuntime().totalMemory() / MB, Runtime.getRuntime().maxMemory() / MB }); } }