Skip to content
Snippets Groups Projects
Commit 60bf8261 authored by Florian Angerer's avatar Florian Angerer
Browse files

Implemented option 'console' and now configuring logger properly.

Implemented relative and absolute specification for test run age.
parent ada83ae5
Branches
No related tags found
No related merge requests found
...@@ -27,12 +27,24 @@ import java.nio.file.DirectoryStream; ...@@ -27,12 +27,24 @@ import java.nio.file.DirectoryStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Map; import java.util.Map;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.oracle.truffle.r.test.packages.analyzer.detectors.DiffDetector; import com.oracle.truffle.r.test.packages.analyzer.detectors.DiffDetector;
import com.oracle.truffle.r.test.packages.analyzer.detectors.InstallationProblemDetector; import com.oracle.truffle.r.test.packages.analyzer.detectors.InstallationProblemDetector;
...@@ -63,23 +75,96 @@ import com.oracle.truffle.r.test.packages.analyzer.parser.LogFileParser.LogFile; ...@@ -63,23 +75,96 @@ import com.oracle.truffle.r.test.packages.analyzer.parser.LogFileParser.LogFile;
*/ */
public class PTAMain { public class PTAMain {
private static final Logger LOGGER = Logger.getLogger(PTAMain.class.getName()); private static final Logger LOGGER = Logger.getLogger(PTAMain.class.getName());
private static final String LOG_FILE_NAME = "pta.log";
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
OptionsParser parser = new OptionsParser(); OptionsParser parser = new OptionsParser();
parser.registerOption("help");
parser.registerOption("outDir", "html");
parser.registerOption("glob", "*");
parser.registerOption("since", "last2weeks");
parser.registerOption("console");
String[] remainingArgs = parser.parseOptions(args); String[] remainingArgs = parser.parseOptions(args);
if (parser.has("help")) {
printHelpAndExit();
}
if (remainingArgs.length != 1) { if (remainingArgs.length != 1) {
System.err.println("Unknown arguments: " + Arrays.toString(remainingArgs)); System.err.println("Unknown arguments: " + Arrays.toString(remainingArgs));
printHelp(); printHelpAndExit();
}
configureLogger(parser);
Date sinceDate = parseSinceDate(parser);
LOGGER.info("Considering only test runs since: " + sinceDate);
Path outDir = Paths.get(parser.get("outDir"));
ftw(Paths.get(remainingArgs[0]), outDir, sinceDate, parser.get("glob"));
}
private static final Pattern REL_SINCE_PATTERN = Pattern.compile("last(\\d+)(days?|weeks?|months?)");
private static Date parseSinceDate(OptionsParser parser) {
String sinceDateStr = parser.get("since");
Matcher matcher = REL_SINCE_PATTERN.matcher(sinceDateStr);
if (matcher.matches()) {
int amount = Integer.parseInt(matcher.group(1));
String unit = matcher.group(2);
GregorianCalendar cal = new GregorianCalendar();
switch (unit) {
case "day":
case "days":
cal.add(Calendar.DATE, -amount);
break;
case "week":
case "weeks":
cal.add(Calendar.WEEK_OF_YEAR, -amount);
break;
case "month":
case "months":
cal.add(Calendar.MONTH, -amount);
break;
default:
throw new RuntimeException("Invalid unit: " + unit);
}
return cal.getTime();
}
try {
return new SimpleDateFormat("MM-dd-yyyy").parse(sinceDateStr);
} catch (ParseException e) {
LOGGER.severe("Invalid date: " + e.getMessage());
System.exit(1); System.exit(1);
} }
// should never be reached
return null;
}
Path outDir = Paths.get(parser.get("--outDir", "html")); private static void configureLogger(OptionsParser parser) throws IOException {
ftw(Paths.get(remainingArgs[0]), outDir, parser.get("--glob", "*")); LogManager.getLogManager().reset();
Logger rootLogger = Logger.getLogger("");
ConsoleHandler consoleHandler = new ConsoleHandler();
if (parser.has("console")) {
consoleHandler.setLevel(Level.INFO);
} else {
// set log level of console handlers to SEVERE
consoleHandler.setLevel(Level.SEVERE);
FileHandler fileHandler = new FileHandler(LOG_FILE_NAME);
fileHandler.setLevel(Level.INFO);
rootLogger.addHandler(fileHandler);
}
rootLogger.addHandler(consoleHandler);
} }
private static final String LF = System.lineSeparator(); private static final String LF = System.lineSeparator();
private static void ftw(Path root, Path outDir, String glob) throws IOException { private static void ftw(Path root, Path outDir, Date sinceDate, String glob) throws IOException {
// TODO FS checking // TODO FS checking
HtmlDumper htmlDumper = new HtmlDumper(outDir); HtmlDumper htmlDumper = new HtmlDumper(outDir);
...@@ -99,7 +184,7 @@ public class PTAMain { ...@@ -99,7 +184,7 @@ public class PTAMain {
Collection<RPackage> pkgs = new LinkedList<>(); Collection<RPackage> pkgs = new LinkedList<>();
for (Path p : stream) { for (Path p : stream) {
if (Files.isDirectory(p)) { if (Files.isDirectory(p)) {
Collection<RPackage> pkgVersions = visitPackageRoot(p); Collection<RPackage> pkgVersions = visitPackageRoot(p, sinceDate);
pkgs.addAll(pkgVersions); pkgs.addAll(pkgVersions);
} }
} }
...@@ -118,21 +203,21 @@ public class PTAMain { ...@@ -118,21 +203,21 @@ public class PTAMain {
return problems; return problems;
} }
private static Collection<RPackage> visitPackageRoot(Path pkgRoot) throws IOException { private static Collection<RPackage> visitPackageRoot(Path pkgRoot, Date sinceDate) throws IOException {
String pkgName = pkgRoot.getFileName().toString(); String pkgName = pkgRoot.getFileName().toString();
Collection<RPackage> pkgs = new LinkedList<>(); Collection<RPackage> pkgs = new LinkedList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(pkgRoot)) { try (DirectoryStream<Path> stream = Files.newDirectoryStream(pkgRoot)) {
for (Path p : stream) { for (Path p : stream) {
if (Files.isDirectory(p)) { if (Files.isDirectory(p)) {
pkgs.add(visitPackageVersion(p, pkgName)); pkgs.add(visitPackageVersion(p, pkgName, sinceDate));
} }
} }
} }
return pkgs; return pkgs;
} }
private static RPackage visitPackageVersion(Path pkgVersionDir, String pkgName) { private static RPackage visitPackageVersion(Path pkgVersionDir, String pkgName, Date sinceDate) {
String pkgVersion = pkgVersionDir.getFileName().toString(); String pkgVersion = pkgVersionDir.getFileName().toString();
RPackage pkg = new RPackage(pkgName, pkgVersion); RPackage pkg = new RPackage(pkgName, pkgVersion);
LOGGER.info("Found package " + pkg); LOGGER.info("Found package " + pkg);
...@@ -141,7 +226,7 @@ public class PTAMain { ...@@ -141,7 +226,7 @@ public class PTAMain {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(pkgVersionDir)) { try (DirectoryStream<Path> stream = Files.newDirectoryStream(pkgVersionDir)) {
for (Path p : stream) { for (Path p : stream) {
if (Files.isDirectory(p)) { if (Files.isDirectory(p)) {
RPackageTestRun testRun = visitTestRun(p, pkg); RPackageTestRun testRun = visitTestRun(p, pkg, sinceDate);
if (testRun != null) { if (testRun != null) {
runs.add(testRun); runs.add(testRun);
} }
...@@ -155,15 +240,20 @@ public class PTAMain { ...@@ -155,15 +240,20 @@ public class PTAMain {
return pkg; return pkg;
} }
private static RPackageTestRun visitTestRun(Path testRunDir, RPackage pkg) { private static RPackageTestRun visitTestRun(Path testRunDir, RPackage pkg, Date sinceDate) {
int testRun = Integer.parseInt(testRunDir.getFileName().toString()); int testRun = Integer.parseInt(testRunDir.getFileName().toString());
LOGGER.info("Visiting test run " + testRun + " of package " + pkg); LOGGER.info("Visiting test run " + testRun + " of package " + pkg);
try { try {
RPackageTestRun pkgTestRun = new RPackageTestRun(pkg, testRun); RPackageTestRun pkgTestRun = new RPackageTestRun(pkg, testRun);
Path logFile = testRunDir.resolve(pkg.getName() + ".log"); Path logFile = testRunDir.resolve(pkg.getName() + ".log");
Collection<Problem> problems = parseLogFile(logFile, pkgTestRun); FileTime lastModifiedTime = Files.getLastModifiedTime(logFile);
pkgTestRun.setProblems(problems); if (isNewerThan(lastModifiedTime, sinceDate)) {
return pkgTestRun; Collection<Problem> problems = parseLogFile(logFile, pkgTestRun);
pkgTestRun.setProblems(problems);
return pkgTestRun;
} else {
LOGGER.info(String.format("Skipping package test run %s because it is too old (%s must be newer than %s)", pkgTestRun, lastModifiedTime, sinceDate));
}
} catch (IOException | LogFileParseException e) { } catch (IOException | LogFileParseException e) {
LOGGER.severe(String.format("Error while parsing test run %d of package \"%s-%s\": %s", testRun, LOGGER.severe(String.format("Error while parsing test run %d of package \"%s-%s\": %s", testRun,
pkg.getName(), pkg.getVersion(), e.getMessage())); pkg.getName(), pkg.getVersion(), e.getMessage()));
...@@ -171,6 +261,11 @@ public class PTAMain { ...@@ -171,6 +261,11 @@ public class PTAMain {
return null; return null;
} }
private static boolean isNewerThan(FileTime lastModifiedTime, Date sinceDate) {
Date lastModDate = new Date(lastModifiedTime.toMillis());
return sinceDate.compareTo(lastModDate) <= 0;
}
private static Collection<Problem> parseLogFile(Path logFile, RPackageTestRun pkgTestRun) throws IOException { private static Collection<Problem> parseLogFile(Path logFile, RPackageTestRun pkgTestRun) throws IOException {
LOGGER.info("Parsing log file " + logFile); LOGGER.info("Parsing log file " + logFile);
...@@ -191,30 +286,39 @@ public class PTAMain { ...@@ -191,30 +286,39 @@ public class PTAMain {
return problems; return problems;
} }
private static void printHelp() { private static void printHelpAndExit() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("USAGE: ").append(PTAMain.class.getSimpleName()).append(" [OPTIONS] ROOT").append(LF); sb.append("USAGE: ").append(PTAMain.class.getSimpleName()).append(" [OPTIONS] ROOT").append(LF);
sb.append(LF); sb.append(LF);
sb.append("OPTIONS:").append(LF); sb.append("OPTIONS:").append(LF);
sb.append( sb.append(" --help\t\tShow this help page").append(LF);
" --since MM-dd-YYYY\tOnly consider package tests since the provided date (default: no restriction).").append(LF); sb.append(" --since SPEC\tOnly consider package tests satisfying the specified age (default: \"last2weeks\").").append(LF);
sb.append(" \t\t\tSPEC is either an absolute date in format MM-dd-yyyy or relative in format:").append(LF);
sb.append(" \t\t\tlast<n>(days|weeks|months).").append(LF);
sb.append(" --glob GLOB\t\tGlob-style directory filter for packages to consider (default: \"*\").").append(LF); sb.append(" --glob GLOB\t\tGlob-style directory filter for packages to consider (default: \"*\").").append(LF);
sb.append(" --outDir PATH\tPath to directory for HTML output (default: \"html\").").append(LF); sb.append(" --outDir PATH\tPath to directory for HTML output (default: \"html\").").append(LF);
sb.append(" --console\t\tPrint output to console (by default, only errors are printed).").append(LF);
System.out.println(sb.toString()); System.out.println(sb.toString());
System.exit(1);
} }
private static class OptionsParser { private static class OptionsParser {
private Map<String, String> options = new HashMap<>(); private Map<String, String> options = new HashMap<>();
private Map<String, Option> registered = new HashMap<>();
public String[] parseOptions(String[] args) { public String[] parseOptions(String[] args) {
int i = 0; int i = 0;
while (i < args.length) { while (i < args.length) {
String key = args[i]; String key = args[i];
if (key.startsWith("--since") || key.startsWith("--glob") || key.startsWith("--outDir")) { if (key.startsWith("--") && registered.containsKey(getBareName(key))) {
String value = getOptionArg(args, i); Option option = registered.get(getBareName(key));
++i; String value = null;
options.put(key, value); if (option.hasValue) {
value = getOptionArg(args, i);
++i;
}
options.put(getBareName(key), value);
} else { } else {
break; break;
} }
...@@ -223,6 +327,14 @@ public class PTAMain { ...@@ -223,6 +327,14 @@ public class PTAMain {
return Arrays.copyOfRange(args, i, args.length); return Arrays.copyOfRange(args, i, args.length);
} }
private static String getBareName(String key) {
if (key.startsWith("--")) {
return key.substring(2);
}
throw new RuntimeException("Invalid option name: " + key);
}
private static String getOptionArg(String[] args, int keyIndex) { private static String getOptionArg(String[] args, int keyIndex) {
if (keyIndex + 1 < args.length) { if (keyIndex + 1 < args.length) {
return args[keyIndex + 1]; return args[keyIndex + 1];
...@@ -234,11 +346,33 @@ public class PTAMain { ...@@ -234,11 +346,33 @@ public class PTAMain {
return options.containsKey(key); return options.containsKey(key);
} }
public String get(String key, String defaultValue) { public String get(String key) {
if (has(key)) { if (has(key)) {
return options.get(key); return options.get(key);
} }
return defaultValue; if (registered.containsKey(key)) {
return registered.get(key).defaultValue;
}
throw new RuntimeException("Unknown option: " + key);
}
public void registerOption(String optionName, String defaultValue) {
registered.put(optionName, new Option(true, defaultValue));
}
public void registerOption(String optionName) {
registered.put(optionName, new Option(false, null));
}
private static class Option {
final boolean hasValue;
final String defaultValue;
protected Option(boolean hasValue, String defaultValue) {
this.hasValue = hasValue;
this.defaultValue = defaultValue;
}
} }
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment