package pebl.builder; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import pebl.HasId; import pebl.benchmark.feature.Metric; import pebl.benchmark.feature.MetricType; import pebl.result.Measurement; import pebl.result.engine.Engine; import pebl.result.feature.AggregatedResult; import pebl.result.test.TestResult; import pebl.xsd.PEBL; public class Aggregator { public void computeFeatureResults(PEBL pebl) { final Map<String, List<TestResult>> resultsPerEngineTool = pebl.result.testResults.stream().collect(Collectors.groupingBy(HasId::getId)); // everything is recalculated pebl.result.aggregatedResults.clear(); List<Metric> metrics = new LinkedList<>(); pebl.benchmark.capabilities.forEach(c -> { metrics.addAll(c.getMetrics()); c.getLanguages().forEach(l -> { metrics.addAll(l.getMetrics()); l.getGroups().forEach(g -> { metrics.addAll(g.getMetrics()); g.getFeatureSets().forEach(fs -> { metrics.addAll(fs.getMetrics()); fs.getFeatures().forEach(f -> { metrics.addAll(f.getMetrics()); }); }); }); }); }); for (Metric metric : metrics) { final MetricType metricType = metric.getMetricType(); if (metricType.getGroovyScript() == null || metricType.getGroovyScript().trim().isEmpty()) { throw new IllegalStateException("Metric type must be a script metric type"); } for (Map.Entry<String, List<TestResult>> entry : resultsPerEngineTool.entrySet()) { if (entry.getValue().isEmpty()) { continue; } // ensure that only the test results relevant for the metric are there List<TestResult> testResults = entry.getValue() .stream() .filter(tr -> { final String postfix = HasId.SEPARATOR + metric.getMetricType().getId(); final String featureTreeIdMetricReferences = metric.getId().replace(postfix, ""); return tr.getTest().getId().startsWith(featureTreeIdMetricReferences); }) .collect(Collectors.toList()); if (testResults.isEmpty()) { continue; } System.out.println("Computing " + metric.getId() + " for " + entry.getKey()); String value = computeThroughScript(metric, testResults); Engine engine = testResults.get(0).getEngine(); Measurement measurement = new Measurement(metric, value); final Optional<AggregatedResult> featureResultOptional = pebl.result.aggregatedResults.stream() .filter(fr -> fr.getEngine().getId().equals(engine.getId())) .findFirst(); if (featureResultOptional.isPresent()) { featureResultOptional.get().getMeasurement().add(measurement); } else { pebl.result.aggregatedResults.add(new AggregatedResult(Arrays.asList(measurement), engine)); } } } } private String computeThroughScript(Metric metric, List<TestResult> testResults) { MetricType metricType = metric.getMetricType(); // TODO use AggregateScript as a wrapper through GroovyShell if (metricType.getId().equals("testCasesSum")) { return String.valueOf(getTestCases(testResults)); } else if (metricType.getId().equals("testCaseSuccessesSum")) { return String.valueOf(getTestCaseSuccesses(testResults)); } else if (metricType.getId().equals("testCaseFailuresSum")) { return String.valueOf(getTestCaseFailures(testResults)); } else if (metricType.getId().equals("testSuccessfulCount")) { return String.valueOf(getTestSuccessfulCount(testResults)); } else if (metricType.getId().equals("testDeployableCount")) { return String.valueOf(getTestDeployable(testResults)); } else if (metricType.getId().equals("testResultTrivalentAggregation")) { return testResults.stream().map(this::getResultTrivalentAggregation).reduce(Ternary.PLUS, Ternary::aggregate).getString(); } else if (metricType.getId().equals("testsCount")) { return String.valueOf((long) testResults.size()); } else if (metricType.getId().equals("patternSupport")) { return getSupport(testResults).getString(); } else if (metricType.getId().equals("patternImplementationSupport")) { return getSupport(testResults.get(0)).getString(); } else if (metricType.getId().equals("patternImplementationFulfilledLanguageSupport")) { return String.valueOf(!getSupport(testResults.get(0)).equals(Ternary.MINUS)); } else if (metricType.getId().equals("patternFulfilledLanguageSupport")) { Ternary support = getSupport(testResults); Ternary languageSupportOfFeatureSet = Ternary.from(testResults.get(0).getTest().getFeature().getFeatureSet().getExtensions().get("languageSupport")); return String.valueOf(support.equals(languageSupportOfFeatureSet)); } throw new IllegalStateException("Cannot compute metric " + metricType); } private long getTestSuccessfulCount(List<TestResult> testResults) { return testResults .stream() .map(tr -> tr.getMeasurements() .stream() .filter(m -> m.getMetric().getMetricType().getId().equals("testSuccessful")) .findFirst() .map(Measurement::getValue) .orElse("false") ) .map(Boolean::parseBoolean) .filter(x -> x) .count(); } private Ternary getResultTrivalentAggregation(TestResult testResult) { final long testCaseSuccesses = getTestCaseSuccesses(Collections.singletonList(testResult)); final long testCasesFailures = getTestCaseFailures(Collections.singletonList(testResult)); if (testCasesFailures == 0) { return Ternary.PLUS; } else if (testCaseSuccesses == 0) { return Ternary.MINUS; } else { return Ternary.PLUS_MINUS; } } private Ternary getSupport(TestResult testResult) { return Optional.of(testResult) .map(tr -> { final String result = tr.getMeasurements() .stream() .filter(m -> m.getMetric().getMetricType().getId().equals("testResult")) .findFirst() .map(Measurement::getValue) .orElse("-"); String extensionLanguageSupport = tr.getTest().getFeature().getExtensions().get("languageSupport"); if (result.equals("+")) { return Ternary.from(extensionLanguageSupport); } else { return Ternary.MINUS; } } ).orElse(Ternary.MINUS); } private Ternary getSupport(List<TestResult> testResults) { Ternary languageSupportOfFeatureSet = Ternary.from(testResults.get(0).getTest().getFeature().getFeatureSet().getExtensions().get("languageSupport")); return testResults.stream().map(this::getSupport).map(t -> t.atMost(languageSupportOfFeatureSet)).reduce(Ternary.MINUS, Ternary::max); } private long getTestDeployable(List<TestResult> testResults) { return testResults .stream() .map(tr -> tr.getMeasurements() .stream() .filter(m -> m.getMetric().getMetricType().getId().equals("testDeployable")) .findFirst() .map(Measurement::getValue) .orElse("false") ) .map(Boolean::parseBoolean) .filter(x -> x) .count(); } private long getTestCaseSuccesses(List<TestResult> testResults) { return testResults .stream() .map(tr -> tr.getMeasurements() .stream() .filter(m -> m.getMetric().getMetricType().getId().equals("testCaseSuccesses")) .findFirst() .map(Measurement::getValue) .orElse("0") ) .mapToLong(Long::parseLong) .sum(); } private long getTestCases(List<TestResult> testResults) { return testResults .stream() .map(tr -> tr.getMeasurements() .stream() .filter(m -> m.getMetric().getMetricType().getId().equals("testCases")) .findFirst() .map(Measurement::getValue) .orElse("0") ) .mapToLong(Long::parseLong) .sum(); } private long getTestCaseFailures(List<TestResult> testResults) { return testResults .stream() .map(tr -> tr.getMeasurements() .stream() .filter(m -> m.getMetric().getMetricType().getId().equals("testCaseFailures")) .findFirst() .map(Measurement::getValue) .orElse("0") ) .mapToLong(Long::parseLong) .sum(); } }