blob: f9b10b6c9b5996f80a81b8cfe8edc6e2ffd774c8 [file] [log] [blame]
package org.checkerframework.framework.test;
import java.io.File;
import java.util.ArrayList;
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 individually. Use {@link CheckerFrameworkPerDirectoryTest} to compile all
* files in a test directory together.
*
* <p>To use this class you must do two things:
*
* <ol>
* <li>Create exactly 1 constructor in the subclass with exactly 1 argument of type java.io.File.
* This File will be the Java file that is compiled and whose output is verified.
* <li>Create one of the following 2 public static methods with the annotation
* org.junit.runners.Parameterized.Parameters. The method name and signature must match
* exactly.
* <ul>
* <li>{@code @Parameters public static String [] getTestDirs()}
* <p>getTestDir must return an array of directories that exist in the test folder, e.g.
* <pre> @Parameters
* public static String [] getTestDirs() {
* return new String[]{"all-systems", "flow"};
* }</pre>
* 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.
* <li>{@code @Parameters public static List<File> getTestFiles() }
* <p>The method returns a List of Java files. There are methods like {@link
* TestUtilities#findNestedJavaTestFiles} to help you construct this List. The
* PerDirectorySuite will then instantiate the subclass once for each file returned by
* getTestFiles and execute the run method. An example of this method is:
* <pre> @Parameters
* public static List&lt;File&gt; getTestFiles() {
* return TestUtilities.findNestedJavaTestFiles("aggregate");
* }</pre>
* </ul>
* </ol>
*/
@RunWith(PerFileSuite.class)
public abstract class CheckerFrameworkPerFileTest {
/** The file containing test code, which will be type-checked. */
protected final File testFile;
/** The checker to use for tests. */
protected final Class<?> checker;
/** 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.
*
* @param testFile the file containing test code, which will be type-checked
* @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
*/
protected CheckerFrameworkPerFileTest(
File testFile,
Class<? extends AbstractProcessor> checker,
String testDir,
String... checkerOptions) {
this.testFile = testFile;
this.checker = checker;
this.testDir = "tests" + File.separator + testDir;
this.checkerOptions = new ArrayList<>(Arrays.asList(checkerOptions));
}
@Test
public void run() {
boolean shouldEmitDebugInfo = TestUtilities.getShouldEmitDebugInfo();
List<String> customizedOptions = customizeOptions(Collections.unmodifiableList(checkerOptions));
TestConfiguration config =
TestConfigurationBuilder.buildDefaultConfiguration(
testDir, testFile, checker, customizedOptions, shouldEmitDebugInfo);
TypecheckResult testResult = new TypecheckExecutor().runTest(config);
TestUtilities.assertTestDidNotFail(testResult);
}
/**
* Override this method if you would like to supply a checker command-line option that depends on
* the Java file passed to the test. That file name is available in field {@link #testFile}.
*
* <p>If you want to specify the same command-line option for all tests of a particular checker,
* then pass it to the {@link CheckerFrameworkPerFileTest} 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;
}
}