/* * SonarQube * Copyright (C) 2009-2017 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.sonar.scanner.report; import com.google.common.collect.Iterables; import java.util.HashSet; import java.util.Set; import java.util.stream.StreamSupport; import org.sonar.api.batch.fs.InputComponent; import org.sonar.api.batch.fs.internal.DefaultInputComponent; import org.sonar.api.test.CoverageBlock; import org.sonar.api.test.MutableTestCase; import org.sonar.api.test.MutableTestPlan; import org.sonar.api.test.TestCase; import org.sonar.scanner.deprecated.test.DefaultTestable; import org.sonar.scanner.deprecated.test.TestPlanBuilder; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.protocol.output.ScannerReport.CoverageDetail; import org.sonar.scanner.protocol.output.ScannerReport.Test; import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus; import org.sonar.scanner.scan.filesystem.InputComponentStore; import org.sonar.scanner.protocol.output.ScannerReportWriter; import static java.util.stream.Collectors.toList; public class TestExecutionAndCoveragePublisher implements ReportPublisherStep { private final InputComponentStore componentStore; private final TestPlanBuilder testPlanBuilder; public TestExecutionAndCoveragePublisher(InputComponentStore componentStore, TestPlanBuilder testPlanBuilder) { this.componentStore = componentStore; this.testPlanBuilder = testPlanBuilder; } @Override public void publish(ScannerReportWriter writer) { final ScannerReport.Test.Builder testBuilder = ScannerReport.Test.newBuilder(); final ScannerReport.CoverageDetail.Builder builder = ScannerReport.CoverageDetail.newBuilder(); final ScannerReport.CoverageDetail.CoveredFile.Builder coveredBuilder = ScannerReport.CoverageDetail.CoveredFile.newBuilder(); for (final InputComponent c : componentStore.all()) { DefaultInputComponent component = (DefaultInputComponent) c; final MutableTestPlan testPlan = testPlanBuilder.loadPerspective(MutableTestPlan.class, component); if (testPlan == null || Iterables.isEmpty(testPlan.testCases())) { continue; } final Set<String> testNamesWithCoverage = new HashSet<>(); writer.writeTests(component.batchId(), StreamSupport.stream(testPlan.testCases().spliterator(), false) .map(testCase -> toProtobufTest(testBuilder, testNamesWithCoverage, testCase)) .collect(toList())); writer.writeCoverageDetails(component.batchId(), testNamesWithCoverage.stream() .map(testName -> toProtobufCoverageDetails(builder, coveredBuilder, testPlan, testName)) .collect(toList())); } } private CoverageDetail toProtobufCoverageDetails(final ScannerReport.CoverageDetail.Builder builder, final ScannerReport.CoverageDetail.CoveredFile.Builder coveredBuilder, final MutableTestPlan testPlan, String testName) { // Take first test with provided name MutableTestCase testCase = testPlan.testCasesByName(testName).iterator().next(); builder.clear(); builder.setTestName(testName); for (CoverageBlock block : testCase.coverageBlocks()) { coveredBuilder.clear(); DefaultInputComponent c = (DefaultInputComponent) componentStore.getByKey(((DefaultTestable) block.testable()).inputFile().key()); coveredBuilder.setFileRef(c.batchId()); for (int line : block.lines()) { coveredBuilder.addCoveredLine(line); } builder.addCoveredFile(coveredBuilder.build()); } return builder.build(); } private static Test toProtobufTest(final ScannerReport.Test.Builder testBuilder, final Set<String> testNamesWithCoverage, MutableTestCase testCase) { testBuilder.clear(); testBuilder.setName(testCase.name()); if (testCase.doesCover()) { testNamesWithCoverage.add(testCase.name()); } Long durationInMs = testCase.durationInMs(); if (durationInMs != null) { testBuilder.setDurationInMs(durationInMs.longValue()); } String msg = testCase.message(); if (msg != null) { testBuilder.setMsg(msg); } String stack = testCase.stackTrace(); if (stack != null) { testBuilder.setStacktrace(stack); } TestCase.Status status = testCase.status(); if (status != null) { testBuilder.setStatus(TestStatus.valueOf(status.name())); } return testBuilder.build(); } }