@Test public void runTests() { final ImmutableList<String> command = ImmutableList.of("hello", "world"); FakeCxxTest cxxTest = new FakeCxxTest() { @Override protected ImmutableList<String> getShellCommand(ExecutionContext context, Path output) { return command; } }; BuildContext buildContext = FakeBuildContext.NOOP_CONTEXT; ExecutionContext executionContext = TestExecutionContext.newInstance(); TestRunningOptions options = TestRunningOptions.builder() .setDryRun(false) .setTestSelectorList(TestSelectorList.empty()) .build(); ImmutableList<Step> actualSteps = cxxTest.runTests( buildContext, executionContext, options, FakeTestRule.NOOP_REPORTING_CALLBACK); CxxTestStep cxxTestStep = new CxxTestStep( new FakeProjectFilesystem(), command, ImmutableMap.<String, String>of(), cxxTest.getPathToTestExitCode(), cxxTest.getPathToTestOutput(), TEST_TIMEOUT_MS); assertEquals(cxxTestStep, Iterables.getLast(actualSteps)); }
@Test public void startAndStopShouldRelateProperlyBasedOnHash() { ImmutableSet<String> tests = ImmutableSet.of("//exmaple:other", "//thing/made/of:cheese"); TestRunEvent.Started started = TestRunEvent.started(false, TestSelectorList.empty(), false, tests); TestRunEvent.Finished finished = TestRunEvent.finished(tests, ImmutableList.<TestResults>of()); assertTrue(started.isRelatedTo(finished)); assertTrue(finished.isRelatedTo(started)); }
@Test public void shouldNotBelieveThatEventsThatAreNotRelatedAreRelated() { ImmutableSet<String> tests = ImmutableSet.of("//exmaple:other", "//thing/made/of:cheese"); ImmutableSet<String> otherTests = ImmutableSet.of("//example:test"); TestRunEvent.Started started = TestRunEvent.started(false, TestSelectorList.empty(), false, tests); TestRunEvent.Finished finished = TestRunEvent.finished(otherTests, ImmutableList.<TestResults>of()); assertFalse(started.isRelatedTo(finished)); assertFalse(finished.isRelatedTo(started)); }
/** * A collection of {@link TestSelector} instances which, as a group, can decide whether or not to * include a given {@link TestDescription}. */ public class TestSelectorList { private static final TestSelectorList EMPTY = TestSelectorList.builder().build(); /** * Test selector strings are parsed in two places: (i) by "buck test" when it is first run, to * validate that the selectors make sense; and (ii) by the JUnitStep's JUnitRunner, which is what * actually does the test selecting. * * <p>We keep a list of the raw selectors used to build out List of TestSelectors so that they can * be passed from (i) to (ii). This is expensive in that it wastes time re-parsing selectors, but * it means that if the input is an "@/tmp/long-list-of-tests.txt" then re-using that terse * argument keeps the "JUnitSteps" Junit java command line nice and short. */ private final List<TestSelector> testSelectors; final boolean defaultIsInclusive; private TestSelectorList(List<TestSelector> testSelectors, boolean defaultIsInclusive) { this.testSelectors = testSelectors; this.defaultIsInclusive = defaultIsInclusive; } public boolean isIncluded(TestDescription description) { for (TestSelector testSelector : testSelectors) { if (testSelector.matches(description)) { return testSelector.isInclusive(); } } return defaultIsInclusive; } public List<String> getExplanation() { List<String> lines = new ArrayList<>(); for (TestSelector testSelector : testSelectors) { lines.add(testSelector.getExplanation()); } // If the last selector matches everything, derive our default behavior from that test selector // and replace the last line of explanation. int lastIndex = testSelectors.size() - 1; TestSelector lastTestSelector = testSelectors.get(lastIndex); if (lastTestSelector.isMatchAnyClass() && lastTestSelector.isMatchAnyMethod()) { String lastLine = formatEverythingElseLine(lastTestSelector.isInclusive()); lines.set(lastIndex, lastLine); } else { // Otherwise describe our default behavior. lines.add(formatEverythingElseLine(defaultIsInclusive)); } return lines; } private String formatEverythingElseLine(boolean isInclusive) { return String.format("%s everything else", isInclusive ? "include" : "exclude"); } public List<String> getRawSelectors() { List<String> rawSelectors = new ArrayList<>(); for (TestSelector testSelector : testSelectors) { String rawSelector = testSelector.getRawSelector(); rawSelectors.add(rawSelector); } return rawSelectors; } public boolean isEmpty() { return testSelectors.isEmpty(); } public static TestSelectorList empty() { return EMPTY; } public static Builder builder() { return new Builder(); } /** * Build a new {@link TestSelectorList} from a list of strings, each of which is parsed by {@link * TestSelector}. * * <p>If any of the selectors is an inclusive selector, everything else will be excluded. * Conversely, if all of the selectors are exclusive, then everything else will be included by * default. */ public static class Builder { private final List<TestSelector> testSelectors; protected Builder() { testSelectors = new ArrayList<>(); } private Builder addRawSelector(String rawSelector) { if (rawSelector.charAt(0) == '@') { try { String pathString = rawSelector.substring(1); if (pathString.isEmpty()) { throw new TestSelectorParseException("Doesn't mention a path!"); } File file = new File(pathString); loadFromFile(file); } catch (TestSelectorParseException | IOException e) { String message = String.format("Error with test-selector '%s': %s", rawSelector, e.getMessage()); throw new RuntimeException(message, e); } return this; } else { TestSelector testSelector = TestSelector.buildFromSelectorString(rawSelector); this.testSelectors.add(testSelector); } return this; } public Builder addRawSelectors(String... rawSelectors) { return addRawSelectors(Arrays.asList(rawSelectors)); } public Builder addRawSelectors(Collection<String> rawTestSelectors) { for (String rawTestSelector : rawTestSelectors) { addRawSelector(rawTestSelector); } return this; } Builder loadFromFile(File file) throws IOException { try (FileReader tempReader = new FileReader(file); BufferedReader in = new BufferedReader(tempReader); ) { String line; int lineNumber = 1; while ((line = in.readLine()) != null) { try { addRawSelector(line.trim()); lineNumber++; } catch (TestSelectorParseException e) { String message = String.format("Test selector error in %s at line %d", file, lineNumber); throw new TestSelectorParseException(message, e); } } } catch (IOException e) { throw e; } return this; } public TestSelectorList build() { // Default to being inclusive only if all selectors are *exclusive*. boolean defaultIsInclusive = true; for (TestSelector testSelector : testSelectors) { if (testSelector.isInclusive()) { defaultIsInclusive = false; break; } } return new TestSelectorList(testSelectors, defaultIsInclusive); } } }