/* * 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.logging.Level.WARNING; import java.lang.reflect.Method; import java.util.function.Predicate; import java.util.logging.Logger; import org.junit.internal.builders.AllDefaultPossibilitiesBuilder; import org.junit.internal.builders.AnnotatedBuilder; import org.junit.internal.builders.JUnit4Builder; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.runner.Runner; import org.junit.runners.model.RunnerBuilder; /** * Customization of {@link AllDefaultPossibilitiesBuilder} from JUnit 4 to * ignore certain classes that would otherwise be reported as errors or cause * infinite recursion. * * @since 4.12 * @see DefensiveAnnotatedBuilder * @see DefensiveJUnit4Builder */ class DefensiveAllDefaultPossibilitiesBuilder extends AllDefaultPossibilitiesBuilder { private static final Logger LOG = Logger.getLogger(DefensiveAllDefaultPossibilitiesBuilder.class.getName()); private final AnnotatedBuilder annotatedBuilder; private final DefensiveJUnit4Builder defensiveJUnit4Builder; DefensiveAllDefaultPossibilitiesBuilder() { super(true); annotatedBuilder = new DefensiveAnnotatedBuilder(this); defensiveJUnit4Builder = new DefensiveJUnit4Builder(); } @Override protected AnnotatedBuilder annotatedBuilder() { return annotatedBuilder; } @Override protected JUnit4Builder junit4Builder() { return defensiveJUnit4Builder; } /** * Customization of {@link AnnotatedBuilder} that ignores classes annotated * with {@code @RunWith(JUnitPlatform.class)} to avoid infinite recursion. */ private static class DefensiveAnnotatedBuilder extends AnnotatedBuilder { DefensiveAnnotatedBuilder(RunnerBuilder suiteBuilder) { super(suiteBuilder); } @Override public Runner buildRunner(Class<? extends Runner> runnerClass, Class<?> testClass) throws Exception { // Referenced by name because it might not be available at runtime. if ("org.junit.platform.runner.JUnitPlatform".equals(runnerClass.getName())) { LOG.log(WARNING, () -> "Ignoring test class using JUnitPlatform runner: " + testClass.getName()); return null; } return super.buildRunner(runnerClass, testClass); } } /** * Customization of {@link JUnit4Builder} that ignores classes that do not * contain any test methods in order not to report errors for them. */ private static class DefensiveJUnit4Builder extends JUnit4Builder { private static final Predicate<Method> hasTestAnnotation = new IsPotentialJUnit4TestMethod(); @Override public Runner runnerForClass(Class<?> testClass) throws Throwable { if (containsTestMethods(testClass)) { return super.runnerForClass(testClass); } return null; } private boolean containsTestMethods(Class<?> testClass) { return !ReflectionUtils.findMethods(testClass, hasTestAnnotation).isEmpty(); } } }