diff --git a/dependency/src/main/java/de/dagere/peass/execution/gradle/GradleTestExecutor.java b/dependency/src/main/java/de/dagere/peass/execution/gradle/GradleTestExecutor.java index 430916937..f762c3c17 100644 --- a/dependency/src/main/java/de/dagere/peass/execution/gradle/GradleTestExecutor.java +++ b/dependency/src/main/java/de/dagere/peass/execution/gradle/GradleTestExecutor.java @@ -146,6 +146,22 @@ public void executeTest(final TestMethodCall test, final File logFolder, final l cleanAboveSize(logFolder, "txt"); } + @Override + public void executeTest(String javaAgent, final TestMethodCall test, final File logFolder, final long timeout) { + throw new RuntimeException("Functionality regarding running tests with javaagent on Gradle is not currently supported."); + } + + /** + * Runs the given test and saves the results to the result folder. + * + * @param specialResultFolder Folder for saving the results + * @param testname Name of the test that should be run + */ + @Override + protected void runTest(String javaAgent, final File moduleFolder, final File methodLogFile, TestMethodCall test, final String testname, final long timeout) { + throw new RuntimeException("Functionality regarding running tests with javaagent on Gradle is not currently supported."); + } + /** * Runs the given test and saves the results to the result folder. * diff --git a/dependency/src/main/java/de/dagere/peass/execution/maven/pom/MavenTestExecutor.java b/dependency/src/main/java/de/dagere/peass/execution/maven/pom/MavenTestExecutor.java index 5c5383b6a..ae8f5d328 100644 --- a/dependency/src/main/java/de/dagere/peass/execution/maven/pom/MavenTestExecutor.java +++ b/dependency/src/main/java/de/dagere/peass/execution/maven/pom/MavenTestExecutor.java @@ -131,6 +131,14 @@ public void executeTest(final TestMethodCall test, final File logFolder, final l cleanAboveSize(logFolder, "txt"); } + @Override + public void executeTest(final String javaAgent, final TestMethodCall test, final File logFolder, final long timeout) { + final File moduleFolder = new File(folders.getProjectFolder(), test.getModule()); + runMethod(logFolder, test, moduleFolder, timeout, javaAgent); + + cleanAboveSize(logFolder, "txt"); + } + /** * Runs the given test and saves the results to the result folder. * @@ -138,15 +146,31 @@ public void executeTest(final TestMethodCall test, final File logFolder, final l * @param testname Name of the test that should be run */ @Override - protected void runTest(final File module, final File logFile, TestMethodCall test, final String testname, final long timeout) { + protected void runTest(final String javaAgent, final File module, final File logFile, TestMethodCall test, final String testname, final long timeout) { try { - final Process process = buildMavenProcess(logFile, test, "-Dtest=" + testname); + final Process process = buildMavenProcess(logFile, test, "-Dtest=" + testname, javaAgent); execute(testname, timeout, process); } catch (final InterruptedException | IOException e) { e.printStackTrace(); } } + /** + * Runs the given test and saves the results to the result folder. + * + * @param specialResultFolder Folder for saving the results + * @param testname Name of the test that should be run + */ + @Override + protected void runTest(final File module, final File logFile, TestMethodCall test, final String testname, final long timeout) { + try { + final Process process = buildMavenProcess(logFile, test, "-Dtest=" + testname); + execute(testname, timeout, process); + } catch (final InterruptedException | IOException e) { + e.printStackTrace(); + } + } + @Override public boolean doesBuildfileExist() { File pomFile = new File(folders.getProjectFolder(), "pom.xml"); diff --git a/dependency/src/main/java/de/dagere/peass/execution/utils/KoPeMeExecutor.java b/dependency/src/main/java/de/dagere/peass/execution/utils/KoPeMeExecutor.java index 82b8d91bb..0f3223c67 100644 --- a/dependency/src/main/java/de/dagere/peass/execution/utils/KoPeMeExecutor.java +++ b/dependency/src/main/java/de/dagere/peass/execution/utils/KoPeMeExecutor.java @@ -45,8 +45,14 @@ protected String getTestGoal() { } protected abstract void runTest(File moduleFolder, final File logFile, TestMethodCall test, final String testname, final long timeout); + + protected abstract void runTest(String javaAgent, File moduleFolder, final File logFile, TestMethodCall test, final String testname, final long timeout); protected void runMethod(final File logFolder, final TestMethodCall test, final File moduleFolder, final long timeout) { + runMethod(logFolder, test, moduleFolder, timeout, null); + } + + protected void runMethod(final File logFolder, final TestMethodCall test, final File moduleFolder, final long timeout, String javaAgent) { try (final JUnitTestShortener shortener = new JUnitTestShortener(testTransformer, moduleFolder, test.toEntity(), test.getMethod())) { if (testTransformer.getConfig().isDirectlyMeasureKieker()) { File fileToInstrument = shortener.getCalleeClazzFile(); @@ -68,7 +74,14 @@ protected void runMethod(final File logFolder, final TestMethodCall test, final clean(cleanFile); final File methodLogFile = getMethodLogFile(logFolder, test); - runTest(moduleFolder, methodLogFile, test, test.getClazz(), timeout); + + if(javaAgent != null) { + runTest(javaAgent, moduleFolder, methodLogFile, test, test.getClazz(), timeout == 0 ? 300 : timeout); + } else { + runTest(moduleFolder, methodLogFile, test, test.getClazz(), timeout == 0 ? 300 : timeout); + } + +// runTest(moduleFolder, methodLogFile, test, test.getClazz(), timeout); } catch (Exception e1) { e1.printStackTrace(); } diff --git a/dependency/src/main/java/de/dagere/peass/execution/utils/TestExecutor.java b/dependency/src/main/java/de/dagere/peass/execution/utils/TestExecutor.java index c9a52ad5f..40eb5695a 100644 --- a/dependency/src/main/java/de/dagere/peass/execution/utils/TestExecutor.java +++ b/dependency/src/main/java/de/dagere/peass/execution/utils/TestExecutor.java @@ -64,6 +64,8 @@ public int getJDKVersion() { public abstract void executeTest(final TestMethodCall test, final File logFolder, long timeout); + public abstract void executeTest(final String javaAgent, final TestMethodCall test, final File logFolder, long timeout); + /** * Deletes files which are bigger than sizeInMb Mb, since they pollute the disc space and will not be analyzable * @@ -125,7 +127,7 @@ protected void prepareKiekerSource() { protected void execute(final String testname, final long timeoutInSeconds, final Process process) { if (timeoutInSeconds == -1) { - LOG.info("Executing without timeout!"); + LOG.warn("Executing without timeout!"); try { process.waitFor(); } catch (InterruptedException e) { diff --git a/dependency/src/main/java/de/dagere/peass/folders/PeassFolders.java b/dependency/src/main/java/de/dagere/peass/folders/PeassFolders.java index 5b21b71e9..3dbe4a136 100644 --- a/dependency/src/main/java/de/dagere/peass/folders/PeassFolders.java +++ b/dependency/src/main/java/de/dagere/peass/folders/PeassFolders.java @@ -201,7 +201,7 @@ public List findTempClazzFolder(final TestCase testcase) { private List findTempClazzFolder(final File baseFolder, final FileFilter folderFilter) { final List files = new LinkedList<>(); - System.out.println("Searching in " + baseFolder + " " + baseFolder.exists()); + LOG.trace("Searching in {} {}", baseFolder, baseFolder.exists()); for (final File subfolder : baseFolder.listFiles()) { if (subfolder.isDirectory()) { if (folderFilter.accept(subfolder)) { diff --git a/dependency/src/test/java/de/dagere/peass/dependency/DummyExecutor.java b/dependency/src/test/java/de/dagere/peass/dependency/DummyExecutor.java index 79842cea3..8ba8473dc 100644 --- a/dependency/src/test/java/de/dagere/peass/dependency/DummyExecutor.java +++ b/dependency/src/test/java/de/dagere/peass/dependency/DummyExecutor.java @@ -52,4 +52,10 @@ public boolean doesBuildfileExist() { return true; } + @Override + public void executeTest(String javaAgent, TestMethodCall test, File logFolder, long timeout) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'executeTest'"); + } + } diff --git a/dependency/src/test/java/de/dagere/peass/dependency/TestExecutorCreatorSubclasses.java b/dependency/src/test/java/de/dagere/peass/dependency/TestExecutorCreatorSubclasses.java index 552ae69dd..6cbf2e99a 100644 --- a/dependency/src/test/java/de/dagere/peass/dependency/TestExecutorCreatorSubclasses.java +++ b/dependency/src/test/java/de/dagere/peass/dependency/TestExecutorCreatorSubclasses.java @@ -74,6 +74,10 @@ public ProjectModules getModules() { @Override protected void clean(final File logFile) throws IOException, InterruptedException { } + + @Override + public void executeTest(String javaAgent, TestMethodCall test, File logFolder, long timeout) { + } } diff --git a/dependency/src/test/java/de/dagere/peass/dependencytests/DependencyDetectorIncludesTest.java b/dependency/src/test/java/de/dagere/peass/dependencytests/DependencyDetectorIncludesTest.java index f4cecb219..afea620fb 100644 --- a/dependency/src/test/java/de/dagere/peass/dependencytests/DependencyDetectorIncludesTest.java +++ b/dependency/src/test/java/de/dagere/peass/dependencytests/DependencyDetectorIncludesTest.java @@ -8,6 +8,7 @@ import org.apache.commons.io.FileUtils; import org.junit.Assert; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import com.github.javaparser.ParseException; diff --git a/measurement/pom.xml b/measurement/pom.xml index b67f3606c..9361cb870 100644 --- a/measurement/pom.xml +++ b/measurement/pom.xml @@ -61,6 +61,12 @@ + + io.github.terahidro2003 + sjsw + 0.1.4-SNAPSHOT + + net.kieker-monitoring diff --git a/measurement/src/main/java/de/dagere/peass/SearchCauseStarter.java b/measurement/src/main/java/de/dagere/peass/SearchCauseStarter.java index c43e10638..14357e09d 100644 --- a/measurement/src/main/java/de/dagere/peass/SearchCauseStarter.java +++ b/measurement/src/main/java/de/dagere/peass/SearchCauseStarter.java @@ -189,7 +189,9 @@ public TreeAnalyzer getAnalyzer(final BothTreeReader reader, final CauseSearcher tester = new CauseSearcherComplete(reader, causeSearcherConfig, measurer, measurementConfiguration, alternateFolders, creator, env); break; case SAMPLING: - tester = new SamplingCauseSearcher(causeSearcherConfig.getTestCase(), measurementConfiguration, alternateFolders, env); + measurementConfiguration.setUseKieker(false); + tester = new SamplingCauseSearcher(causeSearcherConfig.getTestCase(), measurementConfiguration, alternateFolders, env, causeSearcherConfig, reader); + break; default: throw new RuntimeException("Strategy " + causeSearcherConfig.getRcaStrategy() + " not expected"); } diff --git a/measurement/src/main/java/de/dagere/peass/measurement/dependencyprocessors/SamplingRunner.java b/measurement/src/main/java/de/dagere/peass/measurement/dependencyprocessors/SamplingRunner.java index 559c1277f..93312732c 100644 --- a/measurement/src/main/java/de/dagere/peass/measurement/dependencyprocessors/SamplingRunner.java +++ b/measurement/src/main/java/de/dagere/peass/measurement/dependencyprocessors/SamplingRunner.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.IOException; +import java.time.Duration; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; @@ -13,6 +14,12 @@ import de.dagere.peass.measurement.organize.ResultOrganizer; import de.dagere.peass.measurement.rca.searcher.ICauseSearcher; import de.dagere.peass.testtransformation.TestTransformer; +import io.github.terahidro2003.config.Config; +import io.github.terahidro2003.samplers.SamplerExecutorPipeline; +import io.github.terahidro2003.samplers.asyncprofiler.AsyncProfilerExecutor; +import io.github.terahidro2003.samplers.asyncprofiler.MeasurementInformation; + +import static io.github.terahidro2003.samplers.asyncprofiler.AsyncProfilerExecutor.log; public class SamplingRunner extends AbstractMeasurementProcessRunner { private static final Logger LOG = LogManager.getLogger(OnceRunner.class); @@ -23,13 +30,17 @@ public class SamplingRunner extends AbstractMeasurementProcessRunner { protected final ResultOrganizer currentOrganizer; private final ICauseSearcher resultHandler; - public SamplingRunner(final PeassFolders folders, final TestExecutor testExecutor, final ResultOrganizer currentOrganizer, final ICauseSearcher resultHandler) { + private final Config configuration; + + public SamplingRunner(final PeassFolders folders, final TestExecutor testExecutor, final ResultOrganizer currentOrganizer, final ICauseSearcher resultHandler, + final Config config) { super(folders); this.testTransformer = testExecutor.getTestTransformer(); this.testExecutor = testExecutor; this.currentOrganizer = currentOrganizer; this.resultHandler = resultHandler; - + this.configuration = config; + try { FileUtils.cleanDirectory(folders.getTempDir()); } catch (IOException e) { @@ -39,20 +50,32 @@ public SamplingRunner(final PeassFolders folders, final TestExecutor testExecuto @Override public void runOnce(TestMethodCall testcase, String commit, int vmid, File logFolder) { + LOG.debug("Preparing testcase {} to run with SAMPLING enabled", testcase); initCommit(commit); - final File vmidFolder = initVMFolder(commit, vmid, logFolder); - + testExecutor.loadClasses(); testExecutor.prepareKoPeMeExecution(new File(logFolder, "clean.txt")); - - //TODO implement sampling measurement - if (true) { - throw new RuntimeException("Not implemented yet"); - } - + + final File vmidFolder = initVMFolder(commit, vmid, logFolder); + + // What is the reason behind this arithmetic of timeout? + final long outerTimeout = 10 + (int) (this.testTransformer.getConfig().getTimeoutInSeconds() * 1.2); + LOG.info("Executing testcase {}", testcase); + String mavenJavaAgent = retrieveProfilerJavaAgentAsMavenArgument(configuration, outerTimeout, vmid, logFolder, commit); + testExecutor.executeTest(mavenJavaAgent, testcase, vmidFolder, outerTimeout); + LOG.info("Organizing result paths"); currentOrganizer.saveResultFiles(commit, vmid); cleanup(); } + + private String retrieveProfilerJavaAgentAsMavenArgument(Config config, long maxSamplingDuration, int vmid, File logFolder, String commit) { + Duration duration = Duration.ofSeconds(maxSamplingDuration * 60); + SamplerExecutorPipeline pipeline = new AsyncProfilerExecutor(); + MeasurementInformation agent = pipeline.javaAgent(this.configuration, vmid, commit, duration); + String javaAgentAsMavenArgument = "-DargLine=" + agent.javaAgentPath(); + LOG.info("Async-profiler java-agent configured: {}", javaAgentAsMavenArgument); + return javaAgentAsMavenArgument; + } } diff --git a/measurement/src/main/java/de/dagere/peass/measurement/rca/data/BasicNode.java b/measurement/src/main/java/de/dagere/peass/measurement/rca/data/BasicNode.java index b851f260e..c21a052fc 100644 --- a/measurement/src/main/java/de/dagere/peass/measurement/rca/data/BasicNode.java +++ b/measurement/src/main/java/de/dagere/peass/measurement/rca/data/BasicNode.java @@ -73,6 +73,8 @@ public String getCall() { return call; } + public void setCall(String call) { this.call = call; } + public String getKiekerPattern() { return kiekerPattern; } diff --git a/measurement/src/main/java/de/dagere/peass/measurement/rca/data/CallTreeNode.java b/measurement/src/main/java/de/dagere/peass/measurement/rca/data/CallTreeNode.java index 8ba75e064..a8a667325 100644 --- a/measurement/src/main/java/de/dagere/peass/measurement/rca/data/CallTreeNode.java +++ b/measurement/src/main/java/de/dagere/peass/measurement/rca/data/CallTreeNode.java @@ -51,6 +51,14 @@ public class CallTreeNode extends BasicNode { protected final List children = new ArrayList<>(); protected final Map data = new HashMap<>(); + public List getKeys() { + return data.keySet().stream().collect(Collectors.toList()); + } + + public Map getData() { + return data; + } + @JsonIgnore protected MeasurementConfig config; @@ -184,14 +192,23 @@ public String toString() { return kiekerPattern.toString(); } + private String extractMethodName(String call) { + int lastParenthesisIndex = call.contains("(") ? call.lastIndexOf("(") : call.length() -1; + String methodName = call.substring(0, lastParenthesisIndex); + + String[] parts = methodName.split(" "); + return parts.length > 1 ? parts[parts.length - 1] : call; + } + public MethodCall toEntity() { if (call.equals(CauseSearchData.ADDED)) { - String otherKiekerPattern = getOtherKiekerPattern(); - String otherCall = otherKiekerPattern.substring(otherKiekerPattern.lastIndexOf(' '), otherKiekerPattern.indexOf('(')); +// String otherKiekerPattern = getOtherKiekerPattern(); + String otherCall = getOtherCommitNode().getCall(); return MethodCall.createMethodCallFromString(otherCall); } else { final int index = call.lastIndexOf(MethodCall.METHOD_SEPARATOR); String method = call.substring(index + 1); + System.out.println(call + " " + method); final MethodCall entity; if (method.contains("(")) { entity = new MethodCall(call.substring(0, index), module, method.substring(0, method.indexOf('('))); @@ -287,7 +304,7 @@ public void setOtherCommitNode(final CallTreeNode otherVersionNode) { @JsonIgnore public String getMethod() { - final String method = call.substring(call.lastIndexOf('#')); + final String method = call.contains("#") ? call.substring(call.lastIndexOf('#')) : call; return method; } diff --git a/measurement/src/main/java/de/dagere/peass/measurement/rca/data/CauseSearchData.java b/measurement/src/main/java/de/dagere/peass/measurement/rca/data/CauseSearchData.java index 26cd8af4e..06c8a9a2f 100644 --- a/measurement/src/main/java/de/dagere/peass/measurement/rca/data/CauseSearchData.java +++ b/measurement/src/main/java/de/dagere/peass/measurement/rca/data/CauseSearchData.java @@ -98,7 +98,12 @@ private void setStatistic(final CallTreeNode rawDataNode, final MeasuredNode ser serializeNode.setStatistic(rawDataNode.getTestcaseStatistic()); } else { LOG.debug(rawDataNode.getCall() + " " + rawDataNode.getOtherKiekerPattern()); - serializeNode.setStatistic(rawDataNode.getPartialTestcaseStatistic()); + if (rawDataNode.getCall().equals(ADDED) && + !rawDataNode.getOtherKiekerPattern().equals(ADDED)) { + serializeNode.setStatistic(rawDataNode.getOtherCommitNode().getPartialTestcaseStatistic()); + } else { + serializeNode.setStatistic(rawDataNode.getPartialTestcaseStatistic()); + } } } diff --git a/measurement/src/main/java/de/dagere/peass/measurement/rca/searcher/SamplingCauseSearcher.java b/measurement/src/main/java/de/dagere/peass/measurement/rca/searcher/SamplingCauseSearcher.java index bf5e24b7e..3851a295a 100644 --- a/measurement/src/main/java/de/dagere/peass/measurement/rca/searcher/SamplingCauseSearcher.java +++ b/measurement/src/main/java/de/dagere/peass/measurement/rca/searcher/SamplingCauseSearcher.java @@ -1,10 +1,25 @@ package de.dagere.peass.measurement.rca.searcher; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; -import java.util.Set; +import java.nio.file.Path; +import java.util.*; +import de.dagere.peass.dependencyprocessors.CommitComparatorInstance; +import de.dagere.peass.folders.CauseSearchFolders; +import de.dagere.peass.measurement.rca.CausePersistenceManager; +import de.dagere.peass.measurement.rca.CauseSearcherConfig; +import de.dagere.peass.measurement.rca.CauseTester; +import de.dagere.peass.measurement.rca.RCAMeasurementAdder; +import de.dagere.peass.measurement.rca.analyzer.CompleteTreeAnalyzer; +import de.dagere.peass.measurement.rca.analyzer.TreeAnalyzer; +import de.dagere.peass.measurement.rca.data.CallTreeNode; +import de.dagere.peass.measurement.rca.kieker.BothTreeReader; +import de.dagere.peass.measurement.rca.treeanalysis.AllDifferingDeterminer; +import de.dagere.peass.measurement.utils.sjsw.SjswCctConverter; +import de.dagere.peass.vcs.GitUtils; +import io.github.terahidro2003.result.tree.StackTraceTreeBuilder; +import io.github.terahidro2003.result.tree.StackTraceTreeNode; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -18,13 +33,15 @@ import de.dagere.peass.execution.utils.EnvironmentVariables; import de.dagere.peass.execution.utils.TestExecutor; import de.dagere.peass.folders.PeassFolders; -import de.dagere.peass.measurement.dependencyprocessors.DependencyTester; -import de.dagere.peass.measurement.dependencyprocessors.OnceRunner; import de.dagere.peass.measurement.dependencyprocessors.SamplingRunner; import de.dagere.peass.measurement.dependencyprocessors.helper.ProgressWriter; import de.dagere.peass.measurement.organize.FolderDeterminer; import de.dagere.peass.measurement.organize.ResultOrganizer; import de.dagere.peass.testtransformation.TestTransformer; +import de.dagere.peass.utils.Constants; +import io.github.terahidro2003.config.Config; +import io.github.terahidro2003.result.SamplerResultsProcessor; +import io.github.terahidro2003.samplers.asyncprofiler.MeasurementIdentifier; public class SamplingCauseSearcher implements ICauseSearcher { @@ -32,17 +49,25 @@ public class SamplingCauseSearcher implements ICauseSearcher { private final TestMethodCall testcase; protected final MeasurementConfig configuration; - protected final PeassFolders folders; + protected final CauseSearchFolders folders; private ResultOrganizer currentOrganizer; protected final EnvironmentVariables env; - + protected final CauseSearcherConfig causeSearcherConfig; + private final CausePersistenceManager persistenceManager; + private final BothTreeReader reader; + protected long currentChunkStart = 0; - public SamplingCauseSearcher(TestMethodCall testcase, MeasurementConfig configuration, PeassFolders folders, EnvironmentVariables env) { + public SamplingCauseSearcher(TestMethodCall testcase, MeasurementConfig configuration, CauseSearchFolders folders, + EnvironmentVariables env, CauseSearcherConfig causeSearcherConfig, + final BothTreeReader reader) { this.testcase = testcase; this.configuration = configuration; this.folders = folders; this.env = env; + this.causeSearcherConfig = causeSearcherConfig; + this.persistenceManager = new CausePersistenceManager(causeSearcherConfig, configuration, folders); + this.reader = reader; } @Override @@ -52,34 +77,200 @@ public Set search() { fixedCommitConfig.getCommit()); new FolderDeterminer(folders).testResultFolders(fixedCommitConfig.getCommit(), fixedCommitConfig.getCommitOld(), testcase); - final File logFolder = folders.getMeasureLogFolder(configuration.getFixedCommitConfig().getCommit(), testcase); + final File logFolder = folders.getRCALogFolder(configuration.getFixedCommitConfig().getCommit(), testcase, 0); + Set result = new HashSet<>(); try (ProgressWriter writer = new ProgressWriter(folders.getProgressFile(), configuration.getVms())) { - evaluateSimple(testcase, logFolder, writer); + result = evaluateSimple(testcase, logFolder, writer); } - throw new RuntimeException("Not implemented yet"); + if (result.isEmpty()) { + throw new RuntimeException("Result is empty"); + } + + return result; } - private void evaluateSimple(TestMethodCall testcase2, File logFolder, ProgressWriter writer) { + private Set evaluateSimple(TestMethodCall testcase2, File logFolder, ProgressWriter writer) { currentChunkStart = System.currentTimeMillis(); + + MeasurementIdentifier measurementIdentifier = new MeasurementIdentifier(); + String outputPath = logFolder.getAbsolutePath() + "/sjsw-results"; + + Config sjswConfiguration = Config.builder() + .autodownloadProfiler() + .outputPathWithIdentifier(outputPath, measurementIdentifier) + .frequency(1) + .jfrEnabled(true) + .build(); + + SamplerResultsProcessor processor = new SamplerResultsProcessor(); + for (int finishedVMs = 0; finishedVMs < configuration.getVms(); finishedVMs++) { long comparisonStart = System.currentTimeMillis(); - runOneComparison(logFolder, testcase, finishedVMs); + runOneComparison(logFolder, testcase, finishedVMs, sjswConfiguration); long durationInSeconds = (System.currentTimeMillis() - comparisonStart) / 1000; writer.write(durationInSeconds, finishedVMs); betweenVMCooldown(); } + + return analyseSamplingResults(processor, measurementIdentifier, testcase2, configuration.getVms()); + } + + private Set analyseSamplingResults(SamplerResultsProcessor processor, MeasurementIdentifier identifier, TestMethodCall testcase, int vms) { + File resultDir = retrieveSamplingResultsDirectory(identifier); + Path resultsPath = resultDir.toPath(); + var commits = getVersions(); + + StackTraceTreeNode commitBAT = retrieveBatForCommit(commits[1], processor, resultsPath); + StackTraceTreeNode predecessorBAT = retrieveBatForCommit(commits[0], processor, resultsPath); + + // Convert BAT to CallTreeNode for both commits + CallTreeNode root = null; + root = SjswCctConverter.convertCallContextTreeToCallTree(commitBAT, predecessorBAT, root, commits[1], commits[0], vms); + + if (root == null) { + throw new RuntimeException("CallTreeNode was null after attempted conversion from SJSW structure."); + } + + // Persist CallTreeNode + persistBasicCallTreeNode(root); + printCallTreeNode(root); + System.out.println(); + printCallTreeNode(root.getOtherCommitNode()); + + CompleteTreeAnalyzer completeTreeAnalyzer = new CompleteTreeAnalyzer(root, root.getOtherCommitNode()); + + Set differentMethods = getDifferingMethodCalls(root, root.getOtherCommitNode()); + return differentMethods; + } + + public static void printCallTreeNode(CallTreeNode root) { + printCallTreeNodeTreeRecursive(root, "", false); + } + + public static void printCallTreeNodeTreeRecursive(CallTreeNode node, String prefix, boolean isLast) { + List measurements = new LinkedList<>(); + node.getData().forEach((commit, value) -> { + measurements.add(commit + "---" + value.getResults().size()); + }); + if (node.getCall() != null) { + System.out.println(prefix + (isLast ? "└────── " : "├────── ") + node.getCall() + + " Measurements: " + measurements); + } + + List children = node.getChildren(); + for (int i = 0; i < children.size(); i++) { + printCallTreeNodeTreeRecursive(children.get(i), prefix + (isLast ? " " : "│ "), i == children.size() - 1); + } + } + + private void persistBasicCallTreeNode(CallTreeNode node) { + String outputFile = folders.getMeasureLogFolder().getAbsoluteFile() + "/calltreenode_serialized" + UUID.randomUUID() + ".json"; + try { + Constants.OBJECTMAPPER.writeValue(new File(outputFile), node); + } catch (IOException e) { + LOG.error("Failed to serialize call tree node {}", node, e); + } } - public void runOneComparison(final File logFolder, final TestMethodCall testcase, final int vmid) { + private Set getDifferingMethodCalls(CallTreeNode currentRoot, CallTreeNode rootPredecessor) { + // Define tree analyzer + var creator = new TreeAnalyzerCreator() { + @Override + public TreeAnalyzer getAnalyzer(final BothTreeReader reader, final CauseSearcherConfig config) { + return new CompleteTreeAnalyzer(currentRoot, rootPredecessor); + } + }; + final TreeAnalyzer analyzer = creator.getAnalyzer(reader, causeSearcherConfig); + final List predecessorNodeList = analyzer.getMeasurementNodesPredecessor(); + final List includableNodes = getIncludableNodes(predecessorNodeList); + + if (includableNodes.isEmpty()) { + throw new RuntimeException("Tried to analyze empty node list"); + } + + applyMeasurementToDefinedTree(includableNodes, rootPredecessor); + + return convertToChangedEntitites(includableNodes); + } + + private void applyMeasurementToDefinedTree(List differingNodes, CallTreeNode rootPredecessor) { + final AllDifferingDeterminer allSearcher = new AllDifferingDeterminer(differingNodes, causeSearcherConfig, configuration); + allSearcher.calculateDiffering(); + + RCAMeasurementAdder measurementReader = new RCAMeasurementAdder(persistenceManager, differingNodes); + measurementReader.addAllMeasurements(rootPredecessor); + + differingNodes.addAll(allSearcher.getLevelDifferentPredecessor()); + + persistenceManager.writeTreeState(); + } + + private Set convertToChangedEntitites(List differingNodes) { + final Set changed = new TreeSet<>(); + differingNodes.forEach(node -> { + changed.add(node.toEntity()); + }); + return changed; + } + + private List getIncludableNodes(final List predecessorNodeList) { + final List includableNodes; + if (causeSearcherConfig.useCalibrationRun()) { + includableNodes = getAnalysableNodes(predecessorNodeList); + } else { + includableNodes = predecessorNodeList; + } + + LOG.debug("Analyzable: {} / {}", includableNodes.size(), predecessorNodeList.size()); + return includableNodes; + } + + private List getAnalysableNodes(final List predecessorNodeList) { + final MeasurementConfig config = new MeasurementConfig(1, configuration.getFixedCommitConfig().getCommit(), configuration.getFixedCommitConfig().getCommitOld()); + config.setIterations(configuration.getIterations()); + config.setRepetitions(configuration.getRepetitions()); + config.setWarmup(configuration.getWarmup()); + config.getKiekerConfig().setUseKieker(false); + + List commits = GitUtils.getCommits(folders.getProjectFolder(), true, true); + CommitComparatorInstance comparator = new CommitComparatorInstance(commits); + + final CauseTester calibrationMeasurer = new CauseTester(folders, config, causeSearcherConfig, env, comparator); + final AllDifferingDeterminer calibrationRunner = new AllDifferingDeterminer(predecessorNodeList, causeSearcherConfig, config); + calibrationMeasurer.measureCommit(predecessorNodeList); + final List includableByMinTime = calibrationRunner.getIncludableNodes(); + return includableByMinTime; + } + + private StackTraceTreeNode retrieveBatForCommit(String commit, SamplerResultsProcessor processor, Path resultsPath) { + List commitJfrs = processor.listJfrMeasurementFiles(resultsPath, List.of(commit)); + String normalizedMethodName = testcase.getMethodWithParams().substring(testcase.getMethod().lastIndexOf('#') + 1); + + StackTraceTreeBuilder builder = new StackTraceTreeBuilder(); + StackTraceTreeNode mergedTree = builder.buildTree(commitJfrs, commit, configuration.getVms(), normalizedMethodName, true); + + System.out.println(); + mergedTree.printTree(); + System.out.println(); + return mergedTree; + } + + private File retrieveSamplingResultsDirectory(MeasurementIdentifier identifier) { + final File logFolder = folders.getRCALogFolder(configuration.getFixedCommitConfig().getCommit(), testcase, 0); + String outputPath = logFolder.getAbsolutePath() + "/sjsw-results"; + return new File(outputPath + "/measurement_" + identifier.getUuid().toString()); + } + + public void runOneComparison(final File logFolder, final TestMethodCall testcase, final int vmid, final Config sjswConfiguration) { String[] commits = getVersions(); if (configuration.getMeasurementStrategy().equals(MeasurementStrategy.SEQUENTIAL)) { LOG.info("Running sequential"); - runSequential(logFolder, testcase, vmid, commits); + runSequential(logFolder, testcase, vmid, commits, sjswConfiguration); } else if (configuration.getMeasurementStrategy().equals(MeasurementStrategy.PARALLEL)) { LOG.info("Running parallel"); runParallel(logFolder, testcase, vmid, commits); @@ -90,18 +281,18 @@ private void runParallel(File logFolder, TestMethodCall testcase2, int vmid, Str throw new RuntimeException("Not implemented yet"); } - private void runSequential(File logFolder, TestMethodCall testcase2, int vmid, String[] commits) { + private void runSequential(File logFolder, TestMethodCall testcase2, int vmid, String[] commits, Config config) { currentOrganizer = new ResultOrganizer(folders, configuration.getFixedCommitConfig().getCommit(), currentChunkStart, configuration.getKiekerConfig().isUseKieker(), configuration.isSaveAll(), testcase, configuration.getAllIterations()); for (String commit : commits) { - runOnce(testcase, commit, vmid, logFolder); + runOnce(testcase, commit, vmid, logFolder, config); } } - private void runOnce(final TestMethodCall testcase, final String commit, final int vmid, final File logFolder) { + private void runOnce(final TestMethodCall testcase, final String commit, final int vmid, final File logFolder, final Config config) { final TestExecutor testExecutor = getExecutor(folders, commit); - final SamplingRunner runner = new SamplingRunner(folders, testExecutor, getCurrentOrganizer(), this); + final SamplingRunner runner = new SamplingRunner(folders, testExecutor, getCurrentOrganizer(), this, config); runner.runOnce(testcase, commit, vmid, logFolder); } @@ -121,11 +312,11 @@ protected void betweenVMCooldown() { throw new RuntimeException(e); } } - + public ResultOrganizer getCurrentOrganizer() { return currentOrganizer; } - + private String[] getVersions() { String commits[] = new String[2]; commits[0] = configuration.getFixedCommitConfig().getCommitOld().equals("HEAD~1") ? configuration.getFixedCommitConfig().getCommit() + "~1" diff --git a/measurement/src/main/java/de/dagere/peass/measurement/utils/sjsw/SjswCctConverter.java b/measurement/src/main/java/de/dagere/peass/measurement/utils/sjsw/SjswCctConverter.java new file mode 100644 index 000000000..ff06d6623 --- /dev/null +++ b/measurement/src/main/java/de/dagere/peass/measurement/utils/sjsw/SjswCctConverter.java @@ -0,0 +1,230 @@ +package de.dagere.peass.measurement.utils.sjsw; + +import de.dagere.nodeDiffDetector.data.MethodCall; +import de.dagere.peass.config.MeasurementConfig; +import de.dagere.peass.measurement.rca.data.CallTreeNode; +import io.github.terahidro2003.result.tree.StackTraceTreeNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Stack; + +public class SjswCctConverter { + private static final Logger LOG = LoggerFactory.getLogger(SjswCctConverter.class); + + public static CallTreeNode convertCallContextTreeToCallTree(StackTraceTreeNode currentBAT, StackTraceTreeNode predecessorBAT, CallTreeNode ctn, String commit, String predecessor, int vms) { + if (commit == null && predecessor == null) { + throw new IllegalArgumentException("Commit and Predesseror cannot be null"); + } + + LOG.info("Current original node: {}", currentBAT.getPayload().getMethodName()); + + MeasurementConfig mConfig = new MeasurementConfig(vms, commit, predecessor); + StackTraceTreeNode otherNode = predecessorBAT != null ? search(currentBAT, predecessorBAT) : null; + + LOG.info("Other original node: {}", otherNode != null ? otherNode.getPayload().getMethodName() : null); + LOG.info("Other original node: {}", predecessorBAT != null ? predecessorBAT.getPayload().getMethodName() : null); + + String methodNameWithNew = normalizeKiekerPattern(currentBAT); + if(methodNameWithNew.contains("")) { + methodNameWithNew = "new " + methodNameWithNew; + } + String call = getCall(methodNameWithNew); + if(ctn == null) { + ctn = new CallTreeNode(call, + methodNameWithNew, + methodNameWithNew, + mConfig); + createPeassNode(currentBAT, otherNode, ctn, commit, predecessor, vms, true); + } else { + createPeassNode(currentBAT, otherNode, ctn, commit, predecessor, vms, false); + ctn = ctn.getChildByKiekerPattern(methodNameWithNew); + } + + if (otherNode != null) { + CallTreeNode otherCallTreeNode = null; + otherCallTreeNode = createOtherNodeRecursive(otherNode, currentBAT, otherCallTreeNode, vms, predecessor, commit); + ctn.setOtherCommitNode(otherCallTreeNode); + } + + List children = currentBAT.getChildren(); + if (children.isEmpty() && ctn != null) { + createPeassNode(currentBAT, otherNode, ctn, commit, predecessor, vms, true); + } + for (StackTraceTreeNode child : children) { + if (child != null) { + convertCallContextTreeToCallTree(child, otherNode, ctn, commit, predecessor, vms); + } + } + + return ctn; + } + + private static String getCall(String methodNameWithNew) { + int indexOfParenthesis = methodNameWithNew.indexOf('('); + + String partBeforeParenthesis = methodNameWithNew.substring(0, indexOfParenthesis); + String parameters = methodNameWithNew.substring(indexOfParenthesis).replace(" ", ""); + int methodSeperatorIndex = partBeforeParenthesis.lastIndexOf('.'); + String clazz = partBeforeParenthesis.substring(0, methodSeperatorIndex); + String method = partBeforeParenthesis.substring(methodSeperatorIndex + 1) ; + + String call = clazz + MethodCall.METHOD_SEPARATOR + method + parameters; + return call; + } + + private static String normalizeKiekerPattern(StackTraceTreeNode node) { + String methodSignature = node.getPayload().getMethodName(); + if ("root".equals(methodSignature)) { + methodSignature = "RootClass.root"; + } + if (!methodSignature.contains("(")) { + methodSignature = methodSignature + "()"; + } else { + int indexOfParenthesis = methodSignature.indexOf('('); + String partBeforeParenthesis = methodSignature.substring(0, indexOfParenthesis); + String parameters = methodSignature.substring(indexOfParenthesis).replace(" ", ""); + methodSignature = partBeforeParenthesis + parameters; + } + return methodSignature; + } + + public static StackTraceTreeNode search(StackTraceTreeNode searchable, StackTraceTreeNode tree) { + Stack stack = new Stack<>(); + stack.push(tree); + + while (!stack.isEmpty()) { + StackTraceTreeNode currentNode = stack.pop(); + + if(searchable.equals(currentNode)) { + return currentNode; + } + + for (StackTraceTreeNode child : currentNode.getChildren()) { + if (child != null) { + stack.push(child); + } + } + } + + return null; + } + + private static void createPeassNode(StackTraceTreeNode node, StackTraceTreeNode otherNode, CallTreeNode peassNode, + String commit, String oldCommit, int vms, boolean lastNode) { + LOG.info("Creating peass node for stacktracetreenodes: {} -> {}", node.getPayload().getMethodName() + "(" + node.getMeasurements() + ")", otherNode != null ? otherNode.getPayload().getMethodName() + "(" + otherNode.getMeasurements() + ")" : null); + peassNode.initCommitData(); + + addMeasurements(commit, node, peassNode, vms); + if(otherNode != null) { + LOG.info("Adding measurements for the other commit {}", oldCommit); + addMeasurements(oldCommit, otherNode, peassNode, vms); + } + + if(!lastNode) appendChild(node, peassNode); + + peassNode.createStatistics(commit); + peassNode.createStatistics(oldCommit); + + LOG.info("Current stats: {} --> {}", commit, peassNode.getData().get(commit).getResults().size()); + if(otherNode != null) { + LOG.info("Current stats: {} --> {}", oldCommit, peassNode.getData().get(oldCommit).getResults().size()); + } + } + + public static String getCorrectCallString(String method) { + int lastParenthesisIndex = method.contains("(") ? method.lastIndexOf("(") : method.length() -1; + String methodName = method.substring(0, lastParenthesisIndex); + + String[] parts = methodName.split(" "); + String methodNameWithoutType = parts.length > 1 ? parts[parts.length - 1] : method; + + int lastDotIndex = methodNameWithoutType.contains(".") ? methodNameWithoutType.lastIndexOf(".") + : -1; + String className = lastDotIndex > 0 ? methodNameWithoutType.substring(0, lastDotIndex) : ""; + methodName = methodNameWithoutType.substring(lastDotIndex + 1); + + return className + "#" + methodName; + } + + private static void appendChild(StackTraceTreeNode node, CallTreeNode peassNode) { + // check is done as a workaround for Peass kieker pattern check + String methodNameWithNew = normalizeKiekerPattern(node); + String call = getCall(methodNameWithNew); + if(node.getPayload().getMethodName().contains("")) { + methodNameWithNew = "new " + methodNameWithNew; + peassNode.appendChild(call, + methodNameWithNew, + methodNameWithNew + ); + } else { + peassNode.appendChild(call, + methodNameWithNew, + methodNameWithNew + ); + } + } + + private static void addMeasurements(String commit, StackTraceTreeNode node, CallTreeNode peassNode, int vms) { + List measurementsForSpecificCommit = node.getMeasurements().get(commit); + if(measurementsForSpecificCommit == null || measurementsForSpecificCommit.isEmpty()) { + throw new IllegalArgumentException("Possibly invalid measurement data. Commit " + + commit + " does not contain any measurement data."); + } + + if (measurementsForSpecificCommit.size() != vms) { + int missing = vms - measurementsForSpecificCommit.size(); + for (int i = 0; i")) { + methodNameWithNew = "new " + otherNode.getPayload().getMethodName(); + } + String call = getCall(methodNameWithNew); + if(otherCallTreeNode == null) { + otherCallTreeNode = new CallTreeNode(call, + methodNameWithNew, + methodNameWithNew, + mConfig); + createPeassNode(otherNode, node, otherCallTreeNode, predecessor, commit, vms, true); + } else { + createPeassNode(otherNode, node, otherCallTreeNode, predecessor, commit, vms, false); + otherCallTreeNode = otherCallTreeNode.getChildByKiekerPattern(methodNameWithNew); + } + + if (otherCallTreeNode != null) { + List children = otherNode.getChildren(); + if (children.isEmpty() && otherCallTreeNode != null) { + createPeassNode(otherNode, node, otherCallTreeNode, predecessor, commit, vms, true); + } + for (StackTraceTreeNode child : children) { + createOtherNodeRecursive(child, node, otherCallTreeNode , vms, predecessor, commit); + } + } else { + LOG.warn("Didn't find other call tree node for " + methodNameWithNew + " (Call: " + call + ")"); + } + + + + return otherCallTreeNode; + } +} diff --git a/measurement/src/test/java/de/dagere/peass/measurement/utils/SjswCctConverterTest.java b/measurement/src/test/java/de/dagere/peass/measurement/utils/SjswCctConverterTest.java new file mode 100644 index 000000000..99db3b1b5 --- /dev/null +++ b/measurement/src/test/java/de/dagere/peass/measurement/utils/SjswCctConverterTest.java @@ -0,0 +1,172 @@ +package de.dagere.peass.measurement.utils; + +import de.dagere.nodeDiffDetector.data.MethodCall; +import de.dagere.peass.config.MeasurementConfig; +import de.dagere.peass.measurement.rca.analyzer.CompleteTreeAnalyzer; +import de.dagere.peass.measurement.rca.data.CallTreeNode; +import de.dagere.peass.measurement.utils.sjsw.SjswCctConverter; +import io.github.terahidro2003.result.tree.StackTraceTreeBuilder; +import io.github.terahidro2003.result.tree.StackTraceTreeNode; +import io.github.terahidro2003.samplers.jfr.ExecutionSample; +import io.github.terahidro2003.samplers.jfr.Method; +import org.apache.commons.lang3.RandomUtils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; + +import java.util.*; + +public class SjswCctConverterTest { + private List path1a = new ArrayList<>(List.of("org.example.testing", "org.example.methodA", "org.example.methodB")); + private List path1b = new ArrayList<>(List.of("org.example.testing", "org.example.methodA", "org.example.someOtherMethod", "org.example.someOtherMethod", "libjvm.so.Runtime1::counter_overflow()")); + private List path2 = new ArrayList<>(List.of("org.example.testing", "org.example.methodB")); + + @BeforeEach + void prepare() { + reverseStacktraces(); + } + + @Test + public void testWithoutEmptyNodes() { + int vms = 2; + String commit = "a1"; + String oldCommit = "b2"; + StackTraceTreeNode current = prepareFakeTree(List.of(path1a, path1b), commit, vms); + StackTraceTreeNode old = prepareFakeTree(List.of(path1a, path2), + oldCommit, vms); + + printTrees(current, old); + + CallTreeNode root = null; + root = SjswCctConverter.convertCallContextTreeToCallTree(current, old, root, commit, oldCommit, vms); + + CompleteTreeAnalyzer analyzer = new CompleteTreeAnalyzer(root, root.getOtherCommitNode()); + var bla = root.getOtherCommitNode(); + if(bla == null) { + throw new RuntimeException("Other commit node is null"); + } + + printCallTreeNode(root); + System.out.println(); + printCallTreeNode(root.getOtherCommitNode()); + + reproduceToEntityProblem(root, root.getOtherCommitNode()); + } + + @Test + public void testCorrectCallString() { + String methodSignature = "public void org.example.testing(int, long)"; + String call = SjswCctConverter.getCorrectCallString(methodSignature); + Assert.assertEquals("org.example#testing", call); + } + + @Test + public void testCTNToEntity() { + String methodSignature = "public void org.example.testing(int, long)"; + String call = SjswCctConverter.getCorrectCallString(methodSignature); + final CallTreeNode node = new CallTreeNode(call, methodSignature, methodSignature, (MeasurementConfig) null); + System.out.println("Node created: " + node.getCall() + ", " + node.getMethod()); + MethodCall result = node.toEntity(); + Assert.assertEquals(new MethodCall("org.example", "", "testing"), node.toEntity()); + } + + @Test + public void testCTNToEntityWithRootNode() { + String methodSignature = "Root.root()"; + String call = "Root#root"; +// String call = SjswCctConverter.getCorrectCallString(methodSignature); + final CallTreeNode node = new CallTreeNode(call, methodSignature, methodSignature, (MeasurementConfig) null); + System.out.println("Node created: " + node.getCall() + ", " + node.getMethod()); + MethodCall result = node.toEntity(); + Assert.assertEquals(new MethodCall("Root", "", "root"), node.toEntity()); + } + + private void reverseStacktraces() { + Collections.reverse(path1a); + Collections.reverse(path1b); + Collections.reverse(path2); + } + + private void printTrees(StackTraceTreeNode current, StackTraceTreeNode old) { + current.printTree(); + System.out.println(); + System.out.println(); + old.printTree(); + } + + public static void printCallTreeNode(CallTreeNode root) { + printCallTreeNodeTreeRecursive(root, "", false); + } + + public static void printCallTreeNodeTreeRecursive(CallTreeNode node, String prefix, boolean isLast) { + List measurements = new LinkedList<>(); + node.getData().forEach((commit, value) -> { + measurements.add(commit + "---" + value.getResults().size()); + }); + if (node.getCall() != null) { + System.out.println(prefix + (isLast ? "└────── " : "├────── ") + node.getKiekerPattern() + + " Measurements: " + measurements); + } + + List children = node.getChildren(); + for (int i = 0; i < children.size(); i++) { + printCallTreeNodeTreeRecursive(children.get(i), prefix + (isLast ? " " : "│ "), i == children.size() - 1); + } + } + + private StackTraceTreeNode prepareFakeTree(List> pathsAsMethodNames, String commit, int vms) { + List samples = new ArrayList<>(); + pathsAsMethodNames.forEach(path -> { + samples.add(getMockExecutionSample(path)); + }); + + StackTraceTreeBuilder treeBuilder = new StackTraceTreeBuilder(); + StackTraceTreeNode tree = treeBuilder.buildFromExecutionSamples(samples); + addFakeMeasurements(tree, commit, vms); + + return tree; + } + + private void addFakeMeasurements(StackTraceTreeNode root, String commit, int vms) { + Stack stack = new Stack<>(); + stack.push(root); + + while (!stack.isEmpty()) { + StackTraceTreeNode currentNode = stack.pop(); + + int randomAmountofSamples = RandomUtils.nextInt(1, 1000); + for (int i = 0; i < vms; i++) { + int amount = randomAmountofSamples * RandomUtils.nextInt(1, 5); + currentNode.addMeasurement(commit, (double) amount); + } + + for (StackTraceTreeNode child : currentNode.getChildren()) { + if (child != null) { + stack.push(child); + } + } + } + } + + private ExecutionSample getMockExecutionSample(List stacktraceAsString) { + List stacktrace = new ArrayList<>(); + stacktraceAsString.forEach(s -> { + Method method = new Method(); + method.setMethodName(s); + method.setMethodModifier("public void"); + method.setMethodDescriptor("int, long"); + stacktrace.add(method); + }); + ExecutionSample sample = new ExecutionSample(); + sample.setStackTrace(stacktrace); + return sample; + } + + private void reproduceToEntityProblem(CallTreeNode root, CallTreeNode rootPredecessor) { + root.toEntity(); + List children = root.getChildren(); + for (CallTreeNode child : children) { + reproduceToEntityProblem(child, child.getOtherCommitNode()); + } + } +} diff --git a/peass-jmh/src/main/java/de/dagere/peass/dependency/jmh/JmhTestExecutor.java b/peass-jmh/src/main/java/de/dagere/peass/dependency/jmh/JmhTestExecutor.java index f7b3d905a..c55f8859a 100644 --- a/peass-jmh/src/main/java/de/dagere/peass/dependency/jmh/JmhTestExecutor.java +++ b/peass-jmh/src/main/java/de/dagere/peass/dependency/jmh/JmhTestExecutor.java @@ -55,6 +55,11 @@ public void prepareKoPeMeExecution(final File logFile) { execute("jmh-package", transformer.getConfig().getTimeoutInSeconds(), process); } + @Override + public void executeTest(String javaAgent, final TestMethodCall test, final File logFolder, final long timeoutInSeconds) { + throw new RuntimeException("Not implemented yet"); + } + @Override public void executeTest(final TestMethodCall test, final File logFolder, final long timeoutInSeconds) { checkConfiguration(timeoutInSeconds);