Skip to content

Commit

Permalink
Less memory exaustive coverage transformer. (#110)
Browse files Browse the repository at this point in the history
* Reduce memory consumption and fix timeout exception.

Signed-off-by: André Silva <andre15andre@hotmail.com>

* Add tests

Signed-off-by: André Silva <andre15andre@hotmail.com>

* Fix compressed coverage tests

Signed-off-by: André Silva <andre15andre@hotmail.com>
  • Loading branch information
andre15silva committed Jul 19, 2021
1 parent 0e602d5 commit 73b7dd0
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 5 deletions.
10 changes: 6 additions & 4 deletions src/main/java/eu/stamp_project/testrunner/EntryPoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -651,13 +651,15 @@ private static void runGivenCommandLine(String commandLine) throws TimeoutExcept
inheritIO(process.getErrorStream(), EntryPoint.outPrintStream);
}

long startTime = System.currentTimeMillis();
boolean finished = process.waitFor(timeoutInMs, TimeUnit.MILLISECONDS);
long endTime = System.currentTimeMillis();
if (!finished) {
throw new RuntimeException("Forked process did not finished correctly");
throw new RuntimeException("Forked process did not finish correctly. " +
"Timeout set was " + timeoutInMs + " ms, " +
"process took " + (endTime - startTime) + " ms before ending.");
}
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
} finally {
if (process != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package eu.stamp_project.testrunner.listener.impl;

import eu.stamp_project.testrunner.listener.CoverageTransformer;
import org.jacoco.core.analysis.Analyzer;
import org.jacoco.core.analysis.CoverageBuilder;
import org.jacoco.core.analysis.IClassCoverage;
import org.jacoco.core.analysis.IMethodCoverage;
import org.jacoco.core.data.ExecutionDataStore;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Returns a {@link CoverageDetailed} but containing only information regarding covered classes.
* Uses less memory compared to {@link CoverageCollectorDetailed} since the information about non-covered classes is
* ignored.
*/
public class CoverageCollectorDetailedCompressed implements CoverageTransformer {

@Override
public CoverageDetailed transformJacocoObject(ExecutionDataStore executionData, List<String> classesDirectory) {

CoverageInformation covered = new CoverageInformation();

final CoverageBuilder coverageBuilder = new CoverageBuilder();
final Analyzer analyzer = new Analyzer(executionData, coverageBuilder);
try {
for (String directory : classesDirectory) {
analyzer.analyzeAll(new File(directory));
}
} catch (IOException e) {
throw new RuntimeException(e);
}

for (IClassCoverage classCoverage : coverageBuilder.getClasses()) {

if (classCoverage.getInstructionCounter().getCoveredCount() > 0) {

Map<Integer, Integer> covClass = new HashMap<>();

for (IMethodCoverage methodCoverage : classCoverage.getMethods()) {

if (!"<clinit>".equals(methodCoverage.getName())) {

for (int i = methodCoverage.getFirstLine(); i <= methodCoverage.getLastLine() + 1; i++) {
int coveredI = methodCoverage.getLine(i).getInstructionCounter().getCoveredCount();
covClass.put(i, coveredI);
}

}
}
CoverageFromClass l = new CoverageFromClass(classCoverage.getName(), classCoverage.getPackageName(),
classCoverage.getFirstLine(), classCoverage.getLastLine(), covClass);

covered.put(classCoverage.getName(), l);
}

}
return new CoverageDetailed(covered);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import eu.stamp_project.testrunner.listener.CoverageTransformer;
import eu.stamp_project.testrunner.listener.impl.CoverageCollectorDetailed;
import eu.stamp_project.testrunner.listener.impl.CoverageCollectorDetailedCompressed;
import eu.stamp_project.testrunner.listener.impl.CoverageCollectorMethodDetailed;
import eu.stamp_project.testrunner.listener.impl.CoverageCollectorSummarization;
import eu.stamp_project.testrunner.utils.ConstantsHelper;
Expand Down Expand Up @@ -135,7 +136,8 @@ private static void usage() {
public enum CoverageTransformerDetail {
SUMMARIZED,
DETAIL,
METHOD_DETAIL
METHOD_DETAIL,
DETAIL_COMPRESSED
}
/**
* This value represents at which level of detail coverage information should be provided
Expand Down Expand Up @@ -184,6 +186,8 @@ public CoverageTransformer getCoverageTransformer() {
return new CoverageCollectorDetailed();
case METHOD_DETAIL:
return new CoverageCollectorMethodDetailed();
case DETAIL_COMPRESSED:
return new CoverageCollectorDetailedCompressed();
case SUMMARIZED:
default:
return new CoverageCollectorSummarization();
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -562,4 +562,79 @@ Test the runCoveredTestResultPerTestMethods() of EntryPoint.
assertEquals(5, coverageDetailed.getDetailedCoverage().size());
}

// Tests when running same named test methods from different classes
@Test
public void testRunCoveredTestResultPerTestMethodsSameNamedMethodsDetailedCompressedCoverage() throws Exception {
EntryPoint.coverageDetail = ParserOptions.CoverageTransformerDetail.DETAIL_COMPRESSED;

/*
Test the runCoveredTestResultPerTestMethods() of EntryPoint.
It should return the CoveredTestResultPerTestMethod with the instruction coverage computed by Jacoco.
*/
final String classpath = JUNIT_CP + ConstantsHelper.PATH_SEPARATOR + JUNIT5_CP;

final CoveredTestResultPerTestMethod coveredTestResultPerTestMethod = EntryPoint.runCoveredTestResultPerTestMethods(
classpath + ConstantsHelper.PATH_SEPARATOR + SOURCE_PROJECT_CLASSES + ConstantsHelper.PATH_SEPARATOR + TEST_PROJECT_CLASSES,
SOURCE_PROJECT_CLASSES + ConstantsHelper.PATH_SEPARATOR + TEST_PROJECT_CLASSES,
new String[]{"junit5.TestSuiteExample", "junit5.TestSuiteExample2"},
new String[]{"junit5.TestSuiteExample#test3", "junit5.TestSuiteExample2#test3"}
);

// Assert test results
System.out.println(coveredTestResultPerTestMethod);
assertEquals(2, coveredTestResultPerTestMethod.getRunningTests().size());
assertEquals(2, coveredTestResultPerTestMethod.getPassingTests().size());
assertEquals(0, coveredTestResultPerTestMethod.getFailingTests().size());
assertEquals(0, coveredTestResultPerTestMethod.getIgnoredTests().size());

// Assert detailed coverage
assertEquals(2, coveredTestResultPerTestMethod.getCoverageResultsMap().size());

assertTrue(coveredTestResultPerTestMethod.getCoverageOf("junit5.TestSuiteExample#test3") instanceof CoverageDetailed);
CoverageDetailed coverageDetailed = (CoverageDetailed) coveredTestResultPerTestMethod.getCoverageOf("junit5.TestSuiteExample#test3");
assertNotNull(coverageDetailed.getDetailedCoverage());
assertEquals(1, coverageDetailed.getDetailedCoverage().size());

assertTrue(coveredTestResultPerTestMethod.getCoverageOf("junit5.TestSuiteExample2#test3") instanceof CoverageDetailed);
coverageDetailed = (CoverageDetailed) coveredTestResultPerTestMethod.getCoverageOf("junit5.TestSuiteExample2#test3");
assertNotNull(coverageDetailed.getDetailedCoverage());
assertEquals(1, coverageDetailed.getDetailedCoverage().size());
}

@Test
public void testRunCoveredTestResultPerTestMethodsDetailedCompressedCoverage() throws Exception {
EntryPoint.coverageDetail = ParserOptions.CoverageTransformerDetail.DETAIL_COMPRESSED;

/*
Test the runCoveredTestResultPerTestMethods() of EntryPoint.
It should return the CoveredTestResultPerTestMethod with the instruction coverage computed by Jacoco.
*/
final String classpath = JUNIT_CP + ConstantsHelper.PATH_SEPARATOR + JUNIT5_CP;

final CoveredTestResultPerTestMethod coveredTestResultPerTestMethod = EntryPoint.runCoveredTestResultPerTestMethods(
classpath + ConstantsHelper.PATH_SEPARATOR + SOURCE_PROJECT_CLASSES + ConstantsHelper.PATH_SEPARATOR + TEST_PROJECT_CLASSES,
SOURCE_PROJECT_CLASSES + ConstantsHelper.PATH_SEPARATOR + TEST_PROJECT_CLASSES,
"junit5.TestSuiteExample",
new String[]{"test8", "test3"}
);

// Assert test results
assertEquals(2, coveredTestResultPerTestMethod.getRunningTests().size());
assertEquals(2, coveredTestResultPerTestMethod.getPassingTests().size());
assertEquals(0, coveredTestResultPerTestMethod.getFailingTests().size());
assertEquals(0, coveredTestResultPerTestMethod.getIgnoredTests().size());

// Assert detailed coverage
assertEquals(2, coveredTestResultPerTestMethod.getCoverageResultsMap().size());

assertTrue(coveredTestResultPerTestMethod.getCoverageOf("junit5.TestSuiteExample#test3") instanceof CoverageDetailed);
CoverageDetailed coverageDetailed = (CoverageDetailed) coveredTestResultPerTestMethod.getCoverageOf("junit5.TestSuiteExample#test3");
assertNotNull(coverageDetailed.getDetailedCoverage());
assertEquals(1, coverageDetailed.getDetailedCoverage().size());

assertTrue(coveredTestResultPerTestMethod.getCoverageOf("junit5.TestSuiteExample#test8") instanceof CoverageDetailed);
coverageDetailed = (CoverageDetailed) coveredTestResultPerTestMethod.getCoverageOf("junit5.TestSuiteExample#test8");
assertNotNull(coverageDetailed.getDetailedCoverage());
assertEquals(1, coverageDetailed.getDetailedCoverage().size());
}
}
75 changes: 75 additions & 0 deletions src/test/java/eu/stamp_project/testrunner/EntryPointTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -672,4 +672,79 @@ Test the runCoveredTestResultPerTestMethods() of EntryPoint.
assertEquals(5, coverageDetailed.getDetailedCoverage().size());
}

// Tests when running same named test methods from different classes
@Test
public void testRunCoveredTestResultPerTestMethodsSameNamedMethodsDetailedCompressedCoverage() throws Exception {
EntryPoint.coverageDetail = ParserOptions.CoverageTransformerDetail.DETAIL_COMPRESSED;

/*
Test the runCoveredTestResultPerTestMethods() of EntryPoint.
It should return the CoveredTestResult with the instruction coverage computed by Jacoco.
*/
final String classpath = JUNIT_CP + ConstantsHelper.PATH_SEPARATOR + JUNIT5_CP;

final CoveredTestResultPerTestMethod coveredTestResultPerTestMethod = EntryPoint.runCoveredTestResultPerTestMethods(
classpath + ConstantsHelper.PATH_SEPARATOR + SOURCE_PROJECT_CLASSES + ConstantsHelper.PATH_SEPARATOR + TEST_PROJECT_CLASSES,
SOURCE_PROJECT_CLASSES + ConstantsHelper.PATH_SEPARATOR + TEST_PROJECT_CLASSES,
new String[]{"example.TestSuiteExample", "example.TestSuiteExample2"},
new String[]{"example.TestSuiteExample#test3", "example.TestSuiteExample2#test3"}
);

// Assert test results
assertEquals(2, coveredTestResultPerTestMethod.getRunningTests().size());
assertEquals(2, coveredTestResultPerTestMethod.getPassingTests().size());
assertEquals(0, coveredTestResultPerTestMethod.getFailingTests().size());
assertEquals(0, coveredTestResultPerTestMethod.getIgnoredTests().size());

// Assert detailed coverage
assertEquals(2, coveredTestResultPerTestMethod.getCoverageResultsMap().size());

assertTrue(coveredTestResultPerTestMethod.getCoverageOf("example.TestSuiteExample#test3") instanceof CoverageDetailed);
CoverageDetailed coverageDetailed = (CoverageDetailed) coveredTestResultPerTestMethod.getCoverageOf("example.TestSuiteExample#test3");
assertNotNull(coverageDetailed.getDetailedCoverage());
assertEquals(1, coverageDetailed.getDetailedCoverage().size());

assertTrue(coveredTestResultPerTestMethod.getCoverageOf("example.TestSuiteExample2#test3") instanceof CoverageDetailed);
coverageDetailed = (CoverageDetailed) coveredTestResultPerTestMethod.getCoverageOf("example.TestSuiteExample2#test3");
assertNotNull(coverageDetailed.getDetailedCoverage());
assertEquals(1, coverageDetailed.getDetailedCoverage().size());
}

@Test
public void testRunCoveredTestResultPerTestMethodsDetailedCompressedCoverage() throws Exception {
EntryPoint.coverageDetail = ParserOptions.CoverageTransformerDetail.DETAIL_COMPRESSED;

/*
Test the runCoveredTestResultPerTestMethods() of EntryPoint.
It should return the CoveredTestResultPerTestMethod with the instruction coverage computed by Jacoco.
*/
final String classpath = JUNIT_CP + ConstantsHelper.PATH_SEPARATOR + JUNIT5_CP;

final CoveredTestResultPerTestMethod coveredTestResultPerTestMethod = EntryPoint.runCoveredTestResultPerTestMethods(
classpath + ConstantsHelper.PATH_SEPARATOR + SOURCE_PROJECT_CLASSES + ConstantsHelper.PATH_SEPARATOR + TEST_PROJECT_CLASSES,
SOURCE_PROJECT_CLASSES + ConstantsHelper.PATH_SEPARATOR + TEST_PROJECT_CLASSES,
"example.TestSuiteExample",
new String[]{"test8", "test3"}
);

// Assert test results
assertEquals(2, coveredTestResultPerTestMethod.getRunningTests().size());
assertEquals(2, coveredTestResultPerTestMethod.getPassingTests().size());
assertEquals(0, coveredTestResultPerTestMethod.getFailingTests().size());
assertEquals(0, coveredTestResultPerTestMethod.getIgnoredTests().size());

// Assert detailed coverage
assertEquals(2, coveredTestResultPerTestMethod.getCoverageResultsMap().size());

assertTrue(coveredTestResultPerTestMethod.getCoverageOf("example.TestSuiteExample#test3") instanceof CoverageDetailed);
CoverageDetailed coverageDetailed = (CoverageDetailed) coveredTestResultPerTestMethod.getCoverageOf("example.TestSuiteExample#test3");
assertNotNull(coverageDetailed.getDetailedCoverage());
assertEquals(1, coverageDetailed.getDetailedCoverage().size());

assertTrue(coveredTestResultPerTestMethod.getCoverageOf("example.TestSuiteExample#test8") instanceof CoverageDetailed);
coverageDetailed = (CoverageDetailed) coveredTestResultPerTestMethod.getCoverageOf("example.TestSuiteExample#test8");
assertNotNull(coverageDetailed.getDetailedCoverage());
assertEquals(1, coverageDetailed.getDetailedCoverage().size());
}

}

0 comments on commit 73b7dd0

Please sign in to comment.