diff --git a/dspot-diff-test-selection/src/main/java/com/atlassian/clover/reporters/html/RenderFileAction.java b/dspot-diff-test-selection/src/main/java/com/atlassian/clover/reporters/html/RenderFileAction.java index 8f0ba7f6f..9ecd137ed 100644 --- a/dspot-diff-test-selection/src/main/java/com/atlassian/clover/reporters/html/RenderFileAction.java +++ b/dspot-diff-test-selection/src/main/java/com/atlassian/clover/reporters/html/RenderFileAction.java @@ -37,7 +37,6 @@ import java.util.BitSet; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -294,11 +293,10 @@ private boolean isSetForThisTest(Map m, int i) { TODO Implement our own reporter, that compute this information, and do not build the whole HTML report TODO which is unused in DSpot */ + final JSONObject jsonTestTargets = JSONObjectFactory.getJSONTestTargets(targetMethods, targetElements); final String targetClassName = this.fileInfo.getContainingPackage().getName() + "." + this.fileInfo.getName().split("\\.")[0]; - if (!CloverReader.coveragePerTestMethods.containsKey(targetClassName)) { - this.buildCoverage(sublist, jsonTestTargets, targetClassName); - } + this.buildCoverage(sublist, jsonTestTargets, targetClassName); velocity.put("jsonTestTargets", jsonTestTargets); velocity.put("jsonPageData", JSONObjectFactory.getJSONPageData(fileInfo)); @@ -318,22 +316,33 @@ private void buildCoverage(List> sublist, final TestCaseInfo testCaseInfo = getTestCaseInfo(sublist, key.split("_")[1]); final String testClassName = testCaseInfo.getRuntimeTypeName(); final String testName = testCaseInfo.getTestName(); - if (!CloverReader.coveragePerTestMethods.containsKey(testClassName)) { - CloverReader.coveragePerTestMethods.put(testClassName, new HashMap<>()); - } - if (!CloverReader.coveragePerTestMethods.get(testClassName).containsKey(testName)) { - CloverReader.coveragePerTestMethods.get(testClassName).put(testName, new HashMap<>()); - } - if (!CloverReader.coveragePerTestMethods.get(testClassName).get(testName).containsKey(targetClassName)) { - CloverReader.coveragePerTestMethods.get(testClassName).get(testName).put(targetClassName, new ArrayList<>()); - } JSONObject currentValues = jsonTestTargets.getJSONObject((String) key); ((List) currentValues.get("statements")).stream() .map(list -> ((Map) list).get("sl")) - .forEach(line -> - CloverReader.coveragePerTestMethods.get(testClassName).get(testName).get(targetClassName).add((Integer) line) - ); - + .forEach(line -> { + try { + final int hitCount = this.fileInfo.getNamedClass(this.fileInfo.getName().split("\\.")[0]) + .getAllMethods() + .stream() + .flatMap(methodInfo -> methodInfo.getStatements().stream()) + .filter(statementInfo -> statementInfo.getStartLine() == (Integer) line) + .findFirst() + .get() + .getHitCount(); + CloverReader.coverage.addCoverage(testClassName, testName, targetClassName, (Integer) line, hitCount); + } catch (Exception e) { + e.printStackTrace(); + final int hitCount = this.fileInfo.getNamedClass(this.fileInfo.getName().split("\\.")[0]) + .getAllMethods() + .stream() + .flatMap(methodInfo -> methodInfo.getStatements().stream()) + .filter(statementInfo -> statementInfo.getStartLine() == (Integer) line) + .findFirst() + .get() + .getHitCount(); + CloverReader.coverage.addCoverage(testClassName, testName, targetClassName, (Integer) line, hitCount); + } + }); } } diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/Main.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/Main.java index 9467be80b..02dec838d 100644 --- a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/Main.java +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/Main.java @@ -5,6 +5,7 @@ import eu.stamp_project.diff_test_selection.configuration.Configuration; import eu.stamp_project.diff_test_selection.configuration.Options; import eu.stamp_project.diff_test_selection.coverage.Coverage; +import eu.stamp_project.diff_test_selection.coverage.DiffCoverage; import eu.stamp_project.diff_test_selection.selector.DiffTestSelection; import eu.stamp_project.diff_test_selection.selector.DiffTestSelectionImpl; import eu.stamp_project.diff_test_selection.selector.EnhancedDiffTestSelection; @@ -28,7 +29,7 @@ public static void main(String[] args) { public static void run(Configuration configuration) { final Map> selectedTests; - final Coverage coverage = new Coverage(); + final DiffCoverage coverage = new DiffCoverage(); if (configuration.enhanced) { LOGGER.info("Running in enhanced mode..."); selectedTests = enhancedRun(configuration, coverage); @@ -39,8 +40,8 @@ public static void run(Configuration configuration) { output(configuration, coverage, selectedTests); } - public static Map> _run(Configuration configuration, Coverage coverage) { - final Map>>> cloverCoverage = getCoverage(configuration.pathToFirstVersion); + public static Map> _run(Configuration configuration, DiffCoverage coverage) { + final Coverage cloverCoverage = getCoverage(configuration.pathToFirstVersion); final DiffTestSelection diffTestSelectionImpl = new DiffTestSelectionImpl( configuration.pathToFirstVersion, configuration.pathToSecondVersion, @@ -51,11 +52,9 @@ public static Map> _run(Configuration configuration, Coverag return diffTestSelectionImpl.selectTests(); } - private static Map> enhancedRun(Configuration configuration, Coverage coverage) { - final Map>>> cloverCoverageV1 = - getCoverage(configuration.pathToFirstVersion); - final Map>>> cloverCoverageV2 = - getCoverage(configuration.pathToSecondVersion); + private static Map> enhancedRun(Configuration configuration, DiffCoverage coverage) { + final Coverage cloverCoverageV1 = getCoverage(configuration.pathToFirstVersion); + final Coverage cloverCoverageV2 = getCoverage(configuration.pathToSecondVersion); return new EnhancedDiffTestSelection( configuration.pathToFirstVersion, configuration.pathToSecondVersion, @@ -66,7 +65,7 @@ private static Map> enhancedRun(Configuration configuration, ).selectTests(); } - private static void output(Configuration configuration, Coverage coverage, Map> selectedTests) { + private static void output(Configuration configuration, DiffCoverage coverage, Map> selectedTests) { LOGGER.info("Saving result in " + configuration.outputPath + " ..."); configuration.reportFormat.instance.report( configuration.outputPath, @@ -75,7 +74,7 @@ private static void output(Configuration configuration, Coverage coverage, Map>>> getCoverage(final String pathToFirstVersion) { + private static Coverage getCoverage(final String pathToFirstVersion) { LOGGER.info("Computing coverage for " + pathToFirstVersion); new CloverExecutor().instrumentAndRunTest(pathToFirstVersion); return new CloverReader().read(pathToFirstVersion); diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/clover/CloverReader.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/clover/CloverReader.java index 0a0b452b5..ccc795e59 100644 --- a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/clover/CloverReader.java +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/clover/CloverReader.java @@ -1,11 +1,9 @@ package eu.stamp_project.diff_test_selection.clover; import com.atlassian.clover.reporters.html.HtmlReporter; +import eu.stamp_project.diff_test_selection.coverage.Coverage; import java.io.File; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; /** * Created by Benjamin DANGLOT @@ -20,7 +18,7 @@ public class CloverReader { private static final String REPORT_DIRECTORY = "/report/"; - public volatile static Map>>> coveragePerTestMethods = new LinkedHashMap<>(); + public volatile static Coverage coverage = new Coverage(); /** * read the database initialize by {@link CloverExecutor}. @@ -28,8 +26,10 @@ public class CloverReader { * @param directory path to the directory of Clover's result * @return a map, that associate test method names and the map of executed line in each classes */ - public Map>>> read(String directory) { + public Coverage read(String directory) { + coverage = new Coverage(); final File rootDirectoryOfCloverFiles = new File(directory + ROOT_DIRECTORY); + System.out.println("Reading Clover data " + rootDirectoryOfCloverFiles.getAbsolutePath()); HtmlReporter.runReport(new String[]{ "-i", rootDirectoryOfCloverFiles.getAbsolutePath() + DATABASE_FILE, "-o", rootDirectoryOfCloverFiles.getAbsolutePath() + REPORT_DIRECTORY, @@ -37,7 +37,7 @@ public Map>>> read(String director "--showinner", "--showlambda", }); - return coveragePerTestMethods; + return coverage; } } diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/configuration/Configuration.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/configuration/Configuration.java index 52d7c2f93..6a178e4e2 100644 --- a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/configuration/Configuration.java +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/configuration/Configuration.java @@ -6,7 +6,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.xml.transform.sax.SAXSource; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/ClassCoverage.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/ClassCoverage.java new file mode 100644 index 000000000..cd7d2830d --- /dev/null +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/ClassCoverage.java @@ -0,0 +1,49 @@ +package eu.stamp_project.diff_test_selection.coverage; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Benjamin DANGLOT + * benjamin.danglot@davidson.fr + * on 14/06/2021 + */ +public class ClassCoverage { + + public final String className; + + public final List coverages; + + public ClassCoverage(String className) { + this.className = className; + this.coverages = new ArrayList<>(); + } + + public void addCoverage(int line, int hitCounts) { + this.coverages.add(new LineCoverage(line, hitCounts)); + } + + public List getCoverages() { + return this.coverages; + } + + public boolean contains(int line) { + return this.coverages.stream().anyMatch(lineCoverage -> lineCoverage.line == line); + } + + public int getHitCountForLine(int line) { + return this.coverages.stream() + .filter(coverage -> coverage.line == line) + .findFirst() + .orElse(new LineCoverage(0, 0)) + .hitCount; + } + + @Override + public String toString() { + return "ClassCoverage{" + + "className='" + className + '\'' + + ", coverages=" + coverages + + '}'; + } +} diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/Coverage.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/Coverage.java index 6bd150172..bae9efbd3 100644 --- a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/Coverage.java +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/Coverage.java @@ -1,80 +1,60 @@ package eu.stamp_project.diff_test_selection.coverage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.*; +import java.util.stream.Collectors; /** - * created by Benjamin DANGLOT - * benjamin.danglot@inria.fr - * on 21/09/18 - *

- * This class is responsible to compute the Coverage of the provided diff. + * @author Benjamin DANGLOT + * benjamin.danglot@davidson.fr + * on 14/06/2021 */ public class Coverage { - private Map> executedLinePerQualifiedName; - - private Map> modifiedLinePerQualifiedName; - - private static final Logger LOGGER = LoggerFactory.getLogger(Coverage.class); + public final Map testClassCoverage; public Coverage() { - this.modifiedLinePerQualifiedName = new LinkedHashMap<>(); - this.executedLinePerQualifiedName = new LinkedHashMap<>(); + this.testClassCoverage = new LinkedHashMap<>(); } - public void covered(String fullQualifiedName, Integer line) { - if (!this.executedLinePerQualifiedName.containsKey(fullQualifiedName)) { - this.executedLinePerQualifiedName.put(fullQualifiedName, new HashSet<>()); - } - if (this.modifiedLinePerQualifiedName.containsKey(fullQualifiedName) && - this.modifiedLinePerQualifiedName.get(fullQualifiedName).contains(line) - && this.executedLinePerQualifiedName.get(fullQualifiedName).add(line)) { - LOGGER.info(fullQualifiedName + ":" + line + " covered."); + public void addCoverage(String testClassName, String testMethodName, String className, int line, int hitCounts) { + if (!this.testClassCoverage.containsKey(testClassName)) { + this.testClassCoverage.put(testClassName, new TestClassCoverage(testClassName)); } + this.testClassCoverage.get(testClassName).addCoverage(testMethodName, className, line, hitCounts); } - public void addModifiedLines(String fullQualifiedName, List lines) { - if (!this.modifiedLinePerQualifiedName.containsKey(fullQualifiedName)) { - this.modifiedLinePerQualifiedName.put(fullQualifiedName, new HashSet<>()); - } - lines.forEach(this.modifiedLinePerQualifiedName.get(fullQualifiedName)::add); - LOGGER.info(fullQualifiedName + ":" + lines.toString() + " are modified."); + public Set getTestClasses() { + return this.testClassCoverage.keySet(); } - public void addModifiedLine(String fullQualifiedName, Integer line) { - if (!this.modifiedLinePerQualifiedName.containsKey(fullQualifiedName)) { - this.modifiedLinePerQualifiedName.put(fullQualifiedName, new HashSet<>()); - } - this.modifiedLinePerQualifiedName.get(fullQualifiedName).add(line); - LOGGER.info(fullQualifiedName + ":" + line + " is modified."); + public Set getClassesForTestClassAndMethodName(String testClassName, String testMethodName) { + return this.testClassCoverage.get(testClassName).getClassesForTestMethodName(testMethodName); } - @Deprecated - public void addModifiedLines(final Map> newModifiedLinesPerQualifiedName) { - newModifiedLinesPerQualifiedName.keySet() - .forEach(key -> { - if (!this.modifiedLinePerQualifiedName.containsKey(key)) { - this.modifiedLinePerQualifiedName.put(key, new HashSet<>()); - } - newModifiedLinesPerQualifiedName.get(key) - .forEach(line -> { - if (this.modifiedLinePerQualifiedName.get(key).add(line)) { - LOGGER.info(key + ":" + line + " is modified."); - } - } - ); - } - ); + public Set getTestMethodsForTestClassName(String testClassName) { + return this.testClassCoverage.get(testClassName).getTestMethods(); } - public Map> getExecutedLinePerQualifiedName() { - return executedLinePerQualifiedName; + public List getCoverageForTestClassTestMethodAndClassNames(String testClassName, String testMethodName, String className) { + return this.testClassCoverage.get(testClassName).getCoverageForTestMethodAndClassNames(testMethodName, className); + } + + public Map getTestMethodCoverageForClassName(String testClassName, String testMethodName) { + return this.testClassCoverage.get(testClassName).getTestMethodCoverage(testMethodName); + } + + public Map getHitCountFromClassNameForLineForAll(String className, int line) { + final Map allHitCountFromClassNameForLine = new HashMap<>(); + for (TestClassCoverage value : this.testClassCoverage.values()) { + allHitCountFromClassNameForLine.putAll(value.getHitCountFromClassNameForLineForAll(className, line)); + } + return allHitCountFromClassNameForLine; } - public Map> getModifiedLinePerQualifiedName() { - return modifiedLinePerQualifiedName; + @Override + public String toString() { + return "Coverage{" + + "testClassCoverage=" + testClassCoverage.toString() + + '}'; } } diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/DiffCoverage.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/DiffCoverage.java new file mode 100644 index 000000000..c2a93a9fd --- /dev/null +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/DiffCoverage.java @@ -0,0 +1,80 @@ +package eu.stamp_project.diff_test_selection.coverage; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +/** + * created by Benjamin DANGLOT + * benjamin.danglot@inria.fr + * on 21/09/18 + *

+ * This class is responsible to compute the Coverage of the provided diff. + */ +public class DiffCoverage { + + private Map> executedLinePerQualifiedName; + + private Map> modifiedLinePerQualifiedName; + + private static final Logger LOGGER = LoggerFactory.getLogger(DiffCoverage.class); + + public DiffCoverage() { + this.modifiedLinePerQualifiedName = new LinkedHashMap<>(); + this.executedLinePerQualifiedName = new LinkedHashMap<>(); + } + + public void covered(String fullQualifiedName, Integer line) { + if (!this.executedLinePerQualifiedName.containsKey(fullQualifiedName)) { + this.executedLinePerQualifiedName.put(fullQualifiedName, new HashSet<>()); + } + if (this.modifiedLinePerQualifiedName.containsKey(fullQualifiedName) && + this.modifiedLinePerQualifiedName.get(fullQualifiedName).contains(line) + && this.executedLinePerQualifiedName.get(fullQualifiedName).add(line)) { + LOGGER.info(fullQualifiedName + ":" + line + " covered."); + } + } + + public void addModifiedLines(String fullQualifiedName, List lines) { + if (!this.modifiedLinePerQualifiedName.containsKey(fullQualifiedName)) { + this.modifiedLinePerQualifiedName.put(fullQualifiedName, new HashSet<>()); + } + lines.forEach(this.modifiedLinePerQualifiedName.get(fullQualifiedName)::add); + LOGGER.info(fullQualifiedName + ":" + lines.toString() + " are modified."); + } + + public void addModifiedLine(String fullQualifiedName, Integer line) { + if (!this.modifiedLinePerQualifiedName.containsKey(fullQualifiedName)) { + this.modifiedLinePerQualifiedName.put(fullQualifiedName, new HashSet<>()); + } + this.modifiedLinePerQualifiedName.get(fullQualifiedName).add(line); + LOGGER.info(fullQualifiedName + ":" + line + " is modified."); + } + + @Deprecated + public void addModifiedLines(final Map> newModifiedLinesPerQualifiedName) { + newModifiedLinesPerQualifiedName.keySet() + .forEach(key -> { + if (!this.modifiedLinePerQualifiedName.containsKey(key)) { + this.modifiedLinePerQualifiedName.put(key, new HashSet<>()); + } + newModifiedLinesPerQualifiedName.get(key) + .forEach(line -> { + if (this.modifiedLinePerQualifiedName.get(key).add(line)) { + LOGGER.info(key + ":" + line + " is modified."); + } + } + ); + } + ); + } + + public Map> getExecutedLinePerQualifiedName() { + return executedLinePerQualifiedName; + } + + public Map> getModifiedLinePerQualifiedName() { + return modifiedLinePerQualifiedName; + } +} diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/LineCoverage.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/LineCoverage.java new file mode 100644 index 000000000..20d1dfb23 --- /dev/null +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/LineCoverage.java @@ -0,0 +1,26 @@ +package eu.stamp_project.diff_test_selection.coverage; + +/** + * @author Benjamin DANGLOT + * benjamin.danglot@davidson.fr + * on 14/06/2021 + */ +public class LineCoverage { + + public final int line; + + public final int hitCount; + + public LineCoverage(int line, int hitCount) { + this.line = line; + this.hitCount = hitCount; + } + + @Override + public String toString() { + return "LineCoverage{" + + "line=" + line + + ", hitCount=" + hitCount + + '}'; + } +} diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/TestClassCoverage.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/TestClassCoverage.java new file mode 100644 index 000000000..26e0dc2d8 --- /dev/null +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/TestClassCoverage.java @@ -0,0 +1,60 @@ +package eu.stamp_project.diff_test_selection.coverage; + +import java.util.*; + +/** + * @author Benjamin DANGLOT + * benjamin.danglot@davidson.fr + * on 14/06/2021 + */ +public class TestClassCoverage { + + public final String testClassName; + + public final Map testMethodsCoverage; + + public TestClassCoverage(String testClassName) { + this.testClassName = testClassName; + this.testMethodsCoverage = new LinkedHashMap<>(); + } + + public void addCoverage(String testMethodName, String className, int line, int hitCounts) { + if (!this.testMethodsCoverage.containsKey(testMethodName)) { + this.testMethodsCoverage.put(testMethodName, new TestMethodCoverage(testMethodName)); + } + this.testMethodsCoverage.get(testMethodName).addCoverage(className, line, hitCounts); + } + + public Set getTestMethods() { + return this.testMethodsCoverage.keySet(); + } + + public Set getClassesForTestMethodName(String testMethodName) { + return this.testMethodsCoverage.get(testMethodName).getClasses(); + } + + public List getCoverageForTestMethodAndClassNames(String testMethodName, String className) { + return this.testMethodsCoverage.get(testMethodName).getCoverageForClass(className); + } + + public Map getTestMethodCoverage(String testMethodName) { + return this.testMethodsCoverage.get(testMethodName).classCoverageList; + } + + public Map getHitCountFromClassNameForLineForAll(String className, int line) { + final Map hitCountForLinePerTestMethodName = new HashMap<>(); + for (TestMethodCoverage testMethodCoverage : testMethodsCoverage.values()) { + final int hitCountFromClassNameForLine = testMethodCoverage.getHitCountFromClassNameForLine(className, line); + hitCountForLinePerTestMethodName.put(this.testClassName + "#" + testMethodCoverage.testMethodName, hitCountFromClassNameForLine); + } + return hitCountForLinePerTestMethodName; + } + + @Override + public String toString() { + return "TestClassCoverage{" + + "testClassName='" + testClassName + '\'' + + ", testMethodsCoverage=" + testMethodsCoverage + + '}'; + } +} diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/TestMethodCoverage.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/TestMethodCoverage.java new file mode 100644 index 000000000..743831768 --- /dev/null +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/coverage/TestMethodCoverage.java @@ -0,0 +1,47 @@ +package eu.stamp_project.diff_test_selection.coverage; + +import java.util.*; + +/** + * @author Benjamin DANGLOT + * benjamin.danglot@davidson.fr + * on 14/06/2021 + */ +public class TestMethodCoverage { + + public final String testMethodName; + + public final Map classCoverageList; + + public TestMethodCoverage(String testMethodName) { + this.testMethodName = testMethodName; + this.classCoverageList = new LinkedHashMap<>(); + } + + public void addCoverage(String className, int line, int hitCounts) { + if (!this.classCoverageList.containsKey(className)) { + this.classCoverageList.put(className, new ClassCoverage(className)); + } + this.classCoverageList.get(className).addCoverage(line, hitCounts); + } + + public Set getClasses() { + return this.classCoverageList.keySet(); + } + + public List getCoverageForClass(String className) { + return this.classCoverageList.get(className).getCoverages(); + } + + public int getHitCountFromClassNameForLine(String className, int line) { + return this.classCoverageList.get(className).getHitCountForLine(line); + } + + @Override + public String toString() { + return "TestMethodCoverage{" + + "testMethodName='" + testMethodName + '\'' + + ", classCoverageList=" + classCoverageList + + '}'; + } +} diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/report/CSVReport.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/report/CSVReport.java index 6e1875f7e..37c7c0a9c 100644 --- a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/report/CSVReport.java +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/report/CSVReport.java @@ -1,15 +1,12 @@ package eu.stamp_project.diff_test_selection.report; -import eu.stamp_project.diff_test_selection.Main; -import eu.stamp_project.diff_test_selection.coverage.Coverage; -import org.apache.maven.plugin.logging.Log; +import eu.stamp_project.diff_test_selection.coverage.DiffCoverage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -30,7 +27,7 @@ public class CSVReport implements Report { @Override public void report(final String outputPath, final Map> testThatExecuteChanges, - final Coverage coverage) { + final DiffCoverage coverage) { final File file = new File(outputPath); StringBuilder builder = new StringBuilder(); String report = testThatExecuteChanges.keySet() @@ -54,7 +51,7 @@ public void report(final String outputPath, } private void reportCoverageOfDiff(final String outputPath, - final Coverage coverage) { + final DiffCoverage coverage) { final String output = outputPath.substring(0, outputPath.length() - ".csv".length()) + "_coverage.csv"; LOGGER.info("Writing Coverage in " + output); final Map> executedLinePerQualifiedName = coverage.getExecutedLinePerQualifiedName(); diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/report/Report.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/report/Report.java index 07b493639..98adf5986 100644 --- a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/report/Report.java +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/report/Report.java @@ -1,8 +1,6 @@ package eu.stamp_project.diff_test_selection.report; -import eu.stamp_project.diff_test_selection.coverage.Coverage; -import org.apache.maven.plugin.Mojo; -import org.apache.maven.plugin.logging.Log; +import eu.stamp_project.diff_test_selection.coverage.DiffCoverage; import java.util.Map; import java.util.Set; @@ -23,6 +21,6 @@ public interface Report { void report( final String outputPath, final Map> testThatExecuteChanges, - final Coverage coverage); + final DiffCoverage coverage); } diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/DiffTestSelection.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/DiffTestSelection.java index c6db3f1ce..0db66c7b8 100644 --- a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/DiffTestSelection.java +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/DiffTestSelection.java @@ -1,8 +1,8 @@ package eu.stamp_project.diff_test_selection.selector; import eu.stamp_project.diff_test_selection.coverage.Coverage; +import eu.stamp_project.diff_test_selection.coverage.DiffCoverage; -import java.util.List; import java.util.Map; import java.util.Set; @@ -10,11 +10,11 @@ public abstract class DiffTestSelection { protected final String pathToFirstVersion; protected final String pathToSecondVersion; - protected final Map>>> coverageV1; + protected final Coverage coverageV1; protected final String diff; - protected final Coverage coverage; + protected final DiffCoverage coverage; - public DiffTestSelection(String pathToFirstVersion, String pathToSecondVersion, Map>>> coverageV1, String diff, Coverage coverage) { + public DiffTestSelection(String pathToFirstVersion, String pathToSecondVersion, Coverage coverageV1, String diff, DiffCoverage coverage) { this.pathToFirstVersion = pathToFirstVersion; this.pathToSecondVersion = pathToSecondVersion; this.coverageV1 = coverageV1; @@ -24,7 +24,7 @@ public DiffTestSelection(String pathToFirstVersion, String pathToSecondVersion, public abstract Map> selectTests(); - public Coverage getCoverage() { + public DiffCoverage getCoverage() { return this.coverage; } diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/DiffTestSelectionImpl.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/DiffTestSelectionImpl.java index ff8b5fe1c..107962c45 100644 --- a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/DiffTestSelectionImpl.java +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/DiffTestSelectionImpl.java @@ -1,6 +1,8 @@ package eu.stamp_project.diff_test_selection.selector; +import eu.stamp_project.diff_test_selection.coverage.ClassCoverage; import eu.stamp_project.diff_test_selection.coverage.Coverage; +import eu.stamp_project.diff_test_selection.coverage.DiffCoverage; import gumtree.spoon.AstComparator; import gumtree.spoon.diff.Diff; import gumtree.spoon.diff.operations.Operation; @@ -23,11 +25,11 @@ public class DiffTestSelectionImpl extends DiffTestSelection { private static final Logger LOGGER = LoggerFactory.getLogger(DiffTestSelectionImpl.class); - public DiffTestSelectionImpl(String pathToFirstVersion, String pathToSecondVersion, Map>>> coverageV1, String diff, Coverage coverage) { + public DiffTestSelectionImpl(String pathToFirstVersion, String pathToSecondVersion, Coverage coverageV1, String diff, DiffCoverage coverage) { super(pathToFirstVersion, pathToSecondVersion, coverageV1, diff, coverage); } - public Coverage getCoverage() { + public DiffCoverage getCoverage() { return this.coverage; } @@ -71,18 +73,19 @@ private String getJavaFile(String currentLine) { return ""; } - private Map> matchChangedWithCoverage(Map>>> coverage, + private Map> matchChangedWithCoverage(Coverage coverage, Map> modifiedLinesPerQualifiedName) { Map> testClassNamePerTestMethodNamesThatCoverChanges = new LinkedHashMap<>(); - for (String testClassKey : coverage.keySet()) { - for (String testMethodKey : coverage.get(testClassKey).keySet()) { + for (String testClassKey : coverage.getTestClasses()) { + for (String testMethodKey : coverage.getTestMethodsForTestClassName(testClassKey)) { if (this.isParametrized(testMethodKey)) { continue; } - for (String targetClassName : coverage.get(testClassKey).get(testMethodKey).keySet()) { + for (String targetClassName : coverage.getClassesForTestClassAndMethodName(testClassKey, testMethodKey)) { if (modifiedLinesPerQualifiedName.containsKey(targetClassName)) { for (Integer line : modifiedLinesPerQualifiedName.get(targetClassName)) { - if (coverage.get(testClassKey).get(testMethodKey).get(targetClassName).contains(line)) { + final Map testMethodCoverageForClassName = coverage.getTestMethodCoverageForClassName(testClassKey, testMethodKey); + if (testMethodCoverageForClassName.get(targetClassName).contains(line)) { // testClassKey#testMethodKey hits targetClassName#line this.coverage.covered(targetClassName, line); if (!testClassNamePerTestMethodNamesThatCoverChanges.containsKey(testClassKey)) { diff --git a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/EnhancedDiffTestSelection.java b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/EnhancedDiffTestSelection.java index bf3569b96..0acc5a524 100644 --- a/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/EnhancedDiffTestSelection.java +++ b/dspot-diff-test-selection/src/main/java/eu/stamp_project/diff_test_selection/selector/EnhancedDiffTestSelection.java @@ -1,6 +1,8 @@ package eu.stamp_project.diff_test_selection.selector; +import eu.stamp_project.diff_test_selection.coverage.ClassCoverage; import eu.stamp_project.diff_test_selection.coverage.Coverage; +import eu.stamp_project.diff_test_selection.coverage.DiffCoverage; import eu.stamp_project.diff_test_selection.diff.ModifiedLinesTool; import eu.stamp_project.diff_test_selection.utils.DiffTestSelectionChecker; @@ -8,15 +10,15 @@ public class EnhancedDiffTestSelection extends DiffTestSelection { - private final Map>>> coverageV2; + private final Coverage coverageV2; public EnhancedDiffTestSelection( String pathToFirstVersion, String pathToSecondVersion, - Map>>> coverageV1, + Coverage coverageV1, String diff, - Coverage coverage, - Map>>> coverageV2 + DiffCoverage coverage, + Coverage coverageV2 ) { super(pathToFirstVersion, pathToSecondVersion, coverageV1, diff, coverage); this.coverageV2 = coverageV2; @@ -69,21 +71,21 @@ public Map> selectTests() { private void addTestsThatHitGivenChanges( final Map> selectTestsPerTestClasses, Map> modificationPerQualifiedName, - Map>>> coverage) { + Coverage coverage) { for (String modifiedClassFullQualifiedName : modificationPerQualifiedName.keySet()) { final List modifiedLines = modificationPerQualifiedName.get(modifiedClassFullQualifiedName); this.coverage.addModifiedLines(modifiedClassFullQualifiedName, modifiedLines); - for (String fullQualifiedNameOfTestClass : coverage.keySet()) { - for (String testMethodName : coverage.get(fullQualifiedNameOfTestClass).keySet()) { - final Map> coverageOfTestMethod = coverage.get(fullQualifiedNameOfTestClass).get(testMethodName); - if (coverageOfTestMethod.containsKey(modifiedClassFullQualifiedName)) { - if (modifiedLines.stream().anyMatch(line -> coverageOfTestMethod.get(modifiedClassFullQualifiedName).contains(line))) { + for (String fullQualifiedNameOfTestClass : coverage.getTestClasses()) { + for (String testMethodName : coverage.getTestMethodsForTestClassName(fullQualifiedNameOfTestClass)) { + final Map testMethodCoverageForClassName = coverage.getTestMethodCoverageForClassName(fullQualifiedNameOfTestClass, testMethodName); + if (testMethodCoverageForClassName.containsKey(modifiedClassFullQualifiedName)) { + if (modifiedLines.stream().anyMatch(line -> testMethodCoverageForClassName.get(modifiedClassFullQualifiedName).contains(line))) { if (!selectTestsPerTestClasses.containsKey(fullQualifiedNameOfTestClass)) { selectTestsPerTestClasses.put(fullQualifiedNameOfTestClass, new HashSet<>()); } modifiedLines.stream() .filter(line -> - coverageOfTestMethod.get(modifiedClassFullQualifiedName).contains(line)) + testMethodCoverageForClassName.get(modifiedClassFullQualifiedName).contains(line)) .forEach(line -> this.coverage.covered(modifiedClassFullQualifiedName, line)); selectTestsPerTestClasses.get(fullQualifiedNameOfTestClass).add(testMethodName); } diff --git a/dspot-diff-test-selection/src/test/java/eu/stamp_project/diff_test_selection/EnhancedDiffTestSelectionTestImpl.java b/dspot-diff-test-selection/src/test/java/eu/stamp_project/diff_test_selection/EnhancedDiffTestSelectionTestImpl.java index 3900a0680..d8332e236 100644 --- a/dspot-diff-test-selection/src/test/java/eu/stamp_project/diff_test_selection/EnhancedDiffTestSelectionTestImpl.java +++ b/dspot-diff-test-selection/src/test/java/eu/stamp_project/diff_test_selection/EnhancedDiffTestSelectionTestImpl.java @@ -1,6 +1,7 @@ package eu.stamp_project.diff_test_selection; import eu.stamp_project.diff_test_selection.coverage.Coverage; +import eu.stamp_project.diff_test_selection.coverage.DiffCoverage; import eu.stamp_project.diff_test_selection.diff.DiffComputer; import eu.stamp_project.diff_test_selection.selector.EnhancedDiffTestSelection; import org.junit.Test; @@ -23,24 +24,44 @@ public void testOnlyAddition() { NO TEST MODIFICATIONS */ - final Map>>> coverageV1 = new LinkedHashMap<>(); - coverageV1.put("fr.inria.stamp.only_modification.FibonacciTest", new HashMap<>()); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest").put("test", new HashMap<>()); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest").get("test") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 16, 17, 18, 19, 21, 22, 23, 25}.clone())); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest").put("hittingTest", new HashMap<>()); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest").get("hittingTest") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 13, 14}.clone())); - - final Map>>> coverageV2 = new LinkedHashMap<>(); - coverageV2.put("fr.inria.stamp.only_modification.FibonacciTest", new HashMap<>()); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest").put("test", new HashMap<>()); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest").get("test") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 15, 16, 17, 18, 20, 21, 22, 24}.clone())); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest").put("hittingTest", new HashMap<>()); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest").get("hittingTest") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 13}.clone())); - + final Coverage coverageV1 = new Coverage(); + for (int line: new Integer[]{12, 16, 17, 18, 19, 21, 22, 23, 25}) { + coverageV1.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "test", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + } + for (int line: new Integer[]{12, 13, 14}) { + coverageV1.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "hittingTest", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + } + final Coverage coverageV2 = new Coverage(); + for (int line: new Integer[]{12, 15, 16, 17, 18, 20, 21, 22, 24}) { + coverageV2.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "test", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + } + for (int line: new Integer[]{12, 13}) { + coverageV2.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "hittingTest", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + } final File p1Directory = new File("src/test/resources/only-addition-p1"); final File p1SrcDirectory = new File("src/test/resources/only-addition-p1/src/main/java"); final File p2Directory = new File("src/test/resources/only-addition-p2"); @@ -52,7 +73,7 @@ public void testOnlyAddition() { p2Directory.getAbsolutePath(), coverageV1, diff, - new Coverage(), + new DiffCoverage(), coverageV2 ); Map> selectedTests = diffTestSelection.selectTests(); @@ -71,23 +92,44 @@ public void testOnlyDeletion() { NO TEST MODIFICATIONS */ - final Map>>> coverageV1 = new LinkedHashMap<>(); - coverageV1.put("fr.inria.stamp.only_modification.FibonacciTest", new HashMap<>()); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest").put("test", new HashMap<>()); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest").get("test") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 15, 16, 17, 18, 20, 21, 22, 24}.clone())); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest").put("hittingTest", new HashMap<>()); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest").get("hittingTest") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 13}.clone())); - - final Map>>> coverageV2 = new LinkedHashMap<>(); - coverageV2.put("fr.inria.stamp.only_modification.FibonacciTest", new HashMap<>()); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest").put("test", new HashMap<>()); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest").get("test") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 16, 17, 18, 19, 21, 22, 23, 25}.clone())); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest").put("hittingTest", new HashMap<>()); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest").get("hittingTest") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 13, 14}.clone())); + final Coverage coverageV1 = new Coverage(); + for (int line: new Integer[]{12, 15, 16, 17, 18, 20, 21, 22, 24}) { + coverageV1.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "test", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + } + for (int line: new Integer[]{12, 13}) { + coverageV1.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "hittingTest", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + } + final Coverage coverageV2 = new Coverage(); + for (int line: new Integer[]{12, 16, 17, 18, 19, 21, 22, 23, 25}) { + coverageV2.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "test", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + } + for (int line: new Integer[]{12, 13, 14}) { + coverageV2.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "hittingTest", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + } final File p1Directory = new File("src/test/resources/only-deletion-p1"); final File p1SrcDirectory = new File("src/test/resources/only-deletion-p1/src/main/java"); @@ -100,7 +142,7 @@ public void testOnlyDeletion() { p2Directory.getAbsolutePath(), coverageV1, diff, - new Coverage(), + new DiffCoverage(), coverageV2 ); Map> selectedTests = diffTestSelection.selectTests(); @@ -120,27 +162,40 @@ public void testModification() { */ - final Map>>> coverageV1 = new LinkedHashMap<>(); - coverageV1.put("fr.inria.stamp.only_modification.FibonacciTest", new HashMap<>()); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest") - .put("test", new HashMap<>()); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest").get("test") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 15, 16, 17, 18, 20, 21, 22, 24}.clone())); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest") - .put("hittingTest", new HashMap<>()); - coverageV1.get("fr.inria.stamp.only_modification.FibonacciTest").get("hittingTest") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 13}.clone())); - - final Map>>> coverageV2 = new LinkedHashMap<>(); - coverageV2.put("fr.inria.stamp.only_modification.FibonacciTest", new HashMap<>()); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest") - .put("test", new HashMap<>()); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest").get("test") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 15, 16, 17, 18, 20, 21, 22, 24}.clone())); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest") - .put("hittingTest", new HashMap<>()); - coverageV2.get("fr.inria.stamp.only_modification.FibonacciTest").get("hittingTest") - .put("fr.inria.stamp.only_modification.Fibonacci", Arrays.asList(new Integer[]{12, 13}.clone())); + final Coverage coverageV1 = new Coverage(); + final Coverage coverageV2 = new Coverage(); + for (int line: new Integer[]{12, 15, 16, 17, 18, 20, 21, 22, 24}) { + coverageV1.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "test", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + coverageV2.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "test", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + } + for (int line: new Integer[]{12, 13}) { + coverageV1.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "hittingTest", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + coverageV2.addCoverage( + "fr.inria.stamp.only_modification.FibonacciTest", + "hittingTest", + "fr.inria.stamp.only_modification.Fibonacci", + line, + 1 + ); + } final File p1Directory = new File("src/test/resources/only-modification-p1"); final File p1SrcDirectory = new File("src/test/resources/only-modification-p1/src/main/java"); @@ -153,8 +208,8 @@ public void testModification() { p2Directory.getAbsolutePath(), coverageV1, diff, - new Coverage(), - Collections.emptyMap() + new DiffCoverage(), + new Coverage() ); Map> selectedTests = diffTestSelection.selectTests(); assertTrue(selectedTests.containsKey("fr.inria.stamp.only_modification.FibonacciTest")); @@ -163,9 +218,9 @@ public void testModification() { diffTestSelection = new EnhancedDiffTestSelection( p1Directory.getAbsolutePath(), p2Directory.getAbsolutePath(), - Collections.emptyMap(), - diff, new Coverage(), + diff, + new DiffCoverage(), coverageV2 ); selectedTests = diffTestSelection.selectTests(); @@ -177,7 +232,7 @@ public void testModification() { p2Directory.getAbsolutePath(), coverageV1, diff, - new Coverage(), + new DiffCoverage(), coverageV2 ); selectedTests = diffTestSelection.selectTests(); diff --git a/dspot-diff-test-selection/src/test/java/eu/stamp_project/diff_test_selection/clover/CloverExectorTest.java b/dspot-diff-test-selection/src/test/java/eu/stamp_project/diff_test_selection/clover/CloverExectorTest.java index 1e4919784..e3933fe99 100644 --- a/dspot-diff-test-selection/src/test/java/eu/stamp_project/diff_test_selection/clover/CloverExectorTest.java +++ b/dspot-diff-test-selection/src/test/java/eu/stamp_project/diff_test_selection/clover/CloverExectorTest.java @@ -3,6 +3,8 @@ import org.junit.Test; import java.io.File; +import java.util.List; +import java.util.Map; import static org.junit.Assert.assertTrue;