/* * Copyright 2015-2017 the original author or authors. * * 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.junit.vintage.engine.discovery; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toCollection; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.function.IntFunction; import java.util.logging.Logger; import org.junit.platform.engine.TestDescriptor; import org.junit.runner.Description; import org.junit.runner.Runner; import org.junit.runner.manipulation.Filter; import org.junit.runner.manipulation.Filterable; import org.junit.runners.model.RunnerBuilder; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.descriptor.VintageTestDescriptor; /** * @since 4.12 */ class TestClassRequestResolver { private final TestDescriptor engineDescriptor; private final Logger logger; private final UniqueIdReader uniqueIdReader; private final UniqueIdStringifier uniqueIdStringifier = new UniqueIdStringifier(); TestClassRequestResolver(TestDescriptor engineDescriptor, Logger logger) { this.engineDescriptor = engineDescriptor; this.logger = logger; this.uniqueIdReader = new UniqueIdReader(logger); } void populateEngineDescriptorFrom(Set<TestClassRequest> requests) { RunnerBuilder runnerBuilder = new DefensiveAllDefaultPossibilitiesBuilder(); for (TestClassRequest request : requests) { Class<?> testClass = request.getTestClass(); Runner runner = runnerBuilder.safeRunnerForClass(testClass); if (runner != null) { addRunnerTestDescriptor(request, testClass, runner); } } } private void addRunnerTestDescriptor(TestClassRequest request, Class<?> testClass, Runner runner) { RunnerTestDescriptor runnerTestDescriptor = determineRunnerTestDescriptor(testClass, runner, request.getFilters()); engineDescriptor.addChild(runnerTestDescriptor); } private RunnerTestDescriptor determineRunnerTestDescriptor(Class<?> testClass, Runner runner, List<RunnerTestDescriptorAwareFilter> filters) { RunnerTestDescriptor runnerTestDescriptor = createCompleteRunnerTestDescriptor(testClass, runner); if (!filters.isEmpty()) { if (runner instanceof Filterable) { Filter filter = createOrFilter(filters, runnerTestDescriptor); Runner filteredRunner = runnerTestDescriptor.toRequest().filterWith(filter).getRunner(); runnerTestDescriptor = createCompleteRunnerTestDescriptor(testClass, filteredRunner); } else { logger.warning(() -> "Runner " + runner.getClass().getName() // + " (used on " + testClass.getName() + ") does not support filtering" // + " and will therefore be run completely."); } } return runnerTestDescriptor; } private Filter createOrFilter(List<RunnerTestDescriptorAwareFilter> filters, RunnerTestDescriptor runnerTestDescriptor) { filters.forEach(filter -> filter.initialize(runnerTestDescriptor)); return new OrFilter(filters); } private RunnerTestDescriptor createCompleteRunnerTestDescriptor(Class<?> testClass, Runner runner) { RunnerTestDescriptor runnerTestDescriptor = new RunnerTestDescriptor(engineDescriptor, testClass, runner); addChildrenRecursively(runnerTestDescriptor); return runnerTestDescriptor; } private void addChildrenRecursively(VintageTestDescriptor parent) { List<Description> children = parent.getDescription().getChildren(); // Use LinkedHashMap to preserve order, ArrayList for fast access by index Map<String, List<Description>> childrenByUniqueId = children.stream().collect( groupingBy(uniqueIdReader.andThen(uniqueIdStringifier), LinkedHashMap::new, toCollection(ArrayList::new))); for (Entry<String, List<Description>> entry : childrenByUniqueId.entrySet()) { String uniqueId = entry.getKey(); List<Description> childrenWithSameUniqueId = entry.getValue(); IntFunction<String> uniqueIdGenerator = determineUniqueIdGenerator(uniqueId, childrenWithSameUniqueId); for (int index = 0; index < childrenWithSameUniqueId.size(); index++) { String reallyUniqueId = uniqueIdGenerator.apply(index); Description description = childrenWithSameUniqueId.get(index); VintageTestDescriptor child = new VintageTestDescriptor(parent, VintageTestDescriptor.SEGMENT_TYPE_TEST, reallyUniqueId, description); parent.addChild(child); addChildrenRecursively(child); } } } private IntFunction<String> determineUniqueIdGenerator(String uniqueId, List<Description> childrenWithSameUniqueId) { if (childrenWithSameUniqueId.size() == 1) { return index -> uniqueId; } return index -> uniqueId + "[" + index + "]"; } }