io.codemodder.testutils.RawFileCodemodTest Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of codemodder-testutils Show documentation
Show all versions of codemodder-testutils Show documentation
Utilities for testing codemods
The newest version!
package io.codemodder.testutils;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.empty;
import com.github.javaparser.JavaParser;
import io.codemodder.*;
import io.codemodder.codetf.CodeTFResult;
import io.codemodder.javaparser.JavaParserFacade;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
/** Basic tests for {@link RawFileChanger}-based codemods. */
public interface RawFileCodemodTest {
@Test
default void it_verifies_codemod(@TempDir final Path tmpDir) throws IOException {
final Metadata metadata = getClass().getAnnotation(Metadata.class);
if (metadata == null) {
throw new IllegalArgumentException("CodemodTest must be annotated with @Metadata");
}
final Class extends CodeChanger> codemod = metadata.codemodType();
final Path testResourceDir = Path.of(metadata.testResourceDir());
final Path testDir = Path.of("src/test/resources/" + testResourceDir);
verifyCodemod(codemod, metadata, tmpDir, testDir);
}
/** Verify a single test case composed of a .before and .after file. */
private void verifySingleCase(
final Class extends CodeChanger> codemod,
final Path tmpDir,
final Metadata metadata,
final Path filePathBefore,
final Path filePathAfter,
final Map> ruleSarifMap,
final int[] expectedFixLines,
final int[] expectingFailedFixesAtLines,
final Path testResourceDir)
throws IOException {
String tmpFileName = trimExtension(filePathBefore);
final String renameFile = metadata.renameTestFile();
if (!renameFile.isBlank()) {
Path parent = tmpDir.resolve(renameFile).getParent();
if (!Files.exists(parent)) {
Files.createDirectories(parent);
}
tmpFileName = renameFile;
}
final var tmpFilePath = tmpDir.resolve(tmpFileName);
Files.copy(filePathBefore, tmpFilePath);
final CodemodLoader loader =
new CodemodLoader(
List.of(codemod),
CodemodRegulator.of(DefaultRuleSetting.ENABLED, List.of()),
tmpDir,
List.of("**"),
List.of(),
List.of(tmpFilePath),
ruleSarifMap,
List.of(),
null,
null,
null,
null);
List codemods = loader.getCodemods();
assertThat("Only expecting 1 codemod per test", codemods.size(), equalTo(1));
CodemodIdPair pair = codemods.get(0);
CodemodExecutor executor =
CodemodExecutorFactory.from(
tmpDir,
IncludesExcludes.any(),
pair,
List.of(),
List.of(),
FileCache.createDefault(),
JavaParserFacade.from(JavaParser::new),
EncodingDetector.create());
CodeTFResult result = executor.execute(List.of(tmpFilePath));
// let them know if anything failed outright
assertThat("Some files failed to scan", result.getFailedFiles().size(), equalTo(0));
// make sure that some of the basics are being reported
assertThat(result.getSummary(), is(not(blankOrNullString())));
assertThat(result.getDescription(), is(not(blankOrNullString())));
assertThat(result.getReferences(), is(not(empty())));
final var modifiedFile = Files.readString(tmpFilePath);
if (filePathAfter == null) {
// lack of an after file indicates that the before file should be unchanged
assertThat(modifiedFile, equalTo(Files.readString(filePathBefore)));
} else {
assertThat(modifiedFile, equalTo(Files.readString(filePathAfter)));
}
Files.deleteIfExists(tmpFilePath);
ExpectedFixes.verifyExpectedFixes(
testResourceDir, result, pair.getChanger(), expectedFixLines, expectingFailedFixesAtLines);
}
private static String trimExtension(final Path path) {
return path.getFileName()
.toString()
.substring(0, path.getFileName().toString().lastIndexOf('.'));
}
private void verifyCodemod(
final Class extends CodeChanger> codemod,
final Metadata metadata,
final Path tmpDir,
final Path testResourceDir)
throws IOException {
// find all the sarif files
final List allSarifFiles;
try (final var files = Files.list(testResourceDir)) {
allSarifFiles =
files.filter(file -> file.getFileName().toString().endsWith(".sarif")).toList();
}
final CodeDirectory codeDirectory = CodeDirectory.from(tmpDir);
final Map> map =
SarifParser.create().parseIntoMap(allSarifFiles, codeDirectory);
// grab all the .before and .after files in the dir
final List allBeforeFiles;
try (final var files = Files.list(testResourceDir)) {
allBeforeFiles =
files.filter(file -> file.getFileName().toString().endsWith(".before")).toList();
}
final Map afterFilesMap;
try (final var files = Files.list(testResourceDir)) {
afterFilesMap =
files
.filter(file -> file.getFileName().toString().endsWith(".after"))
.collect(Collectors.toMap(RawFileCodemodTest::trimExtension, f -> f));
}
if (allBeforeFiles.isEmpty()) {
throw new IllegalArgumentException("No .before files found in " + testResourceDir);
}
for (var beforeFile : allBeforeFiles) {
final var afterFile = afterFilesMap.get(trimExtension(beforeFile));
// run the codemod
verifySingleCase(
codemod,
tmpDir,
metadata,
beforeFile,
afterFile,
map,
metadata.expectingFixesAtLines(),
metadata.expectingFailedFixesAtLines(),
testResourceDir);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy