package org.checkerframework.framework.test;
import static org.checkerframework.framework.test.TestConfigurationBuilder.buildDefaultConfiguration;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.annotation.processing.AbstractProcessor;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Compiles all test files in a test directory together. Use {@link CheckerFrameworkPerFileTest} to
* compile each test file in a test directory individually. A {@link
* CheckerFrameworkPerDirectoryTest} is faster than an equivalent {@link
* CheckerFrameworkPerFileTest}, but can only test that processor errors or warnings are issued.
*
* <p>To create a {@link CheckerFrameworkPerDirectoryTest}, create a new class that extends this
* class. The new class must do the following:
*
* <ol>
* <li>Declare a constructor taking 1 parameter of type {@code java.util.List<java.io.File>}. This
* is a list of the files that will be compiled.
* <li>Declare the following method:
* <pre>{@code @Parameters public static String [] getTestDirs()}</pre>
* <p>getTestDir must return an array of directories that exist in the test folder. The
* directories can contain more path information (e.g., "myTestDir/moreTests") but note, the
* test suite will find all of the Java test files that exists below the listed directories.
* It is unnecessary to list child directories of a directory you have already listed.
* </ol>
*
* <pre><code>
* public class MyTest extends CheckerFrameworkPerDirectoryTest {
* public MyTest(List{@literal <}File{@literal >} testFiles) {
* super(testFiles, MyChecker.class, "", "Anomsgtext");
* }
* {@literal @}Parameters
* public static String [] getTestDirs() {
* return new String[]{"all-systems"};
* }
* }
* </code></pre>
*/
@RunWith(PerDirectorySuite.class)
public abstract class CheckerFrameworkPerDirectoryTest {
protected final List<File> testFiles;
/** The fully-qualified class name of the checker to use for tests. */
protected final String checkerName;
/** The path, relative to currentDir/test to the directory containing test inputs. */
protected final String testDir;
/** Extra options to pass to javac when running the checker. */
protected final List<String> checkerOptions;
/**
* Creates a new checker test.
*
* <p>{@link TestConfigurationBuilder#getDefaultConfigurationBuilder(String, File, String,
* Iterable, Iterable, List, boolean)} adds additional checker options such as
* -AprintErrorStack.
*
* @param checker the class for the checker to use
* @param testDir the path to the directory of test inputs
* @param checkerOptions options to pass to the compiler when running tests
*/
public CheckerFrameworkPerDirectoryTest(
List<File> testFiles,
Class<? extends AbstractProcessor> checker,
String testDir,
String... checkerOptions) {
this.testFiles = testFiles;
this.checkerName = checker.getName();
this.testDir = "tests" + File.separator + testDir;
this.checkerOptions = Arrays.asList(checkerOptions);
}
@Test
public void run() {
boolean shouldEmitDebugInfo = TestUtilities.getShouldEmitDebugInfo();
List<String> customizedOptions =
customizeOptions(Collections.unmodifiableList(checkerOptions));
TestConfiguration config =
buildDefaultConfiguration(
testDir,
testFiles,
Collections.singleton(checkerName),
customizedOptions,
shouldEmitDebugInfo);
TypecheckResult testResult = new TypecheckExecutor().runTest(config);
TestUtilities.assertResultsAreValid(testResult);
}
/**
* Override this method if you would like to supply a checker command-line option that depends
* on the Java files passed to the test. Those files are available in field {@link #testFiles}.
*
* <p>If you want to specify the same command-line option for all tests of a particular checker,
* then pass it to the {@link #CheckerFrameworkPerDirectoryTest} constructor.
*
* @param previousOptions the options specified in the constructor of the test previousOptions
* is unmodifiable
* @return a new list of options or the original passed through
*/
public List<String> customizeOptions(List<String> previousOptions) {
return previousOptions;
}
}