de.dagere.peass.testtransformation.JUnitTestShortener Maven / Gradle / Ivy
The newest version!
package de.dagere.peass.testtransformation;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import de.dagere.nodeDiffDetector.data.Type;
import de.dagere.nodeDiffDetector.typeFinding.TypeFileFinder;
import de.dagere.nodeDiffDetector.typeFinding.TypeFinder;
import de.dagere.nodeDiffDetector.utils.JavaParserProvider;
public class JUnitTestShortener implements AutoCloseable {
private static final Logger LOG = LogManager.getLogger(JUnitTestShortener.class);
private JUnitTestTransformer transformer;
private final File module;
private final Type callee;
private final String method;
private final Map lastShortenedMap = new HashMap<>();
private final Set superclasses = new HashSet<>();
final File calleeClazzFile;
public JUnitTestShortener(final JUnitTestTransformer transformer, final File module, final Type callee, final String method) {
this.transformer = transformer;
this.module = module;
this.callee = callee;
this.method = method;
TypeFileFinder finder = new TypeFileFinder(transformer.getConfig().getExecutionConfig());
calleeClazzFile = finder.getClazzFile(module, callee);
shortenTest();
}
private void shortenTest() {
if (!lastShortenedMap.isEmpty()) {
throw new RuntimeException("Only use TestShortener once!");
}
if (calleeClazzFile != null) {
try {
shortenTestClazz(callee, calleeClazzFile);
for (final File superclass : superclasses) {
if (!lastShortenedMap.containsValue(superclass)) {
// A rather dirty hack..
final Type callee = new Type(superclass.getName().replaceAll(".java", ""), this.callee.getModule());
LOG.debug("Shortening: " + callee);
shortenTestClazz(callee, superclass);
}
}
} catch (final IOException e1) {
e1.printStackTrace();
}
} else {
throw new RuntimeException("Could not find " + callee.getModule() + "(module) " + callee.getClazz() + " java file in " + module + " - maybe package missing?");
}
}
public File getCalleeClazzFile() {
return calleeClazzFile;
}
private void shortenTestClazz(final Type callee, final File calleeClazzFile) throws IOException {
final int version = transformer.getVersion(calleeClazzFile);
if (version != 0) {
saveUnshortened(calleeClazzFile);
final CompilationUnit calleeUnit = transformer.getLoadedFiles().get(calleeClazzFile);
final TypeDeclaration> clazz = TypeFinder.findClazz(callee, calleeUnit.getChildNodes());
// The clazz might be null, if it is
if (clazz != null && clazz instanceof ClassOrInterfaceDeclaration) {
shortenParent(module, callee, calleeClazzFile, calleeUnit, (ClassOrInterfaceDeclaration) clazz);
removeNonWanted(method, version, (ClassOrInterfaceDeclaration) clazz);
FileUtils.writeStringToFile(calleeClazzFile, calleeUnit.toString(), Charset.defaultCharset());
}
}
}
private void saveUnshortened(final File calleeClazzFile) throws IOException {
final File tempFile = Files.createTempFile("Temp", ".java").toFile();
FileUtils.copyFile(calleeClazzFile, tempFile);
lastShortenedMap.put(tempFile, calleeClazzFile);
}
public void shortenParent(final File module, final Type callee, final File calleeClazzFile, final CompilationUnit calleeUnit, final ClassOrInterfaceDeclaration clazz)
throws IOException {
LOG.debug("Shortening: {}", callee);
if (clazz.getExtendedTypes().size() > 0) {
final Type parentEntity = getParentEntity(callee, calleeUnit, clazz);
TypeFileFinder finder = new TypeFileFinder(transformer.getConfig().getExecutionConfig());
final File parentClazzFile = finder.getClazzFile(module, parentEntity);
if (parentClazzFile != null) {
shortenTestClazz(parentEntity, parentClazzFile);
}
final int version = transformer.getVersion(calleeClazzFile);
if (version == 3 || version == 34) {
final String simpleClazzName = callee.getSimpleClazzName();
addSuperclasses(simpleClazzName);
}
}
}
public void addSuperclasses(final String simpleClazzName) {
final List thisSuperclasses = transformer.getExtensions().get(simpleClazzName);
if (thisSuperclasses != null) {
LOG.debug("Must shorten suclasses: {}", thisSuperclasses);
superclasses.addAll(thisSuperclasses);
for (final File superclass : thisSuperclasses) {
final String supersuperclass = superclass.getName().substring(0, superclass.getName().lastIndexOf('.'));
addSuperclasses(supersuperclass);
}
}
}
public Type getParentEntity(final Type callee, final CompilationUnit calleeUnit, final ClassOrInterfaceDeclaration clazz) {
Type parentEntity = null;
for (final ClassOrInterfaceType parent : clazz.getExtendedTypes()) {
LOG.debug("Must also shorten {} Package: {}", parent, callee.getPackage());
final String parentName = parent.getName().toString();
String fqn = findFQN(calleeUnit, parentName);
if (fqn == parentName) {
if (callee.getPackage().equals("")) {
fqn = parentName;
} else {
fqn = callee.getPackage() + "." + parentName;
}
}
parentEntity = new Type(fqn, callee.getModule());
}
return parentEntity;
}
private void removeNonWanted(final String method, final int version, final ClassOrInterfaceDeclaration clazz) {
final List remove = new LinkedList<>();
for (final MethodDeclaration methodDeclaration : clazz.getMethods()) {
if (!methodDeclaration.getNameAsString().equals(method)) {
if (methodDeclaration.getModifiers().contains(Modifier.publicModifier()) &&
methodDeclaration.getParameters().size() == 0) {
if (version == 3) {
if (methodDeclaration.getNameAsString().contains("test")) {
remove.add(methodDeclaration);
}
} else {
removeTestAnnotations(methodDeclaration);
}
}
removeParameterizedTestAnnotations(methodDeclaration);
}
}
for (final Node removeN : remove) {
clazz.remove(removeN);
}
}
private void removeParameterizedTestAnnotations(final MethodDeclaration methodDeclaration) {
final Optional parameterizedTestAnnotation = methodDeclaration.getAnnotationByName("ParameterizedTest");
final Optional testAnnotationFQNJunit5Parameterized = methodDeclaration.getAnnotationByName("org.junit.jupiter.api.ParameterizedTest");
if (parameterizedTestAnnotation.isPresent()) {
methodDeclaration.getAnnotations().remove(parameterizedTestAnnotation.get());
}
if (testAnnotationFQNJunit5Parameterized.isPresent()) {
methodDeclaration.getAnnotations().remove(testAnnotationFQNJunit5Parameterized.get());
}
}
private void removeTestAnnotations(final MethodDeclaration methodDeclaration) {
final Optional testAnnotation = methodDeclaration.getAnnotationByName("Test");
final Optional testAnnotationFQNJUnit4 = methodDeclaration.getAnnotationByName("org.junit.Test");
final Optional testAnnotationFQNJunit5 = methodDeclaration.getAnnotationByName("org.junit.jupiter.api.Test");
if (testAnnotation.isPresent()) {
methodDeclaration.getAnnotations().remove(testAnnotation.get());
}
if (testAnnotationFQNJUnit4.isPresent()) {
methodDeclaration.getAnnotations().remove(testAnnotationFQNJUnit4.get());
}
if (testAnnotationFQNJunit5.isPresent()) {
methodDeclaration.getAnnotations().remove(testAnnotationFQNJunit5.get());
}
}
public String findFQN(final CompilationUnit calleeUnit, final String parentName) {
String fqn = parentName;
for (final ImportDeclaration importDecl : calleeUnit.getImports()) {
if (importDecl.getNameAsString().endsWith(parentName)) {
fqn = importDecl.getNameAsString();
}
}
return fqn;
}
private void resetShortenedFile() {
if (lastShortenedMap != null) {
for (final Map.Entry shortened : lastShortenedMap.entrySet()) {
try {
final File destFile = shortened.getValue();
destFile.delete();
LOG.debug("File to reset: {} Exists: {} Parent exists: {}", destFile, destFile.exists(), destFile.getParentFile().exists());
Path dest = destFile.toPath();
Path source = shortened.getKey().toPath();
Files.move(source, dest);
final CompilationUnit unit = JavaParserProvider.parse(destFile);
transformer.getLoadedFiles().put(destFile, unit);
} catch (final IOException e) {
e.printStackTrace();
}
}
}
}
@Override
public void close() throws Exception {
resetShortenedFile();
}
}