// Copyright © 2011-2013, Esko Luontola <www.orfjackal.net> // This software is released under the Apache License 2.0. // The license text is at http://www.apache.org/licenses/LICENSE-2.0 package fi.jumi.test; import fi.jumi.core.api.RunId; import java.util.*; import java.util.regex.*; public class TextUIParser { private static final String RUN_HEADER = "(^ > Run #(\\d+) in (\\S+)$)"; private static final String UNTIL_NEXT_HEADER_OR_END = "(?=" + RUN_HEADER + "|\\z)"; private static final int RUN_ID = 2; private static final int CLASS_NAME = 3; private static final String TEST_START_OR_END = "^ > \\s*([+|-]) (.*)$"; private static final String START_SYMBOL = "+"; private static final int SYMBOL = 1; private static final int TEST_NAME = 2; private static final String ANY_LINES = "(?s:(.*?))"; private static final String FOOTER = "(^Pass: (\\d+), Fail: (\\d+)$)"; private static final int PASSING_COUNT = 2; private static final int FAILING_COUNT = 3; private final String fullOutput; private final Map<RunId, RunParsed> runsById = new HashMap<>(); private int passingCount; private int failingCount; public TextUIParser(String output) { this.fullOutput = output; Matcher m = Pattern.compile(ANY_LINES + FOOTER, Pattern.MULTILINE).matcher(output); m.find(); parseRuns(m.group(1)); parseFooter(m.group(2)); } private void parseRuns(String allRunsOutput) { Matcher m = Pattern.compile(RUN_HEADER + ANY_LINES + UNTIL_NEXT_HEADER_OR_END, Pattern.MULTILINE).matcher(allRunsOutput); while (m.find()) { String runOutput = m.group(); RunId runId = new RunId(Integer.parseInt(m.group(RUN_ID))); String className = m.group(CLASS_NAME); this.runsById.put(runId, new RunParsed(runOutput, runId, className)); } } private void parseFooter(String footerOutput) { Matcher m = Pattern.compile(FOOTER).matcher(footerOutput); m.find(); passingCount = Integer.parseInt(m.group(PASSING_COUNT)); failingCount = Integer.parseInt(m.group(FAILING_COUNT)); } public int getPassingCount() { return passingCount; } public int getFailingCount() { return failingCount; } public int getRunCount() { return runsById.size(); } public Set<RunId> getRunIds() { return new HashSet<>(runsById.keySet()); } public String getRunOutput(RunId runId) { return getRun(runId).output; } public List<String> getTestStartAndEndEvents(RunId runId) { return getRun(runId).getTestStartAndEndEvents(); } private RunParsed getRun(RunId runId) { RunParsed run = runsById.get(runId); if (run == null) { throw new IllegalArgumentException("run not found: " + runId); } return run; } @Override public String toString() { return fullOutput; } private static class RunParsed { public final String output; public final RunId runId; public final String className; public RunParsed(String output, RunId runId, String className) { this.output = output; this.runId = runId; this.className = className; } private List<String> getTestStartAndEndEvents() { ArrayList<String> events = new ArrayList<>(); Matcher m = Pattern.compile(TEST_START_OR_END, Pattern.MULTILINE).matcher(output); while (m.find()) { String prefix = m.group(SYMBOL); String testName = m.group(TEST_NAME); events.add(shortEventName(prefix, testName)); } return events; } private static String shortEventName(String prefix, String testName) { if (prefix.equals(START_SYMBOL)) { return testName; } else { return "/"; } } } }