| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package org.apache.tools.ant.taskdefs.optional.junit; |
| |
| import java.util.List; |
| import java.util.function.Predicate; |
| |
| import junit.framework.Test; |
| import junit.framework.TestResult; |
| |
| import org.junit.runner.Description; |
| import org.junit.runner.Request; |
| import org.junit.runner.Runner; |
| import org.junit.runner.manipulation.Filter; |
| |
| /** |
| * Adapter between JUnit 3.8.x API and JUnit 4.x API for execution of tests |
| * and listening of events (test start, test finish, test failure, test skipped). |
| * The constructor is passed a JUnit 4 test class and a list of name of methods |
| * in it that should be executed. Method {@link #run run(TestResult)} executes |
| * the given JUnit-4-style test methods and notifies the given {@code TestResult} |
| * object using its old (JUnit 3.8.x style) API. |
| * |
| * @author Marian Petras |
| */ |
| public class JUnit4TestMethodAdapter implements Test { |
| |
| private final Class<?> testClass; |
| private final String[] methodNames; |
| private final Runner runner; |
| private final CustomJUnit4TestAdapterCache cache; |
| |
| /** |
| * Creates a new adapter for the given class and a method within the class. |
| * |
| * @param testClass test class containing the method to be executed |
| * @param methodNames names of the test methods that are to be executed |
| * @exception java.lang.IllegalArgumentException |
| * if any of the arguments is {@code null} |
| * or if any of the given method names is {@code null} or empty |
| */ |
| public JUnit4TestMethodAdapter(final Class<?> testClass, |
| final String[] methodNames) { |
| if (testClass == null) { |
| throw new IllegalArgumentException("testClass is <null>"); |
| } |
| if (methodNames == null) { |
| throw new IllegalArgumentException("methodNames is <null>"); |
| } |
| for (int i = 0; i < methodNames.length; i++) { |
| if (methodNames[i] == null) { |
| throw new IllegalArgumentException("method name #" + i + " is <null>"); |
| } |
| if (methodNames[i].isEmpty()) { |
| throw new IllegalArgumentException("method name #" + i + " is empty"); |
| } |
| } |
| this.testClass = testClass; |
| this.methodNames = methodNames.clone(); |
| this.cache = CustomJUnit4TestAdapterCache.getInstance(); |
| |
| // Warning: If 'testClass' is an old-style (pre-JUnit-4) class, |
| // then all its test methods will be executed by the returned runner! |
| Request request; |
| if (methodNames.length == 1) { |
| request = Request.method(testClass, methodNames[0]); |
| } else { |
| request = Request.aClass(testClass).filterWith( |
| new MultipleMethodsFilter(testClass, methodNames)); |
| } |
| runner = request.getRunner(); |
| } |
| |
| @Override |
| public int countTestCases() { |
| return runner.testCount(); |
| } |
| |
| public Description getDescription() { |
| return runner.getDescription(); |
| } |
| |
| public List<Test> getTests() { |
| return cache.asTestList(getDescription()); |
| } |
| |
| public Class<?> getTestClass() { |
| return testClass; |
| } |
| |
| @Override |
| public void run(final TestResult result) { |
| runner.run(cache.getNotifier(result)); |
| } |
| |
| @Override |
| public String toString() { |
| return ":" + String.join(",", methodNames); |
| } |
| |
| private static final class MultipleMethodsFilter extends Filter { |
| |
| private final Description methodsListDescription; |
| private final Class<?> testClass; |
| private final String[] methodNames; |
| |
| private MultipleMethodsFilter(Class<?> testClass, String[] methodNames) { |
| if (testClass == null) { |
| throw new IllegalArgumentException("testClass is <null>"); |
| } |
| if (methodNames == null) { |
| throw new IllegalArgumentException("methodNames is <null>"); |
| } |
| methodsListDescription = Description.createSuiteDescription(testClass); |
| for (String methodName : methodNames) { |
| methodsListDescription.addChild( |
| Description.createTestDescription(testClass, methodName)); |
| } |
| this.testClass = testClass; |
| this.methodNames = methodNames; |
| } |
| |
| @Override |
| public boolean shouldRun(Description description) { |
| if (methodNames.length == 0) { |
| return false; |
| } |
| if (description.isTest()) { |
| return methodsListDescription.getChildren().stream() |
| .anyMatch(Predicate.isEqual(description)); |
| } |
| return description.getChildren().stream().anyMatch(this::shouldRun); |
| } |
| |
| @Override |
| public String describe() { |
| StringBuilder buf = new StringBuilder(40); |
| if (methodNames.length == 0) { |
| buf.append("No methods"); |
| } else { |
| buf.append(methodNames.length == 1 ? "Method " : "Methods "); |
| buf.append(String.join(",", methodNames)); |
| } |
| buf.append('(').append(testClass.getName()).append(')'); |
| return buf.toString(); |
| } |
| |
| } |
| |
| } |