All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.stamp_project.dspot.selector.ChangeDetectorSelector Maven / Gradle / Ivy

package eu.stamp_project.dspot.selector;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import eu.stamp_project.dspot.common.automaticbuilder.AutomaticBuilder;
import eu.stamp_project.dspot.common.automaticbuilder.maven.DSpotPOMCreator;
import eu.stamp_project.dspot.common.report.output.selector.TestSelectorElementReport;
import eu.stamp_project.dspot.common.report.output.selector.TestSelectorElementReportImpl;
import eu.stamp_project.dspot.common.report.output.selector.change.json.TestCaseJSON;
import eu.stamp_project.dspot.common.report.output.selector.change.json.TestClassJSON;
import eu.stamp_project.dspot.common.test_framework.TestFramework;
import eu.stamp_project.testrunner.listener.TestResult;
import eu.stamp_project.testrunner.runner.Failure;
import eu.stamp_project.dspot.common.configuration.UserInput;
import eu.stamp_project.dspot.common.miscellaneous.AmplificationHelper;
import eu.stamp_project.dspot.common.miscellaneous.Counter;
import eu.stamp_project.dspot.common.miscellaneous.DSpotUtils;
import eu.stamp_project.dspot.common.compilation.DSpotCompiler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;

import java.io.*;
import java.util.*;

/**
 * Created by Benjamin DANGLOT
 * [email protected]
 * on 09/08/17
 */
public class ChangeDetectorSelector extends AbstractTestSelector {

    private static final Logger LOGGER = LoggerFactory.getLogger(ChangeDetectorSelector.class);

    private String pathToFirstVersionOfProgram;

    private String pathToSecondVersionOfProgram;

    private Map, Failure> failurePerAmplifiedTest;

    private CtType currentClassTestToBeAmplified;

    private String secondVersionTargetClasses;

    public ChangeDetectorSelector(AutomaticBuilder automaticBuilder,
                                  UserInput configuration) {
        super(automaticBuilder, configuration);
        this.failurePerAmplifiedTest = new HashMap<>();
        this.pathToFirstVersionOfProgram = DSpotUtils.shouldAddSeparator.apply(configuration.getAbsolutePathToProjectRoot());
        this.pathToSecondVersionOfProgram = DSpotUtils.shouldAddSeparator.apply(configuration.getAbsolutePathToSecondVersionProjectRoot());
        try {
            this.automaticBuilder.setAbsolutePathToProjectRoot(this.pathToSecondVersionOfProgram);
            configuration.setAbsolutePathToProjectRoot(this.pathToSecondVersionOfProgram);
            this.secondVersionTargetClasses = configuration.getClasspathClassesProject();
            DSpotPOMCreator.createNewPom(configuration);
            this.automaticBuilder.compile();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            this.automaticBuilder.setAbsolutePathToProjectRoot(this.pathToFirstVersionOfProgram);
            configuration.setAbsolutePathToProjectRoot(this.pathToFirstVersionOfProgram);
        }
    }

    @Override
    public boolean init() {

        return true;
    }

    @Override
    public List> selectToAmplify(CtType classTest, List> testsToBeAmplified) {
        if (this.currentClassTestToBeAmplified == null) {
            this.currentClassTestToBeAmplified = classTest;
            this.failurePerAmplifiedTest.clear();
        }
        return testsToBeAmplified;
    }


    @Override
    public List> selectToKeep(List> amplifiedTestToBeKept) {
        if (amplifiedTestToBeKept.isEmpty()) {
            return amplifiedTestToBeKept;
        }
        CtType clone = this.currentClassTestToBeAmplified.clone();
        clone.setParent(this.currentClassTestToBeAmplified.getParent());
        this.currentClassTestToBeAmplified.getMethods().stream()
                 .filter(TestFramework.get()::isTest)
                .forEach(clone::removeMethod);
        amplifiedTestToBeKept.forEach(clone::addMethod);

        DSpotUtils.printCtTypeToGivenDirectory(clone, new File(DSpotCompiler.getPathToAmplifiedTestSrc()));
        final String pathToAmplifiedTestSrc = DSpotCompiler.getPathToAmplifiedTestSrc();

        this.automaticBuilder.setAbsolutePathToProjectRoot(this.pathToSecondVersionOfProgram);
        if (!DSpotCompiler.compile(
                pathToAmplifiedTestSrc,
                this.classpath + AmplificationHelper.PATH_SEPARATOR + this.secondVersionTargetClasses,
                new File(this.pathToSecondVersionOfProgram + this.pathToTestClasses)
        )) {
            LOGGER.warn("Something went bad during the compilation of the amplified test methods using the second version.");
            // add an error in the Main Global error report
        }
        final TestResult results;
        try {
            results = this.testRunner.run(
                    this.classpath + AmplificationHelper.PATH_SEPARATOR + this.secondVersionTargetClasses,
                    this.pathToSecondVersionOfProgram,
                    clone.getQualifiedName(),
                    amplifiedTestToBeKept.stream()
                            .map(CtMethod::getSimpleName)
                            .toArray(String[]::new));
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            this.automaticBuilder.setAbsolutePathToProjectRoot(this.pathToFirstVersionOfProgram);
        }
        final List> amplifiedThatWillBeKept = new ArrayList<>();
        if (!results.getFailingTests().isEmpty()) {
            results.getFailingTests()
                    .forEach(failure -> {
                                final CtMethod key = amplifiedTestToBeKept.stream()
                                        .filter(ctMethod -> ctMethod.getSimpleName().equals(failure.testCaseName))
                                        .findFirst()
                                        .get();
                                amplifiedThatWillBeKept.add(key);
                                this.failurePerAmplifiedTest.put(key, failure);
                            }
                    );
        }
        return amplifiedThatWillBeKept;
    }

    @Override
    public List> getAmplifiedTestCases() {
        return new ArrayList<>(this.failurePerAmplifiedTest.keySet());
    }

    protected void reset() {
        this.currentClassTestToBeAmplified = null;
    }

    @Override
    public TestSelectorElementReport report() {
        final StringBuilder output = new StringBuilder();
        output.append(this.failurePerAmplifiedTest.size()).append(" amplified test fails on the new versions.");
        this.failurePerAmplifiedTest.keySet()
                .stream()
                .map(this.failurePerAmplifiedTest::get)
                .map(Object::toString)
                .map(AmplificationHelper.LINE_SEPARATOR::concat)
                .forEachOrdered(output::append);
        this.failurePerAmplifiedTest.keySet()
                .forEach(amplifiedTest ->
                        output.append(this.failurePerAmplifiedTest.get(amplifiedTest).stackTrace)
                );
        final TestClassJSON testClassJSON = this.reportJson();
        this.reset();
        return new TestSelectorElementReportImpl(output.toString(), testClassJSON, Collections.emptyList(), "");
    }

    private TestClassJSON reportJson() {
        if (this.currentClassTestToBeAmplified == null) {
            return null;
        }
        TestClassJSON testClassJSON;
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        final File file = new File(this.outputDirectory + "/" + this.currentClassTestToBeAmplified.getQualifiedName() + "report.json");
        if (file.exists()) {
            try {
                testClassJSON = gson.fromJson(new FileReader(file), TestClassJSON.class);
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        } else {
            testClassJSON = new TestClassJSON(
                    this.currentClassTestToBeAmplified.getQualifiedName(),
                    TestFramework.getAllTest(this.currentClassTestToBeAmplified).size()
            );
        }
        this.failurePerAmplifiedTest.keySet().stream()
                .map(ctMethod ->
                        new TestCaseJSON(ctMethod.getSimpleName(), Counter.getInputOfSinceOrigin(ctMethod), Counter.getAssertionOfSinceOrigin(ctMethod))
                ).forEach(testClassJSON.testCases::add);
        return testClassJSON;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy