- Drop api/tests WS - Drop persistance of tests and coverage details from compute engine - Drop tests and coverage details from scanner reporttags/7.6
@@ -59,10 +59,6 @@ public interface BatchReportReader { | |||
*/ | |||
Optional<CloseableIterator<String>> readFileSource(int fileRef); | |||
CloseableIterator<ScannerReport.Test> readTests(int testFileRef); | |||
CloseableIterator<ScannerReport.CoverageDetail> readCoverageDetails(int testFileRef); | |||
CloseableIterator<ScannerReport.ContextProperty> readContextProperties(); | |||
Optional<CloseableIterator<ScannerReport.LineSgnificantCode>> readComponentSignificantCode(int fileRef); |
@@ -19,11 +19,7 @@ | |||
*/ | |||
package org.sonar.ce.task.projectanalysis.batch; | |||
import com.google.common.base.Throwables; | |||
import com.google.protobuf.InvalidProtocolBufferException; | |||
import com.google.protobuf.Parser; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStreamReader; | |||
import java.util.NoSuchElementException; | |||
@@ -92,7 +88,6 @@ public class BatchReportReaderImpl implements BatchReportReader { | |||
return delegate.readAdHocRules(); | |||
} | |||
@Override | |||
public CloseableIterator<ScannerReport.Measure> readComponentMeasures(int componentRef) { | |||
ensureInitialized(); | |||
@@ -198,76 +193,12 @@ public class BatchReportReaderImpl implements BatchReportReader { | |||
} | |||
} | |||
@Override | |||
public CloseableIterator<ScannerReport.Test> readTests(int testFileRef) { | |||
ensureInitialized(); | |||
File file = delegate.readTests(testFileRef); | |||
if (file == null) { | |||
return CloseableIterator.emptyCloseableIterator(); | |||
} | |||
try { | |||
return new ParserCloseableIterator<>(ScannerReport.Test.parser(), FileUtils.openInputStream(file)); | |||
} catch (IOException e) { | |||
Throwables.propagate(e); | |||
// actually never reached | |||
return CloseableIterator.emptyCloseableIterator(); | |||
} | |||
} | |||
@Override | |||
public CloseableIterator<ScannerReport.CoverageDetail> readCoverageDetails(int testFileRef) { | |||
ensureInitialized(); | |||
File file = delegate.readCoverageDetails(testFileRef); | |||
if (file == null) { | |||
return CloseableIterator.emptyCloseableIterator(); | |||
} | |||
try { | |||
return new ParserCloseableIterator<>(ScannerReport.CoverageDetail.parser(), FileUtils.openInputStream(file)); | |||
} catch (IOException e) { | |||
Throwables.propagate(e); | |||
// actually never reached | |||
return CloseableIterator.emptyCloseableIterator(); | |||
} | |||
} | |||
@Override | |||
public CloseableIterator<ScannerReport.ContextProperty> readContextProperties() { | |||
ensureInitialized(); | |||
return delegate.readContextProperties(); | |||
} | |||
private static class ParserCloseableIterator<T> extends CloseableIterator<T> { | |||
private final Parser<T> parser; | |||
private final FileInputStream fileInputStream; | |||
public ParserCloseableIterator(Parser<T> parser, FileInputStream fileInputStream) { | |||
this.parser = parser; | |||
this.fileInputStream = fileInputStream; | |||
} | |||
@Override | |||
protected T doNext() { | |||
try { | |||
return parser.parseDelimitedFrom(fileInputStream); | |||
} catch (InvalidProtocolBufferException e) { | |||
Throwables.propagate(e); | |||
// actually never reached | |||
return null; | |||
} | |||
} | |||
@Override | |||
protected void doClose() throws Exception { | |||
fileInputStream.close(); | |||
} | |||
} | |||
public boolean hasSignificantCode(int fileRef) { | |||
return delegate.hasSignificantCode(fileRef); | |||
} | |||
@Override | |||
public Optional<CloseableIterator<LineSgnificantCode>> readComponentSignificantCode(int fileRef) { | |||
ensureInitialized(); |
@@ -25,16 +25,13 @@ import org.sonar.api.server.ServerSide; | |||
import org.sonar.db.purge.PurgeListener; | |||
import org.sonar.server.component.index.ComponentIndexer; | |||
import org.sonar.server.issue.index.IssueIndexer; | |||
import org.sonar.server.test.index.TestIndexer; | |||
@ServerSide | |||
public class IndexPurgeListener implements PurgeListener { | |||
private final TestIndexer testIndexer; | |||
private final IssueIndexer issueIndexer; | |||
private final ComponentIndexer componentIndexer; | |||
public IndexPurgeListener(TestIndexer testIndexer, IssueIndexer issueIndexer, ComponentIndexer componentIndexer) { | |||
this.testIndexer = testIndexer; | |||
public IndexPurgeListener(IssueIndexer issueIndexer, ComponentIndexer componentIndexer) { | |||
this.issueIndexer = issueIndexer; | |||
this.componentIndexer = componentIndexer; | |||
} | |||
@@ -42,11 +39,6 @@ public class IndexPurgeListener implements PurgeListener { | |||
@Override | |||
public void onComponentsDisabling(String projectUuid, Collection<String> disabledComponentUuids) { | |||
componentIndexer.delete(projectUuid, disabledComponentUuids); | |||
disabledComponentUuids.forEach(this::onComponentDisabling); | |||
} | |||
private void onComponentDisabling(String uuid) { | |||
testIndexer.deleteByFile(uuid); | |||
} | |||
@Override |
@@ -22,13 +22,13 @@ package org.sonar.ce.task.projectanalysis.scm; | |||
import java.util.Optional; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; | |||
import org.sonar.ce.task.projectanalysis.analysis.Branch; | |||
import org.sonar.ce.task.projectanalysis.component.Component; | |||
import org.sonar.ce.task.projectanalysis.component.MergeBranchComponentUuids; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.source.FileSourceDto; | |||
import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; | |||
import org.sonar.ce.task.projectanalysis.analysis.Branch; | |||
public class ScmInfoDbLoader { | |||
private static final Logger LOGGER = Loggers.get(ScmInfoDbLoader.class); | |||
@@ -51,7 +51,7 @@ public class ScmInfoDbLoader { | |||
LOGGER.trace("Reading SCM info from DB for file '{}'", uuid.get()); | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
FileSourceDto dto = dbClient.fileSourceDao().selectSourceByFileUuid(dbSession, uuid.get()); | |||
FileSourceDto dto = dbClient.fileSourceDao().selectByFileUuid(dbSession, uuid.get()); | |||
if (dto == null) { | |||
return Optional.empty(); | |||
} |
@@ -39,7 +39,6 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.protobuf.DbFileSources; | |||
import org.sonar.db.source.FileSourceDto; | |||
import org.sonar.db.source.FileSourceDto.Type; | |||
import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER; | |||
@@ -87,7 +86,7 @@ public class PersistFileSourcesStep implements ComputationStep { | |||
@Override | |||
public void visitProject(Component project) { | |||
this.projectUuid = project.getUuid(); | |||
session.select("org.sonar.db.source.FileSourceMapper.selectHashesForProject", ImmutableMap.of("projectUuid", projectUuid, "dataType", Type.SOURCE), | |||
session.select("org.sonar.db.source.FileSourceMapper.selectHashesForProject", ImmutableMap.of("projectUuid", projectUuid), | |||
context -> { | |||
FileSourceDto dto = (FileSourceDto) context.getResultObject(); | |||
previousFileSourcesByUuid.put(dto.getFileUuid(), dto); | |||
@@ -119,7 +118,6 @@ public class PersistFileSourcesStep implements ComputationStep { | |||
FileSourceDto dto = new FileSourceDto() | |||
.setProjectUuid(projectUuid) | |||
.setFileUuid(file.getUuid()) | |||
.setDataType(Type.SOURCE) | |||
.setBinaryData(binaryData) | |||
.setSrcHash(srcHash) | |||
.setDataHash(dataHash) |
@@ -1,249 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.ce.task.projectanalysis.step; | |||
import com.google.common.base.Joiner; | |||
import com.google.common.collect.ArrayListMultimap; | |||
import com.google.common.collect.HashBasedTable; | |||
import com.google.common.collect.ImmutableMap; | |||
import com.google.common.collect.Multimap; | |||
import com.google.common.collect.Table; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.ce.task.projectanalysis.batch.BatchReportReader; | |||
import org.sonar.ce.task.projectanalysis.component.Component; | |||
import org.sonar.ce.task.projectanalysis.component.ComponentVisitor; | |||
import org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit; | |||
import org.sonar.ce.task.projectanalysis.component.DepthTraversalTypeAwareCrawler; | |||
import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; | |||
import org.sonar.ce.task.projectanalysis.component.TypeAwareVisitorAdapter; | |||
import org.sonar.ce.task.step.ComputationStep; | |||
import org.sonar.core.util.CloseableIterator; | |||
import org.sonar.core.util.Uuids; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.protobuf.DbFileSources; | |||
import org.sonar.db.source.FileSourceDto; | |||
import org.sonar.db.source.FileSourceDto.Type; | |||
import org.sonar.scanner.protocol.output.ScannerReport; | |||
import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus; | |||
public class PersistTestsStep implements ComputationStep { | |||
private static final Logger LOG = Loggers.get(PersistTestsStep.class); | |||
private final DbClient dbClient; | |||
private final System2 system; | |||
private final BatchReportReader reportReader; | |||
private final TreeRootHolder treeRootHolder; | |||
public PersistTestsStep(DbClient dbClient, System2 system, BatchReportReader reportReader, TreeRootHolder treeRootHolder) { | |||
this.dbClient = dbClient; | |||
this.system = system; | |||
this.reportReader = reportReader; | |||
this.treeRootHolder = treeRootHolder; | |||
} | |||
@Override | |||
public void execute(ComputationStep.Context context) { | |||
try (DbSession dbSession = dbClient.openSession(true)) { | |||
TestDepthTraversalTypeAwareVisitor visitor = new TestDepthTraversalTypeAwareVisitor(dbSession); | |||
new DepthTraversalTypeAwareCrawler(visitor).visit(treeRootHolder.getRoot()); | |||
dbSession.commit(); | |||
if (visitor.hasUnprocessedCoverageDetails) { | |||
LOG.warn("Some coverage tests are not taken into account during analysis of project '{}'", visitor.getProjectKey()); | |||
} | |||
} | |||
} | |||
@Override | |||
public String getDescription() { | |||
return "Persist tests"; | |||
} | |||
private class TestDepthTraversalTypeAwareVisitor extends TypeAwareVisitorAdapter { | |||
final DbSession session; | |||
final Map<String, FileSourceDto> existingFileSourcesByUuid; | |||
final String projectUuid; | |||
final String projectKey; | |||
boolean hasUnprocessedCoverageDetails = false; | |||
public TestDepthTraversalTypeAwareVisitor(DbSession session) { | |||
super(CrawlerDepthLimit.FILE, ComponentVisitor.Order.PRE_ORDER); | |||
this.session = session; | |||
this.existingFileSourcesByUuid = new HashMap<>(); | |||
this.projectUuid = treeRootHolder.getRoot().getUuid(); | |||
this.projectKey = treeRootHolder.getRoot().getDbKey(); | |||
session.select("org.sonar.db.source.FileSourceMapper.selectHashesForProject", | |||
ImmutableMap.of("projectUuid", treeRootHolder.getRoot().getUuid(), "dataType", Type.TEST), | |||
context -> { | |||
FileSourceDto dto = (FileSourceDto) context.getResultObject(); | |||
existingFileSourcesByUuid.put(dto.getFileUuid(), dto); | |||
}); | |||
} | |||
@Override | |||
public void visitFile(Component file) { | |||
if (file.getFileAttributes().isUnitTest()) { | |||
persistTestResults(file); | |||
} | |||
} | |||
private void persistTestResults(Component component) { | |||
Multimap<String, DbFileSources.Test.Builder> testsByName = buildDbTests(component.getReportAttributes().getRef()); | |||
Table<String, String, DbFileSources.Test.CoveredFile.Builder> coveredFilesByName = loadCoverageDetails(component.getReportAttributes().getRef()); | |||
List<DbFileSources.Test> tests = addCoveredFilesToTests(testsByName, coveredFilesByName); | |||
if (checkIfThereAreUnprocessedCoverageDetails(testsByName, coveredFilesByName, component.getDbKey())) { | |||
hasUnprocessedCoverageDetails = true; | |||
} | |||
if (tests.isEmpty()) { | |||
return; | |||
} | |||
String componentUuid = getUuid(component.getReportAttributes().getRef()); | |||
FileSourceDto existingDto = existingFileSourcesByUuid.get(componentUuid); | |||
long now = system.now(); | |||
if (existingDto != null) { | |||
// update | |||
existingDto | |||
.setTestData(tests) | |||
.setUpdatedAt(now); | |||
dbClient.fileSourceDao().update(session, existingDto); | |||
} else { | |||
// insert | |||
FileSourceDto newDto = new FileSourceDto() | |||
.setTestData(tests) | |||
.setFileUuid(componentUuid) | |||
.setProjectUuid(projectUuid) | |||
.setDataType(Type.TEST) | |||
.setCreatedAt(now) | |||
.setUpdatedAt(now); | |||
dbClient.fileSourceDao().insert(session, newDto); | |||
} | |||
} | |||
private boolean checkIfThereAreUnprocessedCoverageDetails(Multimap<String, DbFileSources.Test.Builder> testsByName, | |||
Table<String, String, DbFileSources.Test.CoveredFile.Builder> coveredFilesByName, String componentKey) { | |||
Set<String> unprocessedCoverageDetailNames = new HashSet<>(coveredFilesByName.rowKeySet()); | |||
unprocessedCoverageDetailNames.removeAll(testsByName.keySet()); | |||
boolean hasUnprocessedCoverage = !unprocessedCoverageDetailNames.isEmpty(); | |||
if (hasUnprocessedCoverage) { | |||
LOG.trace("The following test coverages for file '{}' have not been taken into account: {}", componentKey, Joiner.on(", ").join(unprocessedCoverageDetailNames)); | |||
} | |||
return hasUnprocessedCoverage; | |||
} | |||
private List<DbFileSources.Test> addCoveredFilesToTests(Multimap<String, DbFileSources.Test.Builder> testsByName, | |||
Table<String, String, DbFileSources.Test.CoveredFile.Builder> coveredFilesByName) { | |||
List<DbFileSources.Test> tests = new ArrayList<>(); | |||
for (DbFileSources.Test.Builder test : testsByName.values()) { | |||
Collection<DbFileSources.Test.CoveredFile.Builder> coveredFiles = coveredFilesByName.row(test.getName()).values(); | |||
if (!coveredFiles.isEmpty()) { | |||
for (DbFileSources.Test.CoveredFile.Builder coveredFile : coveredFiles) { | |||
test.addCoveredFile(coveredFile); | |||
} | |||
} | |||
tests.add(test.build()); | |||
} | |||
return tests; | |||
} | |||
private Multimap<String, DbFileSources.Test.Builder> buildDbTests(int componentRed) { | |||
Multimap<String, DbFileSources.Test.Builder> tests = ArrayListMultimap.create(); | |||
try (CloseableIterator<ScannerReport.Test> testIterator = reportReader.readTests(componentRed)) { | |||
while (testIterator.hasNext()) { | |||
ScannerReport.Test batchTest = testIterator.next(); | |||
DbFileSources.Test.Builder dbTest = DbFileSources.Test.newBuilder(); | |||
dbTest.setUuid(Uuids.create()); | |||
dbTest.setName(batchTest.getName()); | |||
if (!batchTest.getStacktrace().isEmpty()) { | |||
dbTest.setStacktrace(batchTest.getStacktrace()); | |||
} | |||
if (batchTest.getStatus() != TestStatus.UNSET) { | |||
dbTest.setStatus(DbFileSources.Test.TestStatus.valueOf(batchTest.getStatus().name())); | |||
} | |||
if (!batchTest.getMsg().isEmpty()) { | |||
dbTest.setMsg(batchTest.getMsg()); | |||
} | |||
dbTest.setExecutionTimeMs(batchTest.getDurationInMs()); | |||
tests.put(dbTest.getName(), dbTest); | |||
} | |||
} | |||
return tests; | |||
} | |||
/** | |||
* returns a Table of (test name, main file uuid, covered file) | |||
*/ | |||
private Table<String, String, DbFileSources.Test.CoveredFile.Builder> loadCoverageDetails(int testFileRef) { | |||
Table<String, String, DbFileSources.Test.CoveredFile.Builder> nameToCoveredFiles = HashBasedTable.create(); | |||
try (CloseableIterator<ScannerReport.CoverageDetail> coverageIterator = reportReader.readCoverageDetails(testFileRef)) { | |||
while (coverageIterator.hasNext()) { | |||
ScannerReport.CoverageDetail batchCoverageDetail = coverageIterator.next(); | |||
String testName = batchCoverageDetail.getTestName(); | |||
for (ScannerReport.CoverageDetail.CoveredFile batchCoveredFile : batchCoverageDetail.getCoveredFileList()) { | |||
loadCoverageFile(batchCoveredFile, testName, nameToCoveredFiles); | |||
} | |||
} | |||
} | |||
return nameToCoveredFiles; | |||
} | |||
private void loadCoverageFile(ScannerReport.CoverageDetail.CoveredFile batchCoveredFile, String testName, Table<String, String, | |||
DbFileSources.Test.CoveredFile.Builder> nameToCoveredFiles) { | |||
String mainFileUuid = getUuid(batchCoveredFile.getFileRef()); | |||
DbFileSources.Test.CoveredFile.Builder existingDbCoveredFile = nameToCoveredFiles.get(testName, mainFileUuid); | |||
List<Integer> batchCoveredLines = batchCoveredFile.getCoveredLineList(); | |||
if (existingDbCoveredFile == null) { | |||
DbFileSources.Test.CoveredFile.Builder dbCoveredFile = DbFileSources.Test.CoveredFile.newBuilder() | |||
.setFileUuid(getUuid(batchCoveredFile.getFileRef())) | |||
.addAllCoveredLine(batchCoveredLines); | |||
nameToCoveredFiles.put(testName, mainFileUuid, dbCoveredFile); | |||
} else { | |||
List<Integer> remainingBatchCoveredLines = new ArrayList<>(batchCoveredLines); | |||
remainingBatchCoveredLines.removeAll(existingDbCoveredFile.getCoveredLineList()); | |||
existingDbCoveredFile.addAllCoveredLine(batchCoveredLines); | |||
} | |||
} | |||
private String getUuid(int fileRef) { | |||
return treeRootHolder.getComponentByRef(fileRef).getUuid(); | |||
} | |||
public String getProjectKey() { | |||
return projectKey; | |||
} | |||
} | |||
} |
@@ -99,7 +99,6 @@ public class ReportComputationSteps extends AbstractComputationSteps { | |||
PersistProjectLinksStep.class, | |||
PersistEventsStep.class, | |||
PersistFileSourcesStep.class, | |||
PersistTestsStep.class, | |||
PersistCrossProjectDuplicationIndexStep.class, | |||
EnableAnalysisStep.class, | |||
@@ -47,10 +47,6 @@ public class BatchReportReaderImplTest { | |||
private static final ScannerReport.SyntaxHighlightingRule SYNTAX_HIGHLIGHTING_2 = ScannerReport.SyntaxHighlightingRule.newBuilder().build(); | |||
private static final ScannerReport.LineCoverage COVERAGE_1 = ScannerReport.LineCoverage.newBuilder().build(); | |||
private static final ScannerReport.LineCoverage COVERAGE_2 = ScannerReport.LineCoverage.newBuilder().build(); | |||
private static final ScannerReport.Test TEST_1 = ScannerReport.Test.newBuilder().setName("1").build(); | |||
private static final ScannerReport.Test TEST_2 = ScannerReport.Test.newBuilder().setName("2").build(); | |||
private static final ScannerReport.CoverageDetail COVERAGE_DETAIL_1 = ScannerReport.CoverageDetail.newBuilder().setTestName("1").build(); | |||
private static final ScannerReport.CoverageDetail COVERAGE_DETAIL_2 = ScannerReport.CoverageDetail.newBuilder().setTestName("2").build(); | |||
@Rule | |||
public JUnitTempFolder tempFolder = new JUnitTempFolder(); | |||
@@ -288,34 +284,6 @@ public class BatchReportReaderImplTest { | |||
res.close(); | |||
} | |||
@Test | |||
public void readTests_returns_empty_CloseableIterator_when_file_does_not_exist() { | |||
assertThat(underTest.readTests(COMPONENT_REF)).isEmpty(); | |||
} | |||
@Test | |||
public void verify_readTests() { | |||
writer.writeTests(COMPONENT_REF, of(TEST_1, TEST_2)); | |||
CloseableIterator<ScannerReport.Test> res = underTest.readTests(COMPONENT_REF); | |||
assertThat(res).containsExactly(TEST_1, TEST_2); | |||
res.close(); | |||
} | |||
@Test | |||
public void readCoverageDetails_returns_empty_CloseableIterator_when_file_does_not_exist() { | |||
assertThat(underTest.readCoverageDetails(COMPONENT_REF)).isEmpty(); | |||
} | |||
@Test | |||
public void verify_readCoverageDetails() { | |||
writer.writeCoverageDetails(COMPONENT_REF, of(COVERAGE_DETAIL_1, COVERAGE_DETAIL_2)); | |||
CloseableIterator<ScannerReport.CoverageDetail> res = underTest.readCoverageDetails(COMPONENT_REF); | |||
assertThat(res).containsExactly(COVERAGE_DETAIL_1, COVERAGE_DETAIL_2); | |||
res.close(); | |||
} | |||
@Test | |||
public void verify_readAnalysisWarnings() { | |||
ScannerReport.AnalysisWarning warning1 = ScannerReport.AnalysisWarning.newBuilder().setText("warning 1").build(); |
@@ -54,8 +54,6 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader { | |||
private Map<Integer, List<ScannerReport.SyntaxHighlightingRule>> syntaxHighlightings = new HashMap<>(); | |||
private Map<Integer, List<ScannerReport.LineCoverage>> coverages = new HashMap<>(); | |||
private Map<Integer, List<String>> fileSources = new HashMap<>(); | |||
private Map<Integer, List<ScannerReport.Test>> tests = new HashMap<>(); | |||
private Map<Integer, List<ScannerReport.CoverageDetail>> coverageDetails = new HashMap<>(); | |||
private Map<Integer, List<ScannerReport.LineSgnificantCode>> significantCode = new HashMap<>(); | |||
private Map<Integer, ScannerReport.ChangedLines> changedLines = new HashMap<>(); | |||
private List<ScannerReport.AnalysisWarning> analysisWarnings = Collections.emptyList(); | |||
@@ -87,8 +85,6 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader { | |||
this.syntaxHighlightings.clear(); | |||
this.coverages.clear(); | |||
this.fileSources.clear(); | |||
this.tests.clear(); | |||
this.coverageDetails.clear(); | |||
this.significantCode.clear(); | |||
} | |||
@@ -308,24 +304,4 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader { | |||
return this; | |||
} | |||
@Override | |||
public CloseableIterator<ScannerReport.Test> readTests(int testFileRef) { | |||
return closeableIterator(this.tests.get(testFileRef)); | |||
} | |||
public BatchReportReaderRule putTests(int testFileRed, List<ScannerReport.Test> tests) { | |||
this.tests.put(testFileRed, tests); | |||
return this; | |||
} | |||
@Override | |||
public CloseableIterator<ScannerReport.CoverageDetail> readCoverageDetails(int testFileRef) { | |||
return closeableIterator(this.coverageDetails.get(testFileRef)); | |||
} | |||
public BatchReportReaderRule putCoverageDetails(int testFileRef, List<ScannerReport.CoverageDetail> coverageDetails) { | |||
this.coverageDetails.put(testFileRef, coverageDetails); | |||
return this; | |||
} | |||
} |
@@ -19,9 +19,6 @@ | |||
*/ | |||
package org.sonar.ce.task.projectanalysis.dbmigration; | |||
import com.tngtech.java.junit.dataprovider.DataProvider; | |||
import com.tngtech.java.junit.dataprovider.DataProviderRunner; | |||
import com.tngtech.java.junit.dataprovider.UseDataProvider; | |||
import java.sql.SQLException; | |||
import java.util.Optional; | |||
import java.util.Random; | |||
@@ -31,11 +28,9 @@ import javax.annotation.Nullable; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.junit.runner.RunWith; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.ce.task.CeTask; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.source.FileSourceDto; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -43,7 +38,6 @@ import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.db.source.FileSourceDto.LINE_COUNT_NOT_POPULATED; | |||
@RunWith(DataProviderRunner.class) | |||
public class PopulateFileSourceLineCountTest { | |||
@Rule | |||
@@ -65,13 +59,12 @@ public class PopulateFileSourceLineCountTest { | |||
} | |||
@Test | |||
@UseDataProvider("anyType") | |||
public void execute_populates_line_count_of_any_type(String type) throws SQLException { | |||
public void execute_populates_line_count_of_any_type() throws SQLException { | |||
String projectUuid = randomAlphanumeric(4); | |||
String fileUuid = randomAlphanumeric(5); | |||
when(ceTask.getComponent()).thenReturn(newComponent(projectUuid)); | |||
int lineCount = 1 + random.nextInt(15); | |||
insertUnpopulatedFileSource(projectUuid, fileUuid, type, lineCount); | |||
insertUnpopulatedFileSource(projectUuid, fileUuid, lineCount); | |||
assertThat(getLineCountByFileUuid(fileUuid)).isEqualTo(LINE_COUNT_NOT_POPULATED); | |||
underTest.execute(); | |||
@@ -80,8 +73,7 @@ public class PopulateFileSourceLineCountTest { | |||
} | |||
@Test | |||
@UseDataProvider("anyType") | |||
public void execute_changes_only_file_source_with_LINE_COUNT_NOT_POPULATED_value(String type) throws SQLException { | |||
public void execute_changes_only_file_source_with_LINE_COUNT_NOT_POPULATED_value() throws SQLException { | |||
String projectUuid = randomAlphanumeric(4); | |||
String fileUuid1 = randomAlphanumeric(5); | |||
String fileUuid2 = randomAlphanumeric(6); | |||
@@ -91,9 +83,9 @@ public class PopulateFileSourceLineCountTest { | |||
int lineCountFile3 = 150 + random.nextInt(15); | |||
when(ceTask.getComponent()).thenReturn(newComponent(projectUuid)); | |||
insertPopulatedFileSource(projectUuid, fileUuid1, type, lineCountFile1); | |||
int badLineCountFile2 = insertInconsistentPopulatedFileSource(projectUuid, fileUuid2, type, lineCountFile2); | |||
insertUnpopulatedFileSource(projectUuid, fileUuid3, type, lineCountFile3); | |||
insertPopulatedFileSource(projectUuid, fileUuid1, lineCountFile1); | |||
int badLineCountFile2 = insertInconsistentPopulatedFileSource(projectUuid, fileUuid2, lineCountFile2); | |||
insertUnpopulatedFileSource(projectUuid, fileUuid3, lineCountFile3); | |||
assertThat(getLineCountByFileUuid(fileUuid1)).isEqualTo(lineCountFile1); | |||
assertThat(getLineCountByFileUuid(fileUuid2)).isEqualTo(badLineCountFile2); | |||
assertThat(getLineCountByFileUuid(fileUuid3)).isEqualTo(LINE_COUNT_NOT_POPULATED); | |||
@@ -106,8 +98,7 @@ public class PopulateFileSourceLineCountTest { | |||
} | |||
@Test | |||
@UseDataProvider("anyType") | |||
public void execute_changes_only_file_source_of_CeTask_component_uuid(String type) throws SQLException { | |||
public void execute_changes_only_file_source_of_CeTask_component_uuid() throws SQLException { | |||
String projectUuid1 = randomAlphanumeric(4); | |||
String projectUuid2 = randomAlphanumeric(5); | |||
String fileUuid1 = randomAlphanumeric(6); | |||
@@ -116,8 +107,8 @@ public class PopulateFileSourceLineCountTest { | |||
int lineCountFile2 = 30 + random.nextInt(15); | |||
when(ceTask.getComponent()).thenReturn(newComponent(projectUuid1)); | |||
insertUnpopulatedFileSource(projectUuid1, fileUuid1, type, lineCountFile1); | |||
insertUnpopulatedFileSource(projectUuid2, fileUuid2, type, lineCountFile2); | |||
insertUnpopulatedFileSource(projectUuid1, fileUuid1, lineCountFile1); | |||
insertUnpopulatedFileSource(projectUuid2, fileUuid2, lineCountFile2); | |||
underTest.execute(); | |||
@@ -126,13 +117,12 @@ public class PopulateFileSourceLineCountTest { | |||
} | |||
@Test | |||
@UseDataProvider("anyType") | |||
public void execute_set_line_count_to_zero_when_file_source_has_no_line_hashes(String type) throws SQLException { | |||
public void execute_set_line_count_to_zero_when_file_source_has_no_line_hashes() throws SQLException { | |||
String projectUuid = randomAlphanumeric(4); | |||
String fileUuid1 = randomAlphanumeric(5); | |||
when(ceTask.getComponent()).thenReturn(newComponent(projectUuid)); | |||
insertFileSource(projectUuid, fileUuid1, type, null, LINE_COUNT_NOT_POPULATED); | |||
insertFileSource(projectUuid, fileUuid1, null, LINE_COUNT_NOT_POPULATED); | |||
underTest.execute(); | |||
@@ -140,52 +130,41 @@ public class PopulateFileSourceLineCountTest { | |||
} | |||
@Test | |||
@UseDataProvider("anyType") | |||
public void execute_set_line_count_to_1_when_file_source_has_empty_line_hashes(String type) throws SQLException { | |||
public void execute_set_line_count_to_1_when_file_source_has_empty_line_hashes() throws SQLException { | |||
String projectUuid = randomAlphanumeric(4); | |||
String fileUuid1 = randomAlphanumeric(5); | |||
when(ceTask.getComponent()).thenReturn(newComponent(projectUuid)); | |||
insertFileSource(projectUuid, fileUuid1, type, "", LINE_COUNT_NOT_POPULATED); | |||
insertFileSource(projectUuid, fileUuid1, "", LINE_COUNT_NOT_POPULATED); | |||
underTest.execute(); | |||
assertThat(getLineCountByFileUuid(fileUuid1)).isEqualTo(1); | |||
} | |||
@DataProvider | |||
public static Object[][] anyType() { | |||
return new Object[][] { | |||
{FileSourceDto.Type.SOURCE}, | |||
{FileSourceDto.Type.TEST}, | |||
{null}, | |||
{randomAlphanumeric(3)}, | |||
}; | |||
} | |||
private int getLineCountByFileUuid(String fileUuid) { | |||
Long res = (Long) db.selectFirst("select line_count as \"LINE_COUNT\" from file_sources where file_uuid = '" + fileUuid + "'") | |||
.get("LINE_COUNT"); | |||
return res.intValue(); | |||
} | |||
private void insertUnpopulatedFileSource(String projectUuid, String fileUuid, @Nullable String dataType, int numberOfHashes) { | |||
private void insertUnpopulatedFileSource(String projectUuid, String fileUuid, int numberOfHashes) { | |||
String lineHashes = generateLineHashes(numberOfHashes); | |||
insertFileSource(projectUuid, fileUuid, dataType, lineHashes, LINE_COUNT_NOT_POPULATED); | |||
insertFileSource(projectUuid, fileUuid, lineHashes, LINE_COUNT_NOT_POPULATED); | |||
} | |||
private void insertPopulatedFileSource(String projectUuid, String fileUuid, @Nullable String dataType, int lineCount) { | |||
private void insertPopulatedFileSource(String projectUuid, String fileUuid, int lineCount) { | |||
String lineHashes = generateLineHashes(lineCount); | |||
insertFileSource(projectUuid, fileUuid, dataType, lineHashes, lineCount); | |||
insertFileSource(projectUuid, fileUuid, lineHashes, lineCount); | |||
} | |||
private int insertInconsistentPopulatedFileSource(String projectUuid, String fileUuid, @Nullable String dataType, int lineCount) { | |||
private int insertInconsistentPopulatedFileSource(String projectUuid, String fileUuid, int lineCount) { | |||
String lineHashes = generateLineHashes(lineCount); | |||
int badLineCount = lineCount + random.nextInt(6); | |||
insertFileSource(projectUuid, fileUuid, dataType, lineHashes, badLineCount); | |||
insertFileSource(projectUuid, fileUuid, lineHashes, badLineCount); | |||
return badLineCount; | |||
} | |||
@@ -196,13 +175,12 @@ public class PopulateFileSourceLineCountTest { | |||
.collect(Collectors.joining("\n")); | |||
} | |||
private void insertFileSource(String projectUuid, String fileUuid, @Nullable String dataType, @Nullable String lineHashes, int lineCount) { | |||
private void insertFileSource(String projectUuid, String fileUuid, @Nullable String lineHashes, int lineCount) { | |||
db.executeInsert( | |||
"FILE_SOURCES", | |||
"PROJECT_UUID", projectUuid, | |||
"FILE_UUID", fileUuid, | |||
"LINE_HASHES", lineHashes, | |||
"DATA_TYPE", dataType, | |||
"LINE_COUNT", lineCount, | |||
"CREATED_AT", 1_222_333L, | |||
"UPDATED_AT", 1_222_333L); |
@@ -600,8 +600,7 @@ public class FileMoveDetectionStepTest { | |||
FileSourceDto fileSourceDto = new FileSourceDto() | |||
.setFileUuid(file.uuid()) | |||
.setProjectUuid(file.projectUuid()) | |||
.setLineHashes(linesHashesComputer.getLineHashes()) | |||
.setDataType(FileSourceDto.Type.SOURCE); | |||
.setLineHashes(linesHashesComputer.getLineHashes()); | |||
dbTester.getDbClient().fileSourceDao().insert(dbTester.getSession(), fileSourceDto); | |||
dbTester.commit(); | |||
return fileSourceDto; |
@@ -23,7 +23,6 @@ import java.util.List; | |||
import org.junit.Test; | |||
import org.sonar.server.component.index.ComponentIndexer; | |||
import org.sonar.server.issue.index.IssueIndexer; | |||
import org.sonar.server.test.index.TestIndexer; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.singletonList; | |||
@@ -32,11 +31,10 @@ import static org.mockito.Mockito.verify; | |||
public class IndexPurgeListenerTest { | |||
private TestIndexer testIndexer = mock(TestIndexer.class); | |||
private IssueIndexer issueIndexer = mock(IssueIndexer.class); | |||
private ComponentIndexer componentIndexer = mock(ComponentIndexer.class); | |||
private IndexPurgeListener underTest = new IndexPurgeListener(testIndexer, issueIndexer, componentIndexer); | |||
private IndexPurgeListener underTest = new IndexPurgeListener(issueIndexer, componentIndexer); | |||
@Test | |||
public void test_onComponentDisabling() { | |||
@@ -45,7 +43,6 @@ public class IndexPurgeListenerTest { | |||
List<String> uuids = singletonList(uuid); | |||
underTest.onComponentsDisabling(projectUuid, uuids); | |||
verify(testIndexer).deleteByFile(uuid); | |||
verify(componentIndexer).delete(projectUuid, uuids); | |||
} | |||
@@ -43,7 +43,6 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.protobuf.DbFileSources; | |||
import org.sonar.db.source.FileSourceDto; | |||
import org.sonar.db.source.FileSourceDto.Type; | |||
import org.sonar.db.source.LineHashVersion; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -107,7 +106,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getProjectUuid()).isEqualTo(PROJECT_UUID); | |||
assertThat(fileSourceDto.getFileUuid()).isEqualTo(FILE1_UUID); | |||
assertThat(fileSourceDto.getBinaryData()).isNotEmpty(); | |||
@@ -135,7 +134,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getLineHashes()).containsExactly("137f72c3708c6bd0de00a0e5a69c699b", "e6251bcf1a7dc3ba5e7933e325bbe605"); | |||
assertThat(fileSourceDto.getSrcHash()).isEqualTo("ee5a58024a155466b43bc559d953e018"); | |||
verify(fileSourceDataWarnings).commitWarnings(); | |||
@@ -156,7 +155,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData); | |||
verify(fileSourceDataWarnings).commitWarnings(); | |||
} | |||
@@ -179,7 +178,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData); | |||
assertThat(fileSourceDto.getRevision()).isNull(); | |||
verify(fileSourceDataWarnings).commitWarnings(); | |||
@@ -204,7 +203,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
DbFileSources.Data data = fileSourceDto.getSourceData(); | |||
@@ -236,7 +235,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
DbFileSources.Data data = fileSourceDto.getSourceData(); | |||
assertThat(data).isEqualTo(dbData); | |||
assertThat(data.getLinesList()).hasSize(1); | |||
@@ -260,7 +259,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData); | |||
verify(fileSourceDataWarnings).commitWarnings(); | |||
} | |||
@@ -277,7 +276,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData); | |||
verify(fileSourceDataWarnings).commitWarnings(); | |||
} | |||
@@ -289,7 +288,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getRevision()).isEqualTo("rev-1"); | |||
verify(fileSourceDataWarnings).commitWarnings(); | |||
} | |||
@@ -300,7 +299,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getRevision()).isNull(); | |||
verify(fileSourceDataWarnings).commitWarnings(); | |||
} | |||
@@ -316,7 +315,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getSrcHash()).isEqualTo("sourceHash"); | |||
assertThat(fileSourceDto.getLineHashes()).isEqualTo(Collections.singletonList("lineHash")); | |||
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(PAST); | |||
@@ -331,7 +330,6 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
dbClient.fileSourceDao().insert(dbTester.getSession(), new FileSourceDto() | |||
.setProjectUuid(PROJECT_UUID) | |||
.setFileUuid(FILE1_UUID) | |||
.setDataType(Type.SOURCE) | |||
.setSrcHash("5b4bd9815cdb17b8ceae19eb1810c34c") | |||
.setLineHashes(Collections.singletonList("6438c669e0d0de98e6929c2cc0fac474")) | |||
.setDataHash("6cad150e3d065976c230cddc5a09efaa") | |||
@@ -362,7 +360,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(past); | |||
assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(NOW); | |||
assertThat(fileSourceDto.getRevision()).isEqualTo("rev-1"); | |||
@@ -380,7 +378,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(PAST); | |||
assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(NOW); | |||
assertThat(fileSourceDto.getSrcHash()).isEqualTo("newSourceHash"); | |||
@@ -405,7 +403,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID); | |||
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectByFileUuid(session, FILE1_UUID); | |||
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(PAST); | |||
assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(NOW); | |||
assertThat(fileSourceDto.getRevision()).isEqualTo("revision"); | |||
@@ -425,7 +423,6 @@ public class PersistFileSourcesStepTest extends BaseStepTest { | |||
FileSourceDto dto = new FileSourceDto() | |||
.setProjectUuid(PROJECT_UUID) | |||
.setFileUuid(FILE1_UUID) | |||
.setDataType(Type.SOURCE) | |||
.setSrcHash("sourceHash") | |||
.setLineHashes(Collections.singletonList("lineHash")) | |||
.setDataHash(dataHash) |
@@ -1,280 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.ce.task.projectanalysis.step; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.utils.log.LogTester; | |||
import org.sonar.api.utils.log.LoggerLevel; | |||
import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule; | |||
import org.sonar.ce.task.projectanalysis.component.Component; | |||
import org.sonar.ce.task.projectanalysis.component.FileAttributes; | |||
import org.sonar.ce.task.projectanalysis.component.ReportComponent; | |||
import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule; | |||
import org.sonar.ce.task.step.ComputationStep; | |||
import org.sonar.ce.task.step.TestComputationStepContext; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.protobuf.DbFileSources; | |||
import org.sonar.db.source.FileSourceDto; | |||
import org.sonar.scanner.protocol.output.ScannerReport; | |||
import org.sonar.scanner.protocol.output.ScannerReport.CoverageDetail; | |||
import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.tuple; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class PersistTestsStepTest extends BaseStepTest { | |||
private static final String PROJECT_UUID = "PROJECT"; | |||
private static final String PROJECT_KEY = "PROJECT_KEY"; | |||
private static final int TEST_FILE_REF_1 = 3; | |||
private static final int TEST_FILE_REF_2 = 4; | |||
private static final int MAIN_FILE_REF_1 = 5; | |||
private static final int MAIN_FILE_REF_2 = 6; | |||
private static final String TEST_FILE_UUID_1 = "TEST-FILE-1"; | |||
private static final String TEST_FILE_UUID_2 = "TEST-FILE-2"; | |||
private static final String MAIN_FILE_UUID_1 = "MAIN-FILE-1"; | |||
private static final String MAIN_FILE_UUID_2 = "MAIN-FILE-2"; | |||
@Rule | |||
public DbTester db = DbTester.create(System2.INSTANCE); | |||
@Rule | |||
public BatchReportReaderRule reportReader = new BatchReportReaderRule(); | |||
@Rule | |||
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); | |||
@Rule | |||
public LogTester log = new LogTester(); | |||
DbClient dbClient = db.getDbClient(); | |||
Component root; | |||
PersistTestsStep underTest; | |||
long now = 123456789L; | |||
@Before | |||
public void setup() { | |||
System2 system2 = mock(System2.class); | |||
when(system2.now()).thenReturn(now); | |||
underTest = new PersistTestsStep(dbClient, system2, reportReader, treeRootHolder); | |||
root = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_UUID).setKey(PROJECT_KEY).addChildren( | |||
ReportComponent.builder(Component.Type.FILE, 3).setUuid(TEST_FILE_UUID_1).setKey("TEST_FILE1_KEY").setFileAttributes(new FileAttributes(true, null, 1)).build(), | |||
ReportComponent.builder(Component.Type.FILE, 4).setUuid(TEST_FILE_UUID_2).setKey("TEST_FILE2_KEY").setFileAttributes(new FileAttributes(true, null, 1)).build(), | |||
ReportComponent.builder(Component.Type.FILE, 5).setUuid(MAIN_FILE_UUID_1).setKey("MAIN_FILE1_KEY").build(), | |||
ReportComponent.builder(Component.Type.FILE, 6).setUuid(MAIN_FILE_UUID_2).setKey("MAIN_FILE2_KEY").build()) | |||
.build(); | |||
treeRootHolder.setRoot(root); | |||
} | |||
@Override | |||
protected ComputationStep step() { | |||
return underTest; | |||
} | |||
@Test | |||
public void no_test_in_database_and_batch_report() { | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1)).isNull(); | |||
assertThat(log.logs()).isEmpty(); | |||
} | |||
@Test | |||
public void insert_several_tests_in_a_report() { | |||
List<ScannerReport.Test> batchTests = Arrays.asList( | |||
newTest(1), newTest(2)); | |||
reportReader.putTests(TEST_FILE_REF_1, batchTests); | |||
List<CoverageDetail> coverageDetails = Arrays.asList( | |||
newCoverageDetail(1, MAIN_FILE_REF_1)); | |||
reportReader.putCoverageDetails(TEST_FILE_REF_1, coverageDetails); | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(db.countRowsOfTable("file_sources")).isEqualTo(1); | |||
FileSourceDto dto = dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1); | |||
assertThat(dto.getCreatedAt()).isEqualTo(now); | |||
assertThat(dto.getUpdatedAt()).isEqualTo(now); | |||
assertThat(dto.getProjectUuid()).isEqualTo(PROJECT_UUID); | |||
assertThat(dto.getFileUuid()).isEqualTo(TEST_FILE_UUID_1); | |||
assertThat(dto.getTestData()).hasSize(2); | |||
assertThat(dto.getTestData()).extracting("name", "coveredFileCount").containsOnly( | |||
tuple("name#1", 1), | |||
tuple("name#2", 0)); | |||
assertThat(log.logs()).isEmpty(); | |||
} | |||
@Test | |||
public void insert_all_data_of_a_test() { | |||
reportReader.putTests(TEST_FILE_REF_1, Arrays.asList(newTest(1))); | |||
reportReader.putCoverageDetails(TEST_FILE_REF_1, Arrays.asList(newCoverageDetail(1, MAIN_FILE_REF_1))); | |||
underTest.execute(new TestComputationStepContext()); | |||
FileSourceDto dto = dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1); | |||
assertThat(dto.getCreatedAt()).isEqualTo(now); | |||
assertThat(dto.getUpdatedAt()).isEqualTo(now); | |||
assertThat(dto.getProjectUuid()).isEqualTo(PROJECT_UUID); | |||
assertThat(dto.getFileUuid()).isEqualTo(TEST_FILE_UUID_1); | |||
assertThat(dto.getTestData()).hasSize(1); | |||
DbFileSources.Test test1 = dto.getTestData().get(0); | |||
assertThat(test1.getUuid()).isNotEmpty(); | |||
assertThat(test1.getName()).isEqualTo("name#1"); | |||
assertThat(test1.getMsg()).isEqualTo("message#1"); | |||
assertThat(test1.getStacktrace()).isEqualTo("stacktrace#1"); | |||
assertThat(test1.getStatus()).isEqualTo(DbFileSources.Test.TestStatus.FAILURE); | |||
assertThat(test1.getExecutionTimeMs()).isEqualTo(1_000); | |||
assertThat(test1.getCoveredFileCount()).isEqualTo(1); | |||
assertThat(test1.getCoveredFile(0).getCoveredLineList()).containsOnly(1, 2, 3); | |||
assertThat(test1.getCoveredFile(0).getFileUuid()).isEqualTo(MAIN_FILE_UUID_1); | |||
} | |||
@Test | |||
public void insert_tests_without_coverage_details() { | |||
List<ScannerReport.Test> batchTests = Arrays.asList(newTest(1)); | |||
reportReader.putTests(TEST_FILE_REF_1, batchTests); | |||
underTest.execute(new TestComputationStepContext()); | |||
FileSourceDto dto = dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1); | |||
assertThat(dto.getFileUuid()).isEqualTo(TEST_FILE_UUID_1); | |||
List<DbFileSources.Test> tests = dto.getTestData(); | |||
assertThat(tests).hasSize(1); | |||
assertThat(tests.get(0).getCoveredFileList()).isEmpty(); | |||
assertThat(tests.get(0).getMsg()).isEqualTo("message#1"); | |||
} | |||
@Test | |||
public void insert_coverage_details_not_taken_into_account() { | |||
List<ScannerReport.Test> batchTests = Arrays.asList(newTest(1)); | |||
reportReader.putTests(TEST_FILE_REF_1, batchTests); | |||
List<CoverageDetail> coverageDetails = Arrays.asList(newCoverageDetail(1, MAIN_FILE_REF_1), newCoverageDetail(2, MAIN_FILE_REF_2)); | |||
reportReader.putCoverageDetails(TEST_FILE_REF_1, coverageDetails); | |||
reportReader.putCoverageDetails(TEST_FILE_REF_2, coverageDetails); | |||
underTest.execute(new TestComputationStepContext()); | |||
assertThat(log.logs(LoggerLevel.WARN)).hasSize(1); | |||
assertThat(log.logs(LoggerLevel.WARN).get(0)).isEqualTo("Some coverage tests are not taken into account during analysis of project 'PROJECT_KEY'"); | |||
assertThat(log.logs(LoggerLevel.TRACE)).hasSize(2); | |||
assertThat(log.logs(LoggerLevel.TRACE).get(0)).isEqualTo("The following test coverages for file 'TEST_FILE1_KEY' have not been taken into account: name#2"); | |||
assertThat(log.logs(LoggerLevel.TRACE).get(1)).startsWith("The following test coverages for file 'TEST_FILE2_KEY' have not been taken into account: "); | |||
assertThat(log.logs(LoggerLevel.TRACE).get(1)).contains("name#1", "name#2"); | |||
} | |||
@Test | |||
public void aggregate_coverage_details() { | |||
reportReader.putTests(TEST_FILE_REF_1, Arrays.asList(newTest(1))); | |||
reportReader.putCoverageDetails(TEST_FILE_REF_1, Arrays.asList( | |||
newCoverageDetailWithLines(1, MAIN_FILE_REF_1, 1, 3), | |||
newCoverageDetailWithLines(1, MAIN_FILE_REF_1, 2, 4))); | |||
underTest.execute(new TestComputationStepContext()); | |||
FileSourceDto dto = dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1); | |||
List<Integer> coveredLines = dto.getTestData().get(0).getCoveredFile(0).getCoveredLineList(); | |||
assertThat(coveredLines).containsOnly(1, 2, 3, 4); | |||
} | |||
@Test | |||
public void update_existing_test() { | |||
// ARRANGE | |||
dbClient.fileSourceDao().insert(db.getSession(), new FileSourceDto() | |||
.setProjectUuid(PROJECT_UUID) | |||
.setFileUuid(TEST_FILE_UUID_1) | |||
.setTestData(Arrays.asList(DbFileSources.Test.newBuilder() | |||
.setUuid("test-uuid-1") | |||
.setName("name#1") | |||
.setStatus(DbFileSources.Test.TestStatus.ERROR) | |||
.setStacktrace("old-stacktrace#1") | |||
.setMsg("old-message#1") | |||
.setExecutionTimeMs(987_654_321L) | |||
.build())) | |||
.setCreatedAt(100_000) | |||
.setUpdatedAt(100_000)); | |||
db.getSession().commit(); | |||
assertThat(dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1)).isNotNull(); | |||
ScannerReport.Test newBatchTest = newTest(1); | |||
reportReader.putTests(TEST_FILE_REF_1, Arrays.asList(newBatchTest)); | |||
CoverageDetail newCoverageDetail = newCoverageDetail(1, MAIN_FILE_REF_1); | |||
reportReader.putCoverageDetails(TEST_FILE_REF_1, Arrays.asList(newCoverageDetail)); | |||
// ACT | |||
underTest.execute(new TestComputationStepContext()); | |||
// ASSERT | |||
FileSourceDto dto = dbClient.fileSourceDao().selectTestByFileUuid(db.getSession(), TEST_FILE_UUID_1); | |||
assertThat(dto.getCreatedAt()).isEqualTo(100_000); | |||
assertThat(dto.getUpdatedAt()).isEqualTo(now); | |||
assertThat(dto.getTestData()).hasSize(1); | |||
DbFileSources.Test test = dto.getTestData().get(0); | |||
assertThat(test.getUuid()).isNotEqualTo("test-uuid-1"); | |||
assertThat(test.getName()).isEqualTo("name#1"); | |||
assertThat(test.getStatus()).isEqualTo(DbFileSources.Test.TestStatus.valueOf(newBatchTest.getStatus().name())); | |||
assertThat(test.getMsg()).isEqualTo(newBatchTest.getMsg()); | |||
assertThat(test.getStacktrace()).isEqualTo(newBatchTest.getStacktrace()); | |||
assertThat(test.getExecutionTimeMs()).isEqualTo(newBatchTest.getDurationInMs()); | |||
assertThat(test.getCoveredFileCount()).isEqualTo(1); | |||
assertThat(test.getCoveredFile(0).getCoveredLineList()).containsOnly(1, 2, 3); | |||
assertThat(test.getCoveredFile(0).getFileUuid()).isEqualTo(MAIN_FILE_UUID_1); | |||
} | |||
private ScannerReport.Test newTest(int id) { | |||
return ScannerReport.Test.newBuilder() | |||
.setStatus(TestStatus.FAILURE) | |||
.setName("name#" + id) | |||
.setStacktrace("stacktrace#" + id) | |||
.setMsg("message#" + id) | |||
.setDurationInMs(1_000) | |||
.build(); | |||
} | |||
private ScannerReport.CoverageDetail newCoverageDetail(int id, int covered_file_ref) { | |||
return newCoverageDetailWithLines(id, covered_file_ref, 1, 2, 3); | |||
} | |||
private ScannerReport.CoverageDetail newCoverageDetailWithLines(int id, int covered_file_ref, Integer... lines) { | |||
return CoverageDetail.newBuilder() | |||
.setTestName("name#" + id) | |||
.addCoveredFile(CoverageDetail.CoveredFile.newBuilder() | |||
.addAllCoveredLine(Arrays.asList(lines)) | |||
.setFileRef(covered_file_ref) | |||
.build()) | |||
.build(); | |||
} | |||
} |
@@ -149,7 +149,6 @@ import org.sonar.server.rule.index.RuleIndexer; | |||
import org.sonar.server.setting.DatabaseSettingLoader; | |||
import org.sonar.server.setting.DatabaseSettingsEnabler; | |||
import org.sonar.server.setting.ThreadLocalSettings; | |||
import org.sonar.server.test.index.TestIndexer; | |||
import org.sonar.server.user.index.UserIndex; | |||
import org.sonar.server.user.index.UserIndexer; | |||
import org.sonar.server.util.OkHttpClientProvider; | |||
@@ -425,9 +424,6 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer { | |||
EmailNotificationChannel.class, | |||
ReportAnalysisFailureNotificationModule.class, | |||
// Tests | |||
TestIndexer.class, | |||
// System | |||
ServerLogging.class, | |||
@@ -97,7 +97,7 @@ public class ComputeEngineContainerImplTest { | |||
assertThat(picoContainer.getComponentAdapters()) | |||
.hasSize( | |||
CONTAINER_ITSELF | |||
+ 70 // level 4 | |||
+ 69 // level 4 | |||
+ 6 // content of CeConfigurationModule | |||
+ 4 // content of CeQueueModule | |||
+ 3 // content of CeHttpModule |
@@ -35,7 +35,6 @@ import org.apache.commons.io.IOUtils; | |||
import org.apache.ibatis.session.ResultHandler; | |||
import org.sonar.db.Dao; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.source.FileSourceDto.Type; | |||
import static org.sonar.db.DatabaseUtils.toUniqueAndSortedPartitions; | |||
@@ -44,18 +43,13 @@ public class FileSourceDao implements Dao { | |||
private static final Splitter END_OF_LINE_SPLITTER = Splitter.on('\n'); | |||
@CheckForNull | |||
public FileSourceDto selectSourceByFileUuid(DbSession session, String fileUuid) { | |||
return mapper(session).select(fileUuid, Type.SOURCE); | |||
} | |||
@CheckForNull | |||
public FileSourceDto selectTestByFileUuid(DbSession dbSession, String fileUuid) { | |||
return mapper(dbSession).select(fileUuid, Type.TEST); | |||
public FileSourceDto selectByFileUuid(DbSession session, String fileUuid) { | |||
return mapper(session).selectByFileUuid(fileUuid); | |||
} | |||
@CheckForNull | |||
public LineHashVersion selectLineHashesVersion(DbSession dbSession, String fileUuid) { | |||
Integer version = mapper(dbSession).selectLineHashesVersion(fileUuid, Type.SOURCE); | |||
Integer version = mapper(dbSession).selectLineHashesVersion(fileUuid); | |||
return version == null ? LineHashVersion.WITHOUT_SIGNIFICANT_CODE : LineHashVersion.valueOf(version); | |||
} | |||
@@ -65,9 +59,8 @@ public class FileSourceDao implements Dao { | |||
PreparedStatement pstmt = null; | |||
ResultSet rs = null; | |||
try { | |||
pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type=?"); | |||
pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type='SOURCE'"); | |||
pstmt.setString(1, fileUuid); | |||
pstmt.setString(2, Type.SOURCE); | |||
rs = pstmt.executeQuery(); | |||
if (rs.next()) { | |||
String string = rs.getString(1); | |||
@@ -100,9 +93,8 @@ public class FileSourceDao implements Dao { | |||
ResultSet rs = null; | |||
Reader reader = null; | |||
try { | |||
pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type=?"); | |||
pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type='SOURCE'"); | |||
pstmt.setString(1, fileUuid); | |||
pstmt.setString(2, Type.SOURCE); | |||
rs = pstmt.executeQuery(); | |||
if (rs.next()) { | |||
reader = rs.getCharacterStream(1); |
@@ -26,8 +26,6 @@ import com.google.protobuf.InvalidProtocolBufferException; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import javax.annotation.CheckForNull; | |||
@@ -68,7 +66,6 @@ public class FileSourceDto { | |||
private int lineCount = LINE_COUNT_NOT_POPULATED; | |||
private String srcHash; | |||
private byte[] binaryData = new byte[0]; | |||
private String dataType; | |||
private String dataHash; | |||
private String revision; | |||
@Nullable | |||
@@ -170,56 +167,6 @@ public class FileSourceDto { | |||
} | |||
} | |||
public static List<DbFileSources.Test> decodeTestData(byte[] binaryData) { | |||
// stream is always closed | |||
return decodeTestData(new ByteArrayInputStream(binaryData)); | |||
} | |||
/** | |||
* Decompress and deserialize content of column FILE_SOURCES.BINARY_DATA. | |||
* The parameter "input" is always closed by this method. | |||
*/ | |||
public static List<DbFileSources.Test> decodeTestData(InputStream binaryInput) { | |||
LZ4BlockInputStream lz4Input = null; | |||
List<DbFileSources.Test> tests = new ArrayList<>(); | |||
try { | |||
lz4Input = new LZ4BlockInputStream(binaryInput); | |||
DbFileSources.Test currentTest; | |||
do { | |||
currentTest = DbFileSources.Test.parseDelimitedFrom(lz4Input); | |||
if (currentTest != null) { | |||
tests.add(currentTest); | |||
} | |||
} while (currentTest != null); | |||
return tests; | |||
} catch (IOException e) { | |||
throw new IllegalStateException("Fail to decompress and deserialize source data", e); | |||
} finally { | |||
IOUtils.closeQuietly(lz4Input); | |||
} | |||
} | |||
/** | |||
* Serialize and compress protobuf message {@link org.sonar.db.protobuf.DbFileSources.Data} | |||
* in the column BINARY_DATA. | |||
*/ | |||
public static byte[] encodeTestData(List<DbFileSources.Test> tests) { | |||
ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(); | |||
LZ4BlockOutputStream compressedOutput = new LZ4BlockOutputStream(byteOutput); | |||
try { | |||
for (DbFileSources.Test test : tests) { | |||
test.writeDelimitedTo(compressedOutput); | |||
} | |||
compressedOutput.close(); | |||
return byteOutput.toByteArray(); | |||
} catch (IOException e) { | |||
throw new IllegalStateException("Fail to serialize and compress source tests", e); | |||
} finally { | |||
IOUtils.closeQuietly(compressedOutput); | |||
} | |||
} | |||
/** | |||
* Compressed value of serialized protobuf message {@link org.sonar.db.protobuf.DbFileSources.Data} | |||
*/ | |||
@@ -243,24 +190,10 @@ public class FileSourceDto { | |||
} | |||
public FileSourceDto setSourceData(DbFileSources.Data data) { | |||
this.dataType = Type.SOURCE; | |||
this.binaryData = encodeSourceData(data); | |||
return this; | |||
} | |||
/** | |||
* Compressed value of serialized protobuf message {@link org.sonar.db.protobuf.DbFileSources.Data} | |||
*/ | |||
public List<DbFileSources.Test> getTestData() { | |||
return decodeTestData(binaryData); | |||
} | |||
public FileSourceDto setTestData(List<DbFileSources.Test> data) { | |||
this.dataType = Type.TEST; | |||
this.binaryData = encodeTestData(data); | |||
return this; | |||
} | |||
/** Used by MyBatis */ | |||
public String getRawLineHashes() { | |||
return lineHashes; | |||
@@ -332,15 +265,6 @@ public class FileSourceDto { | |||
return this; | |||
} | |||
public String getDataType() { | |||
return dataType; | |||
} | |||
public FileSourceDto setDataType(String dataType) { | |||
this.dataType = dataType; | |||
return this; | |||
} | |||
public String getRevision() { | |||
return revision; | |||
} | |||
@@ -350,12 +274,4 @@ public class FileSourceDto { | |||
return this; | |||
} | |||
public static class Type { | |||
public static final String SOURCE = "SOURCE"; | |||
public static final String TEST = "TEST"; | |||
private Type() { | |||
// utility class | |||
} | |||
} | |||
} |
@@ -30,12 +30,12 @@ public interface FileSourceMapper { | |||
List<FileSourceDto> selectHashesForProject(@Param("projectUuid") String projectUuid, @Param("dataType") String dataType); | |||
@CheckForNull | |||
FileSourceDto select(@Param("fileUuid") String fileUuid, @Param("dataType") String dataType); | |||
FileSourceDto selectByFileUuid(@Param("fileUuid") String fileUuid); | |||
void scrollLineHashes(@Param("fileUuids") Collection<String> fileUuids, ResultHandler<LineHashesWithUuidDto> rowHandler); | |||
@CheckForNull | |||
Integer selectLineHashesVersion(@Param("fileUuid") String fileUuid, @Param("dataType") String dataType); | |||
Integer selectLineHashesVersion(@Param("fileUuid") String fileUuid); | |||
void insert(FileSourceDto dto); | |||
@@ -4,7 +4,7 @@ | |||
<mapper namespace="org.sonar.db.source.FileSourceMapper"> | |||
<select id="select" parameterType="map" resultType="org.sonar.db.source.FileSourceDto"> | |||
<select id="selectByFileUuid" parameterType="map" resultType="org.sonar.db.source.FileSourceDto"> | |||
select | |||
id, | |||
project_uuid as projectUuid, | |||
@@ -17,14 +17,12 @@ | |||
line_count as lineCount, | |||
data_hash as dataHash, | |||
src_hash as srcHash, | |||
data_type as | |||
dataType, | |||
revision | |||
from | |||
file_sources | |||
where | |||
file_uuid = #{fileUuid,jdbcType=VARCHAR} | |||
and data_type = #{dataType,jdbcType=VARCHAR} | |||
and data_type = 'SOURCE' | |||
</select> | |||
<select id="selectHashesForProject" parameterType="map" resultType="org.sonar.db.source.FileSourceDto"> | |||
@@ -35,11 +33,11 @@ | |||
src_hash as srcHash, | |||
revision, | |||
updated_at as updatedAt | |||
from | |||
from | |||
file_sources | |||
where | |||
project_uuid = #{projectUuid,jdbcType=VARCHAR} | |||
and data_type = #{dataType,jdbcType=VARCHAR} | |||
and data_type = 'SOURCE' | |||
</select> | |||
<select id="scrollLineHashes" parameterType="map" resultType="org.sonar.db.source.LineHashesWithUuidDto" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY"> | |||
@@ -66,7 +64,7 @@ | |||
file_sources | |||
WHERE | |||
file_uuid = #{fileUuid,jdbcType=VARCHAR} | |||
and data_type=#{dataType,jdbcType=VARCHAR} | |||
and data_type = 'SOURCE' | |||
</select> | |||
<insert id="insert" parameterType="org.sonar.db.source.FileSourceDto" useGeneratedKeys="false"> | |||
@@ -97,7 +95,7 @@ | |||
#{lineCount,jdbcType=INTEGER}, | |||
#{dataHash,jdbcType=VARCHAR}, | |||
#{srcHash,jdbcType=VARCHAR}, | |||
#{dataType,jdbcType=VARCHAR}, | |||
'SOURCE', | |||
#{revision,jdbcType=VARCHAR} | |||
) | |||
</insert> |
@@ -123,26 +123,6 @@ public class ScrollForFileMoveComponentDaoTest { | |||
verifyFileMoveRowDto(resultHandler, file3); | |||
} | |||
@Test | |||
public void scrollAllFilesForFileMove_ignores_file_source_of_type_TEST() { | |||
OrganizationDto organization = db.organizations().insert(); | |||
ComponentDto project = random.nextBoolean() ? db.components().insertPrivateProject(organization) : db.components().insertPublicProject(organization); | |||
ComponentDto module1 = db.components().insertComponent(ComponentTesting.newModuleDto(project)); | |||
ComponentDto module2 = db.components().insertComponent(ComponentTesting.newModuleDto(module1)); | |||
ComponentAndSource file1 = insertFileAndSource(project, FILE); | |||
ComponentDto file2 = db.components().insertComponent(ComponentTesting.newFileDto(module1).setQualifier(UNIT_TEST_FILE)); | |||
db.fileSources().insertFileSource(file2, t -> t.setDataType(UNIT_TEST_FILE)); | |||
ComponentAndSource file3 = insertFileAndSource(module2, FILE); | |||
db.fileSources().insertFileSource(file3.component, t -> t.setDataType(UNIT_TEST_FILE)); | |||
RecordingResultHandler resultHandler = new RecordingResultHandler(); | |||
underTest.scrollAllFilesForFileMove(dbSession, project.uuid(), resultHandler); | |||
assertThat(resultHandler.dtos).hasSize(2); | |||
verifyFileMoveRowDto(resultHandler, file1); | |||
verifyFileMoveRowDto(resultHandler, file3); | |||
} | |||
@Test | |||
public void scrollAllFilesForFileMove_scrolls_large_number_of_files_and_uts() { | |||
OrganizationDto organization = db.organizations().insert(); | |||
@@ -268,5 +248,4 @@ public class ScrollForFileMoveComponentDaoTest { | |||
assertThat(dto.getLineCount()).isEqualTo(componentAndSource.source.getLineCount()); | |||
} | |||
} |
@@ -214,9 +214,8 @@ public class PurgeDaoTest { | |||
assertThat(db.countSql("select count(*) from issues where resolution = 'REMOVED'")).isEqualTo(0); | |||
db.fileSources().insertFileSource(srcFile); | |||
db.fileSources().insertFileSource(testFile, f -> f.setDataType("TEST")); | |||
FileSourceDto nonSelectedFileSource = db.fileSources().insertFileSource(nonSelectedFile); | |||
assertThat(db.countRowsOfTable("file_sources")).isEqualTo(3); | |||
assertThat(db.countRowsOfTable("file_sources")).isEqualTo(2); | |||
MetricDto metric1 = db.measures().insertMetric(); | |||
MetricDto metric2 = db.measures().insertMetric(); | |||
@@ -254,11 +253,12 @@ public class PurgeDaoTest { | |||
// delete file sources of selected | |||
assertThat(db.countRowsOfTable("file_sources")).isEqualTo(1); | |||
assertThat(db.getDbClient().fileSourceDao().selectSourceByFileUuid(dbSession, nonSelectedFileSource.getFileUuid())).isNotNull(); | |||
assertThat(db.getDbClient().fileSourceDao().selectByFileUuid(dbSession, nonSelectedFileSource.getFileUuid())).isNotNull(); | |||
// deletes live measure of selected | |||
assertThat(db.countRowsOfTable("live_measures")).isEqualTo(4); | |||
List<LiveMeasureDto> liveMeasureDtos = db.getDbClient().liveMeasureDao().selectByComponentUuidsAndMetricIds(dbSession, ImmutableSet.of(srcFile.uuid(), dir.uuid(), project.uuid(), nonSelectedFile.uuid()), ImmutableSet.of(metric1.getId(), metric2.getId())); | |||
List<LiveMeasureDto> liveMeasureDtos = db.getDbClient().liveMeasureDao().selectByComponentUuidsAndMetricIds(dbSession, | |||
ImmutableSet.of(srcFile.uuid(), dir.uuid(), project.uuid(), nonSelectedFile.uuid()), ImmutableSet.of(metric1.getId(), metric2.getId())); | |||
assertThat(liveMeasureDtos) | |||
.extracting(LiveMeasureDto::getComponentUuid) | |||
.containsOnly(nonSelectedFile.uuid(), project.uuid()); | |||
@@ -275,7 +275,6 @@ public class PurgeDaoTest { | |||
db.assertDbUnit(getClass(), "shouldDeleteAnalyses-result.xml", "snapshots"); | |||
} | |||
@Test | |||
public void deleteAnalyses_deletes_rows_in_events_and_event_component_changes() { | |||
ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization()); |
@@ -41,7 +41,6 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.source.FileSourceDto.Type; | |||
import static com.google.common.collect.ImmutableList.of; | |||
import static java.util.Collections.emptyList; | |||
@@ -64,7 +63,7 @@ public class FileSourceDaoTest { | |||
public void select() { | |||
dbTester.prepareDbUnit(getClass(), "shared.xml"); | |||
FileSourceDto fileSourceDto = underTest.selectSourceByFileUuid(dbSession, "FILE1_UUID"); | |||
FileSourceDto fileSourceDto = underTest.selectByFileUuid(dbSession, "FILE1_UUID"); | |||
assertThat(fileSourceDto.getBinaryData()).isNotEmpty(); | |||
assertThat(fileSourceDto.getDataHash()).isEqualTo("hash"); | |||
@@ -72,7 +71,6 @@ public class FileSourceDaoTest { | |||
assertThat(fileSourceDto.getFileUuid()).isEqualTo("FILE1_UUID"); | |||
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(1500000000000L); | |||
assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(1500000000000L); | |||
assertThat(fileSourceDto.getDataType()).isEqualTo(Type.SOURCE); | |||
assertThat(fileSourceDto.getRevision()).isEqualTo("123456789"); | |||
assertThat(fileSourceDto.getLineHashesVersion()).isEqualTo(0); | |||
@@ -117,7 +115,6 @@ public class FileSourceDaoTest { | |||
.setDataHash("FILE2_DATA_HASH") | |||
.setLineHashes(of("LINE1_HASH", "LINE2_HASH")) | |||
.setSrcHash("FILE2_HASH") | |||
.setDataType(Type.SOURCE) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1500000000001L) | |||
.setLineHashesVersion(1) | |||
@@ -125,7 +122,7 @@ public class FileSourceDaoTest { | |||
underTest.insert(dbSession, expected); | |||
dbSession.commit(); | |||
FileSourceDto fileSourceDto = underTest.selectSourceByFileUuid(dbSession, expected.getFileUuid()); | |||
FileSourceDto fileSourceDto = underTest.selectByFileUuid(dbSession, expected.getFileUuid()); | |||
assertThat(fileSourceDto.getProjectUuid()).isEqualTo(expected.getProjectUuid()); | |||
assertThat(fileSourceDto.getFileUuid()).isEqualTo(expected.getFileUuid()); | |||
@@ -156,30 +153,12 @@ public class FileSourceDaoTest { | |||
FileSourceDto fileSourceDto = new FileSourceDto() | |||
.setProjectUuid("Foo") | |||
.setFileUuid("Bar") | |||
.setDataType(Type.SOURCE) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1500000000001L); | |||
underTest.insert(dbSession, fileSourceDto); | |||
dbSession.commit(); | |||
FileSourceDto res = underTest.selectSourceByFileUuid(dbSession, fileSourceDto.getFileUuid()); | |||
assertThat(res.getLineCount()).isEqualTo(0); | |||
assertThat(res.getLineHashes()).isEmpty(); | |||
} | |||
@Test | |||
public void selectTest_reads_test_without_line_hashes() { | |||
FileSourceDto fileSourceDto = new FileSourceDto() | |||
.setProjectUuid("Foo") | |||
.setFileUuid("Bar") | |||
.setDataType(Type.TEST) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1500000000001L); | |||
underTest.insert(dbSession, fileSourceDto); | |||
dbSession.commit(); | |||
FileSourceDto res = underTest.selectTestByFileUuid(dbSession, fileSourceDto.getFileUuid()); | |||
FileSourceDto res = underTest.selectByFileUuid(dbSession, fileSourceDto.getFileUuid()); | |||
assertThat(res.getLineCount()).isEqualTo(0); | |||
assertThat(res.getLineHashes()).isEmpty(); | |||
@@ -195,7 +174,6 @@ public class FileSourceDaoTest { | |||
.setBinaryData("FILE2_BINARY_DATA".getBytes()) | |||
.setDataHash("FILE2_DATA_HASH") | |||
.setSrcHash("FILE2_HASH") | |||
.setDataType(Type.SOURCE) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1500000000001L) | |||
.setRevision("123456789")); | |||
@@ -213,7 +191,6 @@ public class FileSourceDaoTest { | |||
.setDataHash("FILE2_DATA_HASH") | |||
.setLineHashes(singletonList("hashes")) | |||
.setSrcHash("FILE2_HASH") | |||
.setDataType(Type.SOURCE) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1500000000001L) | |||
.setRevision("123456789")); | |||
@@ -231,7 +208,6 @@ public class FileSourceDaoTest { | |||
.setDataHash("FILE2_DATA_HASH") | |||
.setLineHashes(singletonList("hashes")) | |||
.setSrcHash("FILE2_HASH") | |||
.setDataType(Type.SOURCE) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1500000000001L) | |||
.setLineHashesVersion(1) | |||
@@ -251,7 +227,6 @@ public class FileSourceDaoTest { | |||
.setBinaryData("FILE2_BINARY_DATA".getBytes()) | |||
.setDataHash("FILE2_DATA_HASH") | |||
.setSrcHash("FILE2_HASH") | |||
.setDataType(Type.SOURCE) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1500000000001L) | |||
.setRevision("123456789")); | |||
@@ -313,24 +288,6 @@ public class FileSourceDaoTest { | |||
verifyLinesHashes(handler, file1, fileSource1); | |||
} | |||
@Test | |||
public void scrollLineHashes_does_not_scroll_hashes_of_component_with_TEST_source() { | |||
OrganizationDto organization = dbTester.organizations().insert(); | |||
ComponentDto project = new Random().nextBoolean() ? dbTester.components().insertPrivateProject(organization) : dbTester.components().insertPublicProject(organization); | |||
ComponentDto file1 = dbTester.components().insertComponent(newFileDto(project)); | |||
FileSourceDto fileSource1 = dbTester.fileSources().insertFileSource(file1); | |||
ComponentDto file2 = dbTester.components().insertComponent(newFileDto(project)); | |||
FileSourceDto fileSource2 = dbTester.fileSources().insertFileSource(file2, t -> t.setDataType(Type.TEST)); | |||
ComponentDto file3 = dbTester.components().insertComponent(newFileDto(project)); | |||
FileSourceDto fileSource3 = dbTester.fileSources().insertFileSource(file3, t -> t.setDataType(Type.SOURCE)); | |||
FileSourceDto testFileSource3 = dbTester.fileSources().insertFileSource(file3, t -> t.setDataType(Type.TEST)); | |||
LineHashesWithKeyDtoHandler handler = scrollLineHashes(file2.uuid(), file1.uuid(), file3.uuid()); | |||
assertThat(handler.dtos).hasSize(2); | |||
verifyLinesHashes(handler, file1, fileSource1); | |||
verifyLinesHashes(handler, file3, fileSource3); | |||
} | |||
@Test | |||
public void scrollLineHashes_handles_scrolling_more_than_1000_files() { | |||
OrganizationDto organization = dbTester.organizations().insert(); | |||
@@ -390,14 +347,13 @@ public class FileSourceDaoTest { | |||
.setDataHash("NEW_DATA_HASH") | |||
.setSrcHash("NEW_FILE_HASH") | |||
.setLineHashes(singletonList("NEW_LINE_HASHES")) | |||
.setDataType(Type.SOURCE) | |||
.setUpdatedAt(1500000000002L) | |||
.setLineHashesVersion(1) | |||
.setRevision("987654321")); | |||
dbSession.commit(); | |||
dbTester.assertDbUnitTable(getClass(), "update-result.xml", "file_sources", "project_uuid", "file_uuid", | |||
"data_hash", "line_hashes", "src_hash", "created_at", "updated_at", "data_type", "revision", "line_hashes_version"); | |||
"data_hash", "line_hashes", "src_hash", "created_at", "updated_at", "revision", "line_hashes_version"); | |||
} | |||
@Test | |||
@@ -406,14 +362,13 @@ public class FileSourceDaoTest { | |||
FileSourceDto fileSourceDto = new FileSourceDto() | |||
.setProjectUuid("Foo") | |||
.setFileUuid("Bar") | |||
.setDataType(Type.SOURCE) | |||
.setLineHashes(lineHashes) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1500000000001L); | |||
underTest.insert(dbSession, fileSourceDto); | |||
dbSession.commit(); | |||
FileSourceDto resBefore = underTest.selectSourceByFileUuid(dbSession, fileSourceDto.getFileUuid()); | |||
FileSourceDto resBefore = underTest.selectByFileUuid(dbSession, fileSourceDto.getFileUuid()); | |||
assertThat(resBefore.getLineCount()).isEqualTo(lineHashes.size()); | |||
assertThat(resBefore.getLineHashes()).isEqualTo(lineHashes); | |||
@@ -422,7 +377,7 @@ public class FileSourceDaoTest { | |||
underTest.update(dbSession, fileSourceDto); | |||
dbSession.commit(); | |||
FileSourceDto res = underTest.selectSourceByFileUuid(dbSession, fileSourceDto.getFileUuid()); | |||
FileSourceDto res = underTest.selectByFileUuid(dbSession, fileSourceDto.getFileUuid()); | |||
assertThat(res.getLineHashes()).isEmpty(); | |||
assertThat(res.getLineCount()).isEqualTo(1); | |||
} |
@@ -20,7 +20,6 @@ | |||
package org.sonar.db.source; | |||
import com.google.common.base.Joiner; | |||
import java.util.Arrays; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.Random; | |||
@@ -43,22 +42,6 @@ public class FileSourceDtoTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Test | |||
public void encode_and_decode_test_data() { | |||
List<DbFileSources.Test> tests = Arrays.asList( | |||
DbFileSources.Test.newBuilder() | |||
.setName("name#1") | |||
.build(), | |||
DbFileSources.Test.newBuilder() | |||
.setName("name#2") | |||
.build()); | |||
FileSourceDto underTest = new FileSourceDto().setTestData(tests); | |||
assertThat(underTest.getTestData()).hasSize(2); | |||
assertThat(underTest.getTestData().get(0).getName()).isEqualTo("name#1"); | |||
} | |||
@Test | |||
public void getSourceData_throws_ISE_with_id_fileUuid_and_projectUuid_in_message_when_data_cant_be_read() { | |||
long id = 12L; | |||
@@ -98,7 +81,7 @@ public class FileSourceDtoTest { | |||
} | |||
@Test | |||
public void new_FileSourceDto_as_lineCount_0_and_rawLineHashes_to_null() { | |||
public void new_FileSourceDto_as_lineCount_0_and_rawLineHashes_to_null() { | |||
FileSourceDto underTest = new FileSourceDto(); | |||
assertThat(underTest.getLineCount()).isZero(); |
@@ -1,96 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.source.index; | |||
import com.google.common.base.Joiner; | |||
import java.sql.PreparedStatement; | |||
import java.sql.SQLException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import javax.annotation.Nullable; | |||
import org.elasticsearch.action.update.UpdateRequest; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
public class FileSourcesUpdaterHelper { | |||
private static final String SQL_ALL = "SELECT %s FROM file_sources WHERE data_type='%s' "; | |||
private static final String PROJECT_FILTER = " AND project_uuid=?"; | |||
private static final String[] FIELDS = { | |||
"project_uuid", | |||
"file_uuid", | |||
"updated_at", | |||
"binary_data" | |||
}; | |||
private static final String FIELDS_ONE_LINE = Joiner.on(",").join(FIELDS); | |||
private FileSourcesUpdaterHelper() { | |||
// only static stuff | |||
} | |||
public static PreparedStatement preparedStatementToSelectFileSources(DbClient dbClient, DbSession session, String dataType, @Nullable String projectUuid) | |||
throws SQLException { | |||
String sql = createSQL(dataType, projectUuid); | |||
// rows are big, so they are scrolled once at a time (one row in memory at a time) | |||
PreparedStatement stmt = dbClient.getMyBatis().newScrollingSingleRowSelectStatement(session, sql); | |||
if (projectUuid != null) { | |||
stmt.setString(1, projectUuid); | |||
} | |||
return stmt; | |||
} | |||
private static String createSQL(String dataType, @Nullable String projectUuid) { | |||
StringBuilder sql = new StringBuilder(String.format(SQL_ALL, FIELDS_ONE_LINE, dataType)); | |||
if (projectUuid != null) { | |||
sql.append(PROJECT_FILTER); | |||
} | |||
return sql.toString(); | |||
} | |||
public static class Row { | |||
private final String fileUuid; | |||
private final String projectUuid; | |||
private final long updatedAt; | |||
private final List<UpdateRequest> updateRequests = new ArrayList<>(); | |||
public Row(String projectUuid, String fileUuid, long updatedAt) { | |||
this.projectUuid = projectUuid; | |||
this.fileUuid = fileUuid; | |||
this.updatedAt = updatedAt; | |||
} | |||
public String getProjectUuid() { | |||
return projectUuid; | |||
} | |||
public String getFileUuid() { | |||
return fileUuid; | |||
} | |||
public long getUpdatedAt() { | |||
return updatedAt; | |||
} | |||
public List<UpdateRequest> getUpdateRequests() { | |||
return updateRequests; | |||
} | |||
} | |||
} |
@@ -1,74 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.index; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import com.google.common.collect.Maps; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.sonar.server.es.BaseDoc; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_LINES; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_UUID; | |||
public class CoveredFileDoc extends BaseDoc { | |||
public CoveredFileDoc(Map<String, Object> fields) { | |||
super(fields); | |||
} | |||
@VisibleForTesting | |||
public CoveredFileDoc() { | |||
super(Maps.newHashMapWithExpectedSize(2)); | |||
} | |||
@Override | |||
public String getId() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
@Override | |||
public String getRouting() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
@Override | |||
public String getParent() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
public String fileUuid() { | |||
return getField(FIELD_COVERED_FILE_UUID); | |||
} | |||
public CoveredFileDoc setFileUuid(String fileUuid) { | |||
setField(FIELD_COVERED_FILE_UUID, fileUuid); | |||
return this; | |||
} | |||
public List<Integer> coveredLines() { | |||
return getField(FIELD_COVERED_FILE_LINES); | |||
} | |||
public CoveredFileDoc setCoveredLines(List<Integer> coveredLines) { | |||
setField(FIELD_COVERED_FILE_LINES, coveredLines); | |||
return this; | |||
} | |||
} |
@@ -1,162 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.index; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import com.google.common.collect.Maps; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import javax.annotation.CheckForNull; | |||
import org.sonar.server.es.BaseDoc; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILES; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_DURATION_IN_MS; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_MESSAGE; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_NAME; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_PROJECT_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STACKTRACE; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STATUS; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_TEST_UUID; | |||
public class TestDoc extends BaseDoc { | |||
public TestDoc(Map<String, Object> fields) { | |||
super(fields); | |||
} | |||
@VisibleForTesting | |||
public TestDoc() { | |||
super(Maps.newHashMapWithExpectedSize(10)); | |||
} | |||
@Override | |||
public String getId() { | |||
return testUuid(); | |||
} | |||
@Override | |||
public String getRouting() { | |||
return projectUuid(); | |||
} | |||
@Override | |||
public String getParent() { | |||
return null; | |||
} | |||
public String projectUuid() { | |||
return getField(FIELD_PROJECT_UUID); | |||
} | |||
public TestDoc setProjectUuid(String projectUuid) { | |||
setField(FIELD_PROJECT_UUID, projectUuid); | |||
return this; | |||
} | |||
public String fileUuid() { | |||
return getField(FIELD_FILE_UUID); | |||
} | |||
public TestDoc setFileUuid(String fileUuid) { | |||
setField(FIELD_FILE_UUID, fileUuid); | |||
return this; | |||
} | |||
public String testUuid() { | |||
return getField(FIELD_TEST_UUID); | |||
} | |||
public TestDoc setUuid(String testUuid) { | |||
setField(FIELD_TEST_UUID, testUuid); | |||
return this; | |||
} | |||
public String name() { | |||
return getField(FIELD_NAME); | |||
} | |||
public TestDoc setName(String name) { | |||
setField(FIELD_NAME, name); | |||
return this; | |||
} | |||
public String status() { | |||
return getField(FIELD_STATUS); | |||
} | |||
public TestDoc setStatus(String status) { | |||
setField(FIELD_STATUS, status); | |||
return this; | |||
} | |||
@CheckForNull | |||
public String message() { | |||
return getNullableField(FIELD_MESSAGE); | |||
} | |||
public TestDoc setMessage(String message) { | |||
setField(FIELD_MESSAGE, message); | |||
return this; | |||
} | |||
@CheckForNull | |||
public String stackTrace() { | |||
return getNullableField(FIELD_STACKTRACE); | |||
} | |||
public TestDoc setStackTrace(String stackTrace) { | |||
setField(FIELD_STACKTRACE, stackTrace); | |||
return this; | |||
} | |||
@CheckForNull | |||
public Long durationInMs() { | |||
Number number = getNullableField(FIELD_DURATION_IN_MS); | |||
return number == null ? null : number.longValue(); | |||
} | |||
public TestDoc setDurationInMs(Long durationInMs) { | |||
setField(FIELD_DURATION_IN_MS, durationInMs); | |||
return this; | |||
} | |||
public List<CoveredFileDoc> coveredFiles() { | |||
List<Map<String, Object>> coveredFilesAsMaps = getNullableField(FIELD_COVERED_FILES); | |||
if (coveredFilesAsMaps == null) { | |||
return new ArrayList<>(); | |||
} | |||
List<CoveredFileDoc> coveredFiles = new ArrayList<>(); | |||
for (Map<String, Object> coveredFileMap : coveredFilesAsMaps) { | |||
coveredFiles.add(new CoveredFileDoc(coveredFileMap)); | |||
} | |||
return coveredFiles; | |||
} | |||
public TestDoc setCoveredFiles(List<CoveredFileDoc> coveredFiles) { | |||
List<Map<String, Object>> coveredFilesAsMaps = new ArrayList<>(); | |||
for (CoveredFileDoc coveredFile : coveredFiles) { | |||
coveredFilesAsMaps.add(coveredFile.getFields()); | |||
} | |||
setField(FIELD_COVERED_FILES, coveredFilesAsMaps); | |||
return this; | |||
} | |||
} |
@@ -1,116 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.index; | |||
import com.google.common.base.Optional; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.apache.lucene.search.join.ScoreMode; | |||
import org.elasticsearch.action.search.SearchRequestBuilder; | |||
import org.elasticsearch.search.SearchHit; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.SearchOptions; | |||
import org.sonar.server.es.SearchResult; | |||
import static org.elasticsearch.index.query.QueryBuilders.boolQuery; | |||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; | |||
import static org.elasticsearch.index.query.QueryBuilders.nestedQuery; | |||
import static org.elasticsearch.index.query.QueryBuilders.termQuery; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILES; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_LINES; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_TEST_UUID; | |||
public class TestIndex { | |||
private final EsClient client; | |||
private final System2 system2; | |||
public TestIndex(EsClient client, System2 system2) { | |||
this.client = client; | |||
this.system2 = system2; | |||
} | |||
public List<CoveredFileDoc> coveredFiles(String testUuid) { | |||
List<CoveredFileDoc> coveredFiles = new ArrayList<>(); | |||
for (SearchHit hit : client.prepareSearch(TestIndexDefinition.INDEX_TYPE_TEST) | |||
.setSize(1) | |||
.setQuery(boolQuery().must(matchAllQuery()).filter(termQuery(FIELD_TEST_UUID, testUuid))) | |||
.get().getHits().getHits()) { | |||
coveredFiles.addAll(new TestDoc(hit.getSourceAsMap()).coveredFiles()); | |||
} | |||
return coveredFiles; | |||
} | |||
public SearchResult<TestDoc> searchByTestFileUuid(String testFileUuid, SearchOptions searchOptions) { | |||
SearchRequestBuilder searchRequest = client.prepareSearch(TestIndexDefinition.INDEX_TYPE_TEST) | |||
.setSize(searchOptions.getLimit()) | |||
.setFrom(searchOptions.getOffset()) | |||
.setQuery(boolQuery().must(matchAllQuery()).filter(termQuery(FIELD_FILE_UUID, testFileUuid))); | |||
return new SearchResult<>(searchRequest.get(), TestDoc::new, system2.getDefaultTimeZone()); | |||
} | |||
public SearchResult<TestDoc> searchBySourceFileUuidAndLineNumber(String sourceFileUuid, int lineNumber, SearchOptions searchOptions) { | |||
SearchRequestBuilder searchRequest = client.prepareSearch(TestIndexDefinition.INDEX_TYPE_TEST) | |||
.setSize(searchOptions.getLimit()) | |||
.setFrom(searchOptions.getOffset()) | |||
.setQuery(nestedQuery( | |||
FIELD_COVERED_FILES, | |||
boolQuery() | |||
.must(termQuery(FIELD_COVERED_FILES + "." + FIELD_COVERED_FILE_UUID, sourceFileUuid)) | |||
.must(termQuery(FIELD_COVERED_FILES + "." + FIELD_COVERED_FILE_LINES, lineNumber)), | |||
ScoreMode.Avg)); | |||
return new SearchResult<>(searchRequest.get(), TestDoc::new, system2.getDefaultTimeZone()); | |||
} | |||
public TestDoc getByTestUuid(String testUuid) { | |||
Optional<TestDoc> testDoc = getNullableByTestUuid(testUuid); | |||
if (testDoc.isPresent()) { | |||
return testDoc.get(); | |||
} | |||
throw new IllegalStateException(String.format("Test id '%s' not found", testUuid)); | |||
} | |||
public Optional<TestDoc> getNullableByTestUuid(String testUuid) { | |||
SearchHit[] hits = client.prepareSearch(TestIndexDefinition.INDEX_TYPE_TEST) | |||
.setSize(1) | |||
.setQuery(boolQuery().must(matchAllQuery()).filter(termQuery(FIELD_TEST_UUID, testUuid))) | |||
.get().getHits().getHits(); | |||
if (hits.length > 0) { | |||
return Optional.of(new TestDoc(hits[0].getSourceAsMap())); | |||
} | |||
return Optional.absent(); | |||
} | |||
public SearchResult<TestDoc> searchByTestUuid(String testUuid, SearchOptions searchOptions) { | |||
SearchRequestBuilder searchRequest = client.prepareSearch(TestIndexDefinition.INDEX_TYPE_TEST) | |||
.setSize(searchOptions.getLimit()) | |||
.setFrom(searchOptions.getOffset()) | |||
.setQuery(boolQuery().must(matchAllQuery()).filter(termQuery(FIELD_TEST_UUID, testUuid))); | |||
return new SearchResult<>(searchRequest.get(), TestDoc::new, system2.getDefaultTimeZone()); | |||
} | |||
} |
@@ -1,151 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.index; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Set; | |||
import org.elasticsearch.action.search.SearchRequestBuilder; | |||
import org.elasticsearch.index.query.QueryBuilders; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.es.EsQueueDto; | |||
import org.sonar.server.es.BulkIndexer; | |||
import org.sonar.server.es.BulkIndexer.Size; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.IndexType; | |||
import org.sonar.server.es.IndexingListener; | |||
import org.sonar.server.es.IndexingResult; | |||
import org.sonar.server.es.OneToManyResilientIndexingListener; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.source.index.FileSourcesUpdaterHelper; | |||
import static java.util.Collections.emptyList; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.INDEX_TYPE_TEST; | |||
/** | |||
* Add to Elasticsearch index {@link TestIndexDefinition} the rows of | |||
* db table FILE_SOURCES of type TEST that are not indexed yet | |||
* <p> | |||
* This indexer is not resilient by itself since it's called by Compute Engine | |||
*/ | |||
public class TestIndexer implements ProjectIndexer { | |||
private final DbClient dbClient; | |||
private final EsClient esClient; | |||
public TestIndexer(DbClient dbClient, EsClient esClient) { | |||
this.dbClient = dbClient; | |||
this.esClient = esClient; | |||
} | |||
@Override | |||
public Set<IndexType> getIndexTypes() { | |||
return ImmutableSet.of(INDEX_TYPE_TEST); | |||
} | |||
@Override | |||
public void indexOnStartup(Set<IndexType> uninitializedIndexTypes) { | |||
try (DbSession dbSession = dbClient.openSession(false); | |||
TestResultSetIterator rowIt = TestResultSetIterator.create(dbClient, dbSession, null)) { | |||
BulkIndexer bulkIndexer = new BulkIndexer(esClient, INDEX_TYPE_TEST, Size.LARGE); | |||
bulkIndexer.start(); | |||
addTestsToBulkIndexer(rowIt, bulkIndexer); | |||
bulkIndexer.stop(); | |||
} | |||
} | |||
@Override | |||
public void indexOnAnalysis(String branchUuid) { | |||
BulkIndexer bulkIndexer = new BulkIndexer(esClient, INDEX_TYPE_TEST, Size.REGULAR); | |||
bulkIndexer.start(); | |||
addProjectDeletionToBulkIndexer(bulkIndexer, branchUuid); | |||
try (DbSession dbSession = dbClient.openSession(false); | |||
TestResultSetIterator rowIt = TestResultSetIterator.create(dbClient, dbSession, branchUuid)) { | |||
addTestsToBulkIndexer(rowIt, bulkIndexer); | |||
} | |||
bulkIndexer.stop(); | |||
} | |||
@Override | |||
public Collection<EsQueueDto> prepareForRecovery(DbSession dbSession, Collection<String> projectUuids, Cause cause) { | |||
switch (cause) { | |||
case PROJECT_CREATION: | |||
// no tests at that time | |||
case MEASURE_CHANGE: | |||
case PROJECT_KEY_UPDATE: | |||
case PROJECT_TAGS_UPDATE: | |||
case PERMISSION_CHANGE: | |||
// Measures, project key, tags and permissions are not part of tests/test | |||
return emptyList(); | |||
case PROJECT_DELETION: | |||
List<EsQueueDto> items = projectUuids.stream() | |||
.map(projectUuid -> EsQueueDto.create(INDEX_TYPE_TEST.format(), projectUuid, null, projectUuid)) | |||
.collect(MoreCollectors.toArrayList(projectUuids.size())); | |||
return dbClient.esQueueDao().insert(dbSession, items); | |||
default: | |||
// defensive case | |||
throw new IllegalStateException("Unsupported cause: " + cause); | |||
} | |||
} | |||
public void deleteByFile(String fileUuid) { | |||
SearchRequestBuilder searchRequest = esClient.prepareSearch(INDEX_TYPE_TEST) | |||
.setQuery(QueryBuilders.termQuery(FIELD_FILE_UUID, fileUuid)); | |||
BulkIndexer.delete(esClient, INDEX_TYPE_TEST, searchRequest); | |||
} | |||
@Override | |||
public IndexingResult index(DbSession dbSession, Collection<EsQueueDto> items) { | |||
// The items are to be deleted | |||
if (items.isEmpty()) { | |||
return new IndexingResult(); | |||
} | |||
IndexingListener listener = new OneToManyResilientIndexingListener(dbClient, dbSession, items); | |||
BulkIndexer bulkIndexer = new BulkIndexer(esClient, INDEX_TYPE_TEST, Size.REGULAR, listener); | |||
bulkIndexer.start(); | |||
items.forEach(i -> { | |||
String projectUuid = i.getDocId(); | |||
addProjectDeletionToBulkIndexer(bulkIndexer, projectUuid); | |||
}); | |||
return bulkIndexer.stop(); | |||
} | |||
private void addProjectDeletionToBulkIndexer(BulkIndexer bulkIndexer, String projectUuid) { | |||
SearchRequestBuilder searchRequest = esClient.prepareSearch(INDEX_TYPE_TEST) | |||
.setQuery(QueryBuilders.termQuery(TestIndexDefinition.FIELD_PROJECT_UUID, projectUuid)); | |||
bulkIndexer.addDeletion(searchRequest); | |||
} | |||
private static void addTestsToBulkIndexer(TestResultSetIterator rowIt, BulkIndexer bulkIndexer) { | |||
while (rowIt.hasNext()) { | |||
FileSourcesUpdaterHelper.Row row = rowIt.next(); | |||
row.getUpdateRequests().forEach(bulkIndexer::add); | |||
} | |||
} | |||
} |
@@ -1,144 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.index; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.InputStream; | |||
import java.io.OutputStreamWriter; | |||
import java.nio.charset.StandardCharsets; | |||
import java.sql.PreparedStatement; | |||
import java.sql.ResultSet; | |||
import java.sql.SQLException; | |||
import java.util.Collections; | |||
import java.util.Date; | |||
import java.util.List; | |||
import javax.annotation.Nullable; | |||
import org.elasticsearch.action.update.UpdateRequest; | |||
import org.elasticsearch.common.xcontent.XContentType; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.api.utils.text.JsonWriter; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.ResultSetIterator; | |||
import org.sonar.db.protobuf.DbFileSources; | |||
import org.sonar.db.source.FileSourceDto; | |||
import org.sonar.server.es.EsUtils; | |||
import org.sonar.server.source.index.FileSourcesUpdaterHelper.Row; | |||
import static org.sonar.server.source.index.FileSourcesUpdaterHelper.preparedStatementToSelectFileSources; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILES; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_LINES; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILE_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_DURATION_IN_MS; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_MESSAGE; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_NAME; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_PROJECT_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STACKTRACE; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STATUS; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_TEST_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_UPDATED_AT; | |||
import static org.sonar.server.test.index.TestIndexDefinition.INDEX_TYPE_TEST; | |||
/** | |||
* Scroll over table FILE_SOURCES of test type and directly parse data required to | |||
* populate the index tests/test | |||
*/ | |||
public class TestResultSetIterator extends ResultSetIterator<Row> { | |||
private TestResultSetIterator(PreparedStatement stmt) throws SQLException { | |||
super(stmt); | |||
} | |||
public static TestResultSetIterator create(DbClient dbClient, DbSession session, @Nullable String projectUuid) { | |||
try { | |||
return new TestResultSetIterator(preparedStatementToSelectFileSources(dbClient, session, FileSourceDto.Type.TEST, projectUuid)); | |||
} catch (SQLException e) { | |||
throw new IllegalStateException("Fail to prepare SQL request to select all tests", e); | |||
} | |||
} | |||
@Override | |||
protected Row read(ResultSet rs) throws SQLException { | |||
String projectUuid = rs.getString(1); | |||
String fileUuid = rs.getString(2); | |||
Date updatedAt = new Date(rs.getLong(3)); | |||
List<DbFileSources.Test> tests = parseData(fileUuid, rs.getBinaryStream(4)); | |||
return toRow(projectUuid, fileUuid, updatedAt, tests); | |||
} | |||
private static List<DbFileSources.Test> parseData(String fileUuid, @Nullable InputStream dataInput) { | |||
List<DbFileSources.Test> tests = Collections.emptyList(); | |||
if (dataInput != null) { | |||
try { | |||
tests = FileSourceDto.decodeTestData(dataInput); | |||
} catch (Exception e) { | |||
Loggers.get(TestResultSetIterator.class).warn(String.format("Invalid file_sources.binary_data on row with file_uuid='%s', test file will be ignored", fileUuid), e); | |||
} | |||
} | |||
return tests; | |||
} | |||
/** | |||
* Convert protobuf message to tests required for Elasticsearch indexing | |||
*/ | |||
public static Row toRow(String projectUuid, String fileUuid, Date updatedAt, List<DbFileSources.Test> tests) { | |||
Row result = new Row(projectUuid, fileUuid, updatedAt.getTime()); | |||
for (DbFileSources.Test test : tests) { | |||
ByteArrayOutputStream bytes = new ByteArrayOutputStream(); | |||
// all the fields must be present, even if value is null | |||
try (JsonWriter writer = JsonWriter.of(new OutputStreamWriter(bytes, StandardCharsets.UTF_8)).setSerializeNulls(true)) { | |||
writer.beginObject(); | |||
writer.prop(FIELD_PROJECT_UUID, projectUuid); | |||
writer.prop(FIELD_FILE_UUID, fileUuid); | |||
writer.prop(FIELD_TEST_UUID, test.getUuid()); | |||
writer.prop(FIELD_NAME, test.getName()); | |||
writer.prop(FIELD_STATUS, test.hasStatus() ? test.getStatus().toString() : null); | |||
writer.prop(FIELD_DURATION_IN_MS, test.hasExecutionTimeMs() ? test.getExecutionTimeMs() : null); | |||
writer.prop(FIELD_MESSAGE, test.hasMsg() ? test.getMsg() : null); | |||
writer.prop(FIELD_STACKTRACE, test.hasStacktrace() ? test.getStacktrace() : null); | |||
writer.prop(FIELD_UPDATED_AT, EsUtils.formatDateTime(updatedAt)); | |||
writer.name(FIELD_COVERED_FILES); | |||
writer.beginArray(); | |||
for (DbFileSources.Test.CoveredFile coveredFile : test.getCoveredFileList()) { | |||
writer.beginObject(); | |||
writer.prop(FIELD_COVERED_FILE_UUID, coveredFile.getFileUuid()); | |||
writer.name(FIELD_COVERED_FILE_LINES).valueObject(coveredFile.getCoveredLineList()); | |||
writer.endObject(); | |||
} | |||
writer.endArray(); | |||
writer.endObject(); | |||
} | |||
// This is an optimization to reduce memory consumption and multiple conversions from Map to JSON. | |||
// UpdateRequest#doc() and #upsert() take the same parameter values, so: | |||
// - passing the same Map would execute two JSON serializations | |||
// - Map is a useless temporarily structure: read JDBC result set -> convert to map -> convert to JSON. Generating | |||
// directly JSON from result set is more efficient. | |||
byte[] jsonDoc = bytes.toByteArray(); | |||
UpdateRequest updateRequest = new UpdateRequest(INDEX_TYPE_TEST.getIndex(), INDEX_TYPE_TEST.getType(), test.getUuid()) | |||
.routing(projectUuid) | |||
.doc(jsonDoc, XContentType.JSON) | |||
.upsert(jsonDoc, XContentType.JSON); | |||
result.getUpdateRequests().add(updateRequest); | |||
} | |||
return result; | |||
} | |||
} |
@@ -19,15 +19,8 @@ | |||
*/ | |||
package org.sonar.server.source.index; | |||
import java.io.IOException; | |||
import java.sql.Connection; | |||
import java.sql.PreparedStatement; | |||
import java.sql.SQLException; | |||
import java.util.Arrays; | |||
import org.apache.commons.lang.RandomStringUtils; | |||
import org.apache.commons.lang.math.RandomUtils; | |||
import org.sonar.db.protobuf.DbFileSources; | |||
import org.sonar.db.source.FileSourceDto; | |||
public class FileSourceTesting { | |||
@@ -35,18 +28,6 @@ public class FileSourceTesting { | |||
// only static stuff | |||
} | |||
public static void updateDataColumn(Connection connection, String fileUuid, DbFileSources.Data data) throws SQLException { | |||
updateDataColumn(connection, fileUuid, FileSourceDto.encodeSourceData(data)); | |||
} | |||
public static void updateDataColumn(Connection connection, String fileUuid, byte[] data) throws SQLException { | |||
PreparedStatement stmt = connection.prepareStatement("UPDATE file_sources SET binary_data = ? WHERE file_uuid=? AND data_type='" + FileSourceDto.Type.SOURCE + "'"); | |||
stmt.setBytes(1, data); | |||
stmt.setString(2, fileUuid); | |||
stmt.executeUpdate(); | |||
stmt.close(); | |||
} | |||
/** | |||
* Generate predefined fake data. Result is mutable. | |||
*/ | |||
@@ -71,26 +52,4 @@ public class FileSourceTesting { | |||
return dataBuilder; | |||
} | |||
/** | |||
* Generate random data. Result is mutable. | |||
*/ | |||
public static DbFileSources.Data.Builder newRandomData(int numberOfLines) { | |||
DbFileSources.Data.Builder dataBuilder = DbFileSources.Data.newBuilder(); | |||
for (int i = 1; i <= numberOfLines; i++) { | |||
dataBuilder.addLinesBuilder() | |||
.setLine(i) | |||
.setScmRevision(RandomStringUtils.randomAlphanumeric(15)) | |||
.setScmAuthor(RandomStringUtils.randomAlphanumeric(10)) | |||
.setScmDate(RandomUtils.nextLong()) | |||
.setSource(RandomStringUtils.randomAlphanumeric(20)) | |||
.setLineHits(RandomUtils.nextInt(4)) | |||
.setConditions(RandomUtils.nextInt(4)) | |||
.setCoveredConditions(RandomUtils.nextInt(4)) | |||
.setHighlighting(RandomStringUtils.randomAlphanumeric(40)) | |||
.setSymbols(RandomStringUtils.randomAlphanumeric(30)) | |||
.addAllDuplication(Arrays.asList(RandomUtils.nextInt(200), RandomUtils.nextInt(200))) | |||
.build(); | |||
} | |||
return dataBuilder; | |||
} | |||
} |
@@ -1,96 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.db; | |||
import java.io.IOException; | |||
import java.sql.Connection; | |||
import java.sql.PreparedStatement; | |||
import java.sql.SQLException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.apache.commons.lang.RandomStringUtils; | |||
import org.apache.commons.lang.math.RandomUtils; | |||
import org.sonar.core.util.Uuids; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.protobuf.DbFileSources; | |||
import org.sonar.db.source.FileSourceDto; | |||
import static java.util.Arrays.asList; | |||
public class TestTesting { | |||
private TestTesting() { | |||
// only static stuff | |||
} | |||
public static void updateDataColumn(DbSession session, String fileUuid, List<DbFileSources.Test> tests) throws SQLException { | |||
updateDataColumn(session, fileUuid, FileSourceDto.encodeTestData(tests)); | |||
} | |||
public static void updateDataColumn(DbSession session, String fileUuid, byte[] data) throws SQLException { | |||
Connection connection = session.getConnection(); | |||
PreparedStatement stmt = connection.prepareStatement("UPDATE file_sources SET binary_data = ? WHERE file_uuid=? AND data_type='TEST'"); | |||
stmt.setBytes(1, data); | |||
stmt.setString(2, fileUuid); | |||
stmt.executeUpdate(); | |||
stmt.close(); | |||
connection.commit(); | |||
} | |||
/** | |||
* Generate random data. | |||
*/ | |||
public static List<DbFileSources.Test> newRandomTests(int numberOfTests) { | |||
List<DbFileSources.Test> tests = new ArrayList<>(); | |||
for (int i = 1; i <= numberOfTests; i++) { | |||
DbFileSources.Test.Builder test = DbFileSources.Test.newBuilder() | |||
.setUuid(Uuids.create()) | |||
.setName(RandomStringUtils.randomAlphanumeric(20)) | |||
.setStatus(DbFileSources.Test.TestStatus.FAILURE) | |||
.setStacktrace(RandomStringUtils.randomAlphanumeric(50)) | |||
.setMsg(RandomStringUtils.randomAlphanumeric(30)) | |||
.setExecutionTimeMs(RandomUtils.nextLong()); | |||
for (int j = 0; j < numberOfTests; j++) { | |||
test.addCoveredFile( | |||
DbFileSources.Test.CoveredFile.newBuilder() | |||
.setFileUuid(Uuids.create()) | |||
.addCoveredLine(RandomUtils.nextInt(500))); | |||
} | |||
tests.add(test.build()); | |||
} | |||
return tests; | |||
} | |||
public static DbFileSources.Test.Builder newTest(ComponentDto mainFile, Integer... coveredLines) { | |||
DbFileSources.Test.Builder test = DbFileSources.Test.newBuilder() | |||
.setUuid(Uuids.create()) | |||
.setName(RandomStringUtils.randomAlphanumeric(20)) | |||
.setStatus(DbFileSources.Test.TestStatus.FAILURE) | |||
.setStacktrace(RandomStringUtils.randomAlphanumeric(50)) | |||
.setMsg(RandomStringUtils.randomAlphanumeric(30)) | |||
.setExecutionTimeMs(RandomUtils.nextLong()); | |||
test.addCoveredFile( | |||
DbFileSources.Test.CoveredFile.newBuilder() | |||
.setFileUuid(mainFile.uuid()) | |||
.addAllCoveredLine(asList(coveredLines))); | |||
return test; | |||
} | |||
} |
@@ -1,161 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.index; | |||
import com.google.common.base.Optional; | |||
import java.util.List; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.es.SearchOptions; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.guava.api.Assertions.assertThat; | |||
import static org.sonar.server.test.index.TestIndexDefinition.INDEX_TYPE_TEST; | |||
public class TestIndexTest { | |||
@Rule | |||
public EsTester es = EsTester.create(); | |||
private TestIndex underTest = new TestIndex(es.client(), System2.INSTANCE); | |||
@Test | |||
public void coveredFiles() { | |||
es.putDocuments(INDEX_TYPE_TEST, | |||
newTestDoc("1", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")), | |||
newTestDoc("2", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7"))); | |||
List<CoveredFileDoc> result = underTest.coveredFiles("1"); | |||
assertThat(result).hasSize(3); | |||
assertThat(result).extractingResultOf("fileUuid").containsOnly("main-uuid-3", "main-uuid-4", "main-uuid-5"); | |||
assertThat(result.get(0).coveredLines()).containsOnly(25, 33, 82); | |||
} | |||
@Test | |||
public void searchByTestFileUuid() { | |||
es.putDocuments(INDEX_TYPE_TEST, | |||
newTestDoc("1", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")), | |||
newTestDoc("2", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7")), | |||
newTestDoc("3", "TESTFILE2", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7"))); | |||
List<TestDoc> result = underTest.searchByTestFileUuid("TESTFILE1", searchOptions()).getDocs(); | |||
assertThat(result).hasSize(2); | |||
assertThat(result).extractingResultOf("name").containsOnly("name-1", "name-2"); | |||
} | |||
@Test | |||
public void searchBySourceFileUuidAndLineNumber() { | |||
es.putDocuments(INDEX_TYPE_TEST, | |||
newTestDoc("1", "TESTFILE1", newCoveredFileDoc("10"), newCoveredFileDoc("11"), newCoveredFileDoc("12")), | |||
newTestDoc("2", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")), | |||
newTestDoc("3", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7"))); | |||
List<TestDoc> result = underTest.searchBySourceFileUuidAndLineNumber("main-uuid-5", 82, searchOptions()).getDocs(); | |||
assertThat(result).hasSize(2); | |||
assertThat(result).extractingResultOf("name").containsOnly("name-2", "name-3"); | |||
} | |||
@Test | |||
public void searchByTestUuid() { | |||
es.putDocuments(INDEX_TYPE_TEST, | |||
newTestDoc("1", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")), | |||
newTestDoc("2", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7"))); | |||
TestDoc test = underTest.getByTestUuid("1"); | |||
assertThat(test.testUuid()).isEqualTo("1"); | |||
assertThat(test.fileUuid()).isEqualTo("TESTFILE1"); | |||
assertThat(test.name()).isEqualTo("name-1"); | |||
assertThat(test.durationInMs()).isEqualTo(1L); | |||
assertThat(test.status()).isEqualTo("status-1"); | |||
assertThat(test.message()).isEqualTo("message-1"); | |||
assertThat(test.coveredFiles()).hasSize(3); | |||
assertThat(test.coveredFiles()).extractingResultOf("fileUuid").containsOnly("main-uuid-3", "main-uuid-4", "main-uuid-5"); | |||
} | |||
@Test | |||
public void getNullableByTestUuid() { | |||
es.putDocuments(INDEX_TYPE_TEST, | |||
newTestDoc("1", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")), | |||
newTestDoc("2", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7"))); | |||
Optional<TestDoc> result = underTest.getNullableByTestUuid("1"); | |||
assertThat(result).isPresent(); | |||
TestDoc test = result.get(); | |||
assertThat(test.testUuid()).isEqualTo("1"); | |||
assertThat(test.fileUuid()).isEqualTo("TESTFILE1"); | |||
assertThat(test.name()).isEqualTo("name-1"); | |||
assertThat(test.durationInMs()).isEqualTo(1L); | |||
assertThat(test.status()).isEqualTo("status-1"); | |||
assertThat(test.message()).isEqualTo("message-1"); | |||
assertThat(test.coveredFiles()).hasSize(3); | |||
assertThat(test.coveredFiles()).extractingResultOf("fileUuid").containsOnly("main-uuid-3", "main-uuid-4", "main-uuid-5"); | |||
} | |||
@Test | |||
public void getNullableByTestUuid_with_absent_value() { | |||
Optional<TestDoc> result = underTest.getNullableByTestUuid("unknown-uuid"); | |||
assertThat(result).isAbsent(); | |||
} | |||
@Test | |||
public void searchByTestUuid_with_SearchOptions() { | |||
es.putDocuments(INDEX_TYPE_TEST, | |||
newTestDoc("1", "TESTFILE1", newCoveredFileDoc("3"), newCoveredFileDoc("4"), newCoveredFileDoc("5")), | |||
newTestDoc("2", "TESTFILE1", newCoveredFileDoc("5"), newCoveredFileDoc("6"), newCoveredFileDoc("7"))); | |||
List<TestDoc> result = underTest.searchByTestUuid("1", searchOptions()).getDocs(); | |||
assertThat(result).hasSize(1); | |||
assertThat(result.get(0).testUuid()).isEqualTo("1"); | |||
} | |||
private CoveredFileDoc newCoveredFileDoc(String id) { | |||
return new CoveredFileDoc() | |||
.setFileUuid("main-uuid-" + id) | |||
.setCoveredLines(asList(25, 33, 82)); | |||
} | |||
private TestDoc newTestDoc(String testUuid, String fileUuid, CoveredFileDoc... coveredFiles) { | |||
return new TestDoc() | |||
.setUuid(testUuid) | |||
.setProjectUuid("P1") | |||
.setName("name-" + testUuid) | |||
.setMessage("message-" + testUuid) | |||
.setStackTrace("stacktrace-" + testUuid) | |||
.setStatus("status-" + testUuid) | |||
.setDurationInMs(Long.valueOf(testUuid)) | |||
.setFileUuid(fileUuid) | |||
.setCoveredFiles(asList(coveredFiles)); | |||
} | |||
private SearchOptions searchOptions() { | |||
return new SearchOptions() | |||
.setLimit(100) | |||
.setOffset(0); | |||
} | |||
} |
@@ -1,168 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.index; | |||
import java.io.IOException; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.apache.commons.io.IOUtils; | |||
import org.elasticsearch.common.xcontent.XContentType; | |||
import org.elasticsearch.search.SearchHit; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.test.db.TestTesting; | |||
import static java.lang.String.format; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.doNothing; | |||
import static org.mockito.Mockito.spy; | |||
import static org.mockito.Mockito.verify; | |||
import static org.sonar.server.es.DefaultIndexSettings.REFRESH_IMMEDIATE; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_MESSAGE; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_NAME; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STACKTRACE; | |||
import static org.sonar.server.test.index.TestIndexDefinition.INDEX_TYPE_TEST; | |||
public class TestIndexerTest { | |||
private System2 system2 = System2.INSTANCE; | |||
@Rule | |||
public EsTester es = EsTester.create(); | |||
@Rule | |||
public DbTester db = DbTester.create(system2); | |||
private TestIndexer underTest = new TestIndexer(db.getDbClient(), es.client()); | |||
@Test | |||
public void index_on_startup() { | |||
TestIndexer indexer = spy(underTest); | |||
doNothing().when(indexer).indexOnStartup(null); | |||
indexer.indexOnStartup(null); | |||
verify(indexer).indexOnStartup(null); | |||
} | |||
@Test | |||
public void index_tests() throws Exception { | |||
db.prepareDbUnit(getClass(), "db.xml"); | |||
TestTesting.updateDataColumn(db.getSession(), "FILE_UUID", TestTesting.newRandomTests(3)); | |||
underTest.indexOnStartup(null); | |||
assertThat(countDocuments()).isEqualTo(3); | |||
} | |||
@Test | |||
public void index_tests_from_project() throws Exception { | |||
db.prepareDbUnit(getClass(), "db.xml"); | |||
TestTesting.updateDataColumn(db.getSession(), "FILE_UUID", TestTesting.newRandomTests(3)); | |||
underTest.indexOnAnalysis("PROJECT_UUID"); | |||
assertThat(countDocuments()).isEqualTo(3); | |||
} | |||
@Test | |||
public void index_nothing_from_unknown_project() throws Exception { | |||
db.prepareDbUnit(getClass(), "db.xml"); | |||
TestTesting.updateDataColumn(db.getSession(), "FILE_UUID", TestTesting.newRandomTests(3)); | |||
underTest.indexOnAnalysis("UNKNOWN"); | |||
assertThat(countDocuments()).isZero(); | |||
} | |||
@Test | |||
public void delete_file_by_uuid() throws Exception { | |||
indexTest("P1", "F1", "T1", "U111"); | |||
indexTest("P1", "F1", "T2", "U112"); | |||
indexTest("P1", "F2", "T1", "U121"); | |||
underTest.deleteByFile("F1"); | |||
List<SearchHit> hits = getDocuments(); | |||
Map<String, Object> document = hits.get(0).getSource(); | |||
assertThat(hits).hasSize(1); | |||
assertThat(document.get(FIELD_NAME)).isEqualTo("NAME_1"); | |||
assertThat(document.get(FIELD_FILE_UUID)).isEqualTo("F2"); | |||
} | |||
@Test | |||
public void long_message_can_be_indexed() throws Exception { | |||
indexTest("P3", "F1", "long_message", "U111"); | |||
assertThat(countDocuments()).isEqualTo(1); | |||
List<SearchHit> hits = getDocuments(); | |||
Map<String, Object> document = hits.get(0).getSource(); | |||
assertThat(hits).hasSize(1); | |||
assertThat(document.get(FIELD_MESSAGE).toString()).hasSize(50000); | |||
assertThat(document.get(FIELD_FILE_UUID)).isEqualTo("F1"); | |||
} | |||
@Test | |||
public void long_stacktrace_can_be_indexed() throws Exception { | |||
indexTest("P3", "F1", "long_stacktrace", "U111"); | |||
assertThat(countDocuments()).isEqualTo(1); | |||
List<SearchHit> hits = getDocuments(); | |||
Map<String, Object> document = hits.get(0).getSource(); | |||
assertThat(hits).hasSize(1); | |||
assertThat(document.get(FIELD_STACKTRACE).toString()).hasSize(50000); | |||
assertThat(document.get(FIELD_FILE_UUID)).isEqualTo("F1"); | |||
} | |||
@Test | |||
public void long_name_can_be_indexed() throws Exception { | |||
indexTest("P3", "F1", "long_name", "U111"); | |||
assertThat(countDocuments()).isEqualTo(1); | |||
List<SearchHit> hits = getDocuments(); | |||
Map<String, Object> document = hits.get(0).getSource(); | |||
assertThat(hits).hasSize(1); | |||
assertThat(document.get(FIELD_NAME).toString()).hasSize(50000); | |||
assertThat(document.get(FIELD_FILE_UUID)).isEqualTo("F1"); | |||
} | |||
private void indexTest(String projectUuid, String fileUuid, String testName, String uuid) throws IOException { | |||
String json = IOUtils.toString(getClass().getResource(format("%s/%s_%s_%s.json", getClass().getSimpleName(), projectUuid, fileUuid, testName))); | |||
es.client().prepareIndex(INDEX_TYPE_TEST) | |||
.setId(uuid) | |||
.setRouting(projectUuid) | |||
.setSource(json, XContentType.JSON) | |||
.setRefreshPolicy(REFRESH_IMMEDIATE) | |||
.get(); | |||
} | |||
private List<SearchHit> getDocuments() { | |||
return es.getDocuments(INDEX_TYPE_TEST); | |||
} | |||
private long countDocuments() { | |||
return es.countDocuments(INDEX_TYPE_TEST); | |||
} | |||
} |
@@ -1,192 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.index; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.elasticsearch.action.update.UpdateRequest; | |||
import org.junit.After; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.utils.log.LogTester; | |||
import org.sonar.api.utils.log.LoggerLevel; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.protobuf.DbFileSources; | |||
import org.sonar.server.source.index.FileSourcesUpdaterHelper; | |||
import org.sonar.server.test.db.TestTesting; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.data.MapEntry.entry; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_COVERED_FILES; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_DURATION_IN_MS; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_FILE_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_MESSAGE; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_NAME; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_PROJECT_UUID; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STACKTRACE; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_STATUS; | |||
import static org.sonar.server.test.index.TestIndexDefinition.FIELD_TEST_UUID; | |||
public class TestResultSetIteratorTest { | |||
@Rule | |||
public DbTester dbTester = DbTester.create(System2.INSTANCE); | |||
@Rule | |||
public LogTester logTester = new LogTester(); | |||
TestResultSetIterator underTest; | |||
private static List<DbFileSources.Test> newFakeTests(int numberOfTests) { | |||
List<DbFileSources.Test> tests = new ArrayList<>(); | |||
for (int i = 1; i <= numberOfTests; i++) { | |||
DbFileSources.Test.Builder test = DbFileSources.Test.newBuilder() | |||
.setUuid("TEST_FILE_UUID_" + i) | |||
.setName("NAME_" + i) | |||
.setStatus(DbFileSources.Test.TestStatus.FAILURE) | |||
.setStacktrace("STACKTRACE_" + i) | |||
.setMsg("MESSAGE_" + i) | |||
.setExecutionTimeMs(i); | |||
for (int j = 1; j <= numberOfTests; j++) { | |||
test.addCoveredFile( | |||
DbFileSources.Test.CoveredFile.newBuilder() | |||
.setFileUuid("MAIN_FILE_UUID_" + j) | |||
.addCoveredLine(j)); | |||
} | |||
tests.add(test.build()); | |||
} | |||
return tests; | |||
} | |||
@After | |||
public void after() { | |||
if (underTest != null) { | |||
underTest.close(); | |||
} | |||
} | |||
@Test | |||
public void traverse_db() throws Exception { | |||
dbTester.prepareDbUnit(getClass(), "shared.xml"); | |||
TestTesting.updateDataColumn(dbTester.getSession(), "F1", newFakeTests(3)); | |||
underTest = TestResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), null); | |||
FileSourcesUpdaterHelper.Row row = underTest.next(); | |||
assertThat(row.getProjectUuid()).isEqualTo("P1"); | |||
assertThat(row.getFileUuid()).isEqualTo("F1"); | |||
assertThat(row.getUpdatedAt()).isEqualTo(1416239042000L); | |||
assertThat(row.getUpdateRequests()).hasSize(3); | |||
UpdateRequest firstRequest = row.getUpdateRequests().get(0); | |||
Map<String, Object> doc = firstRequest.doc().sourceAsMap(); | |||
assertThat(doc).contains( | |||
entry(FIELD_PROJECT_UUID, "P1"), | |||
entry(FIELD_FILE_UUID, "F1"), | |||
entry(FIELD_TEST_UUID, "TEST_FILE_UUID_1"), | |||
entry(FIELD_STATUS, "FAILURE"), | |||
entry(FIELD_MESSAGE, "MESSAGE_1"), | |||
entry(FIELD_DURATION_IN_MS, 1), | |||
entry(FIELD_STACKTRACE, "STACKTRACE_1"), | |||
entry(FIELD_NAME, "NAME_1")); | |||
} | |||
/** | |||
* File with one line. No metadata available on the line. | |||
*/ | |||
@Test | |||
public void minimal_data() throws Exception { | |||
dbTester.prepareDbUnit(getClass(), "shared.xml"); | |||
List<DbFileSources.Test> tests = Arrays.asList( | |||
DbFileSources.Test.newBuilder() | |||
.setUuid("U1") | |||
.setName("N1") | |||
.build()); | |||
TestTesting.updateDataColumn(dbTester.getSession(), "F1", tests); | |||
underTest = TestResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), null); | |||
FileSourcesUpdaterHelper.Row row = underTest.next(); | |||
assertThat(row.getProjectUuid()).isEqualTo("P1"); | |||
assertThat(row.getFileUuid()).isEqualTo("F1"); | |||
assertThat(row.getUpdatedAt()).isEqualTo(1416239042000L); | |||
assertThat(row.getUpdateRequests()).hasSize(1); | |||
UpdateRequest firstRequest = row.getUpdateRequests().get(0); | |||
Map<String, Object> doc = firstRequest.doc().sourceAsMap(); | |||
assertThat(doc).contains( | |||
entry(FIELD_PROJECT_UUID, "P1"), | |||
entry(FIELD_FILE_UUID, "F1"), | |||
entry(FIELD_TEST_UUID, "U1"), | |||
entry(FIELD_NAME, "N1")); | |||
// null values | |||
assertThat(doc).containsKeys( | |||
FIELD_DURATION_IN_MS, | |||
FIELD_STACKTRACE, | |||
FIELD_MESSAGE, | |||
FIELD_STATUS, | |||
FIELD_COVERED_FILES); | |||
} | |||
@Test | |||
public void filter_by_project() throws Exception { | |||
dbTester.prepareDbUnit(getClass(), "filter_by_project.xml"); | |||
TestTesting.updateDataColumn(dbTester.getSession(), "F1", newFakeTests(1)); | |||
underTest = TestResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), "P1"); | |||
FileSourcesUpdaterHelper.Row row = underTest.next(); | |||
assertThat(row.getProjectUuid()).isEqualTo("P1"); | |||
assertThat(row.getFileUuid()).isEqualTo("F1"); | |||
// File from other project P2 is not returned | |||
assertThat(underTest.hasNext()).isFalse(); | |||
} | |||
@Test | |||
public void read_does_not_fail_if_corrupted_data() throws Exception { | |||
dbTester.prepareDbUnit(getClass(), "shared.xml"); | |||
TestTesting.updateDataColumn(dbTester.getSession(), "F1", "THIS_IS_NOT_PROTOBUF".getBytes()); | |||
underTest = TestResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), null); | |||
FileSourcesUpdaterHelper.Row row = underTest.next(); | |||
assertThat(row.getFileUuid()).isEqualTo("F1"); | |||
assertThat(row.getUpdateRequests()).isEmpty(); | |||
assertThat(underTest.hasNext()).isFalse(); | |||
assertThat(logTester.logs(LoggerLevel.WARN)).contains("Invalid file_sources.binary_data on row with file_uuid='F1', test file will be ignored"); | |||
} | |||
@Test | |||
public void read_does_not_fail_if_null_data() throws Exception { | |||
dbTester.prepareDbUnit(getClass(), "shared.xml"); | |||
TestTesting.updateDataColumn(dbTester.getSession(), "F1", (byte[])null); | |||
underTest = TestResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), null); | |||
FileSourcesUpdaterHelper.Row row = underTest.next(); | |||
assertThat(row.getFileUuid()).isEqualTo("F1"); | |||
assertThat(row.getUpdateRequests()).isEmpty(); | |||
assertThat(underTest.hasNext()).isFalse(); | |||
} | |||
} |
@@ -1,11 +0,0 @@ | |||
{ | |||
"projectUuid": "P1", | |||
"fileUuid": "F1", | |||
"testUuid": "U111", | |||
"name": "NAME_1", | |||
"status": "FAILURE", | |||
"durationInMs": 100000, | |||
"message": "MESSAGE_1", | |||
"stacktrace": "STACKTRACE_1", | |||
"updatedAt": "2014-01-01T23:45:01.8+01:00" | |||
} |
@@ -1,11 +0,0 @@ | |||
{ | |||
"projectUuid": "P1", | |||
"fileUuid": "F1", | |||
"testUuid": "U112", | |||
"name": "NAME_2", | |||
"status": "FAILURE", | |||
"durationInMs": 100000, | |||
"message": "MESSAGE_1", | |||
"stacktrace": "STACKTRACE_1", | |||
"updatedAt": "2014-01-01T23:45:01.8+01:00" | |||
} |
@@ -1,11 +0,0 @@ | |||
{ | |||
"projectUuid": "P1", | |||
"fileUuid": "F2", | |||
"testUuid": "U121", | |||
"name": "NAME_1", | |||
"status": "FAILURE", | |||
"durationInMs": 100000, | |||
"message": "MESSAGE_1", | |||
"stacktrace": "STACKTRACE_1", | |||
"updatedAt": "2014-01-01T23:45:01.8+01:00" | |||
} |
@@ -1,11 +0,0 @@ | |||
{ | |||
"projectUuid": "P2", | |||
"fileUuid": "F3", | |||
"testUuid": "U231", | |||
"name": "NAME_1", | |||
"status": "FAILURE", | |||
"durationInMs": 100000, | |||
"message": "MESSAGE_1", | |||
"stacktrace": "STACKTRACE_1", | |||
"updatedAt": "2014-01-01T23:45:01.8+01:00" | |||
} |
@@ -1,14 +0,0 @@ | |||
<dataset> | |||
<file_sources id="1" | |||
project_uuid="PROJECT_UUID" | |||
file_uuid="FILE_UUID" | |||
line_count="0" | |||
created_at="1416238020000" | |||
updated_at="1416239042000" | |||
binary_data="" | |||
data_hash="" | |||
data_type="TEST" | |||
/> | |||
</dataset> |
@@ -1,23 +0,0 @@ | |||
<dataset> | |||
<file_sources id="1" | |||
project_uuid="P1" | |||
file_uuid="F1" | |||
created_at="1416238020000" | |||
updated_at="1416239042000" | |||
line_count="0" | |||
binary_data="" | |||
data_hash="" | |||
data_type="TEST"/> | |||
<file_sources id="2" | |||
project_uuid="P2" | |||
file_uuid="F2" | |||
created_at="1416238020000" | |||
updated_at="1416239042000" | |||
line_count="0" | |||
binary_data="" | |||
data_hash="" | |||
data_type="TEST"/> | |||
</dataset> |
@@ -1,23 +0,0 @@ | |||
<dataset> | |||
<file_sources id="1" | |||
project_uuid="P1" | |||
file_uuid="F1" | |||
created_at="1416238020000" | |||
updated_at="1416239042000" | |||
line_count="0" | |||
binary_data="" | |||
data_hash="" | |||
data_type="TEST"/> | |||
<file_sources id="2" | |||
project_uuid="P1" | |||
file_uuid="F2" | |||
created_at="1416238020000" | |||
updated_at="1300000000000" | |||
line_count="0" | |||
binary_data="" | |||
data_hash="" | |||
data_type="TEST"/> | |||
</dataset> |
@@ -1,11 +0,0 @@ | |||
CREATE TABLE "FILE_SOURCES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"PROJECT_UUID" VARCHAR(50) NOT NULL, | |||
"FILE_UUID" VARCHAR(50) NOT NULL, | |||
"BINARY_DATA" BINARY(167772150), | |||
"DATA_HASH" VARCHAR(50) NOT NULL, | |||
"DATA_TYPE" VARCHAR(50), | |||
"CREATED_AT" BIGINT NOT NULL, | |||
"UPDATED_AT" BIGINT NOT NULL | |||
); |
@@ -1,13 +0,0 @@ | |||
<dataset> | |||
<file_sources id="1" | |||
project_uuid="P1" | |||
file_uuid="F1" | |||
created_at="1416238020000" | |||
updated_at="1416239042000" | |||
line_count="0" | |||
binary_data="" | |||
data_hash="" | |||
data_type="TEST"/> | |||
</dataset> |
@@ -199,10 +199,7 @@ import org.sonar.server.startup.LogServerId; | |||
import org.sonar.server.telemetry.TelemetryClient; | |||
import org.sonar.server.telemetry.TelemetryDaemon; | |||
import org.sonar.server.telemetry.TelemetryDataLoader; | |||
import org.sonar.server.test.index.TestIndex; | |||
import org.sonar.server.test.index.TestIndexDefinition; | |||
import org.sonar.server.test.index.TestIndexer; | |||
import org.sonar.server.test.ws.CoveredFilesAction; | |||
import org.sonar.server.test.ws.TestsWs; | |||
import org.sonar.server.text.MacroInterpreter; | |||
import org.sonar.server.ui.DeprecatedViews; | |||
@@ -479,11 +476,7 @@ public class PlatformLevel4 extends PlatformLevel { | |||
// Tests | |||
TestsWs.class, | |||
CoveredFilesAction.class, | |||
org.sonar.server.test.ws.ListAction.class, | |||
TestIndexDefinition.class, | |||
TestIndex.class, | |||
TestIndexer.class, | |||
// Settings | |||
PersistentSettings.class, |
@@ -65,7 +65,7 @@ public class SourceService { | |||
private <E> Optional<Iterable<E>> getLines(DbSession dbSession, String fileUuid, int from, int toInclusive, Function<DbFileSources.Line, E> function) { | |||
verifyLine(from); | |||
checkArgument(toInclusive >= from, String.format("Line number must greater than or equal to %d, got %d", from, toInclusive)); | |||
FileSourceDto dto = dbClient.fileSourceDao().selectSourceByFileUuid(dbSession, fileUuid); | |||
FileSourceDto dto = dbClient.fileSourceDao().selectByFileUuid(dbSession, fileUuid); | |||
if (dto == null) { | |||
return Optional.empty(); | |||
} |
@@ -1,124 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.ws; | |||
import com.google.common.base.Function; | |||
import com.google.common.collect.Lists; | |||
import com.google.common.collect.Maps; | |||
import com.google.common.io.Resources; | |||
import java.util.List; | |||
import java.util.Map; | |||
import javax.annotation.Nonnull; | |||
import org.sonar.api.server.ws.Change; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.Response; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.api.web.UserRole; | |||
import org.sonar.core.util.Uuids; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.server.test.index.CoveredFileDoc; | |||
import org.sonar.server.test.index.TestDoc; | |||
import org.sonar.server.test.index.TestIndex; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonarqube.ws.Tests; | |||
import static org.sonar.core.util.Protobuf.setNullable; | |||
import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; | |||
import static org.sonar.server.ws.WsUtils.writeProtobuf; | |||
public class CoveredFilesAction implements TestsWsAction { | |||
public static final String TEST_ID = "testId"; | |||
private final DbClient dbClient; | |||
private final TestIndex index; | |||
private final UserSession userSession; | |||
public CoveredFilesAction(DbClient dbClient, TestIndex index, UserSession userSession) { | |||
this.dbClient = dbClient; | |||
this.index = index; | |||
this.userSession = userSession; | |||
} | |||
@Override | |||
public void define(WebService.NewController controller) { | |||
WebService.NewAction action = controller.createAction("covered_files") | |||
.setDescription("Get the list of source files covered by a test. Require Browse permission on test file's project") | |||
.setSince("4.4") | |||
.setResponseExample(Resources.getResource(getClass(), "tests-example-covered-files.json")) | |||
.setDeprecatedSince("5.6") | |||
.setHandler(this) | |||
.setChangelog(new Change("6.6", "\"branch\" field is now returned")) | |||
.addPagingParams(100); | |||
action | |||
.createParam(TEST_ID) | |||
.setRequired(true) | |||
.setDescription("Test ID") | |||
.setExampleValue(Uuids.UUID_EXAMPLE_01); | |||
} | |||
@Override | |||
public void handle(Request request, Response response) throws Exception { | |||
String testId = request.mandatoryParam(TEST_ID); | |||
TestDoc testDoc = checkFoundWithOptional(index.getNullableByTestUuid(testId), "Test with id '%s' is not found", testId); | |||
userSession.checkComponentUuidPermission(UserRole.CODEVIEWER, testDoc.fileUuid()); | |||
List<CoveredFileDoc> coveredFiles = index.coveredFiles(testId); | |||
Map<String, ComponentDto> componentsByUuid = buildComponentsByUuid(coveredFiles); | |||
Tests.CoveredFilesResponse.Builder responseBuilder = Tests.CoveredFilesResponse.newBuilder(); | |||
if (!coveredFiles.isEmpty()) { | |||
for (CoveredFileDoc doc : coveredFiles) { | |||
Tests.CoveredFilesResponse.CoveredFile.Builder fileBuilder = Tests.CoveredFilesResponse.CoveredFile.newBuilder(); | |||
fileBuilder.setId(doc.fileUuid()); | |||
fileBuilder.setCoveredLines(doc.coveredLines().size()); | |||
ComponentDto component = componentsByUuid.get(doc.fileUuid()); | |||
if (component != null) { | |||
fileBuilder.setKey(component.getKey()); | |||
fileBuilder.setLongName(component.longName()); | |||
setNullable(component.getBranch(), fileBuilder::setBranch); | |||
} | |||
responseBuilder.addFiles(fileBuilder); | |||
} | |||
} | |||
writeProtobuf(responseBuilder.build(), request, response); | |||
} | |||
private Map<String, ComponentDto> buildComponentsByUuid(List<CoveredFileDoc> coveredFiles) { | |||
List<String> sourceFileUuids = Lists.transform(coveredFiles, new CoveredFileToFileUuidFunction()); | |||
List<ComponentDto> components; | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
components = dbClient.componentDao().selectByUuids(dbSession, sourceFileUuids); | |||
} | |||
return Maps.uniqueIndex(components, ComponentDto::uuid); | |||
} | |||
private static class CoveredFileToFileUuidFunction implements Function<CoveredFileDoc, String> { | |||
@Override | |||
public String apply(@Nonnull CoveredFileDoc coveredFile) { | |||
return coveredFile.fileUuid(); | |||
} | |||
} | |||
} |
@@ -1,266 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.ws; | |||
import com.google.common.base.Function; | |||
import com.google.common.collect.Lists; | |||
import com.google.common.collect.Maps; | |||
import com.google.common.io.Resources; | |||
import java.util.List; | |||
import java.util.Map; | |||
import javax.annotation.Nonnull; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.server.ws.Change; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.Response; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.core.util.Uuids; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.es.SearchOptions; | |||
import org.sonar.server.es.SearchResult; | |||
import org.sonar.server.test.index.CoveredFileDoc; | |||
import org.sonar.server.test.index.TestDoc; | |||
import org.sonar.server.test.index.TestIndex; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonar.server.ws.KeyExamples; | |||
import org.sonar.server.ws.WsUtils; | |||
import org.sonarqube.ws.Common; | |||
import org.sonarqube.ws.Tests; | |||
import static org.sonar.api.server.ws.WebService.Param.PAGE; | |||
import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE; | |||
import static org.sonar.api.web.UserRole.CODEVIEWER; | |||
import static org.sonar.core.util.Protobuf.setNullable; | |||
import static org.sonar.server.es.SearchOptions.MAX_LIMIT; | |||
import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; | |||
import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001; | |||
import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; | |||
public class ListAction implements TestsWsAction { | |||
public static final String TEST_ID = "testId"; | |||
public static final String TEST_FILE_ID = "testFileId"; | |||
public static final String TEST_FILE_KEY = "testFileKey"; | |||
public static final String SOURCE_FILE_ID = "sourceFileId"; | |||
public static final String SOURCE_FILE_KEY = "sourceFileKey"; | |||
public static final String SOURCE_FILE_LINE_NUMBER = "sourceFileLineNumber"; | |||
public static final String PARAM_BRANCH = "branch"; | |||
public static final String PARAM_PULL_REQUEST = "pullRequest"; | |||
private final DbClient dbClient; | |||
private final TestIndex testIndex; | |||
private final UserSession userSession; | |||
private final ComponentFinder componentFinder; | |||
public ListAction(DbClient dbClient, TestIndex testIndex, UserSession userSession, ComponentFinder componentFinder) { | |||
this.dbClient = dbClient; | |||
this.testIndex = testIndex; | |||
this.userSession = userSession; | |||
this.componentFinder = componentFinder; | |||
} | |||
@Override | |||
public void define(WebService.NewController controller) { | |||
WebService.NewAction action = controller | |||
.createAction("list") | |||
.setDescription(String.format( | |||
"Get the list of tests either in a test file or that test a given line of source code.<br /> " + | |||
"Requires 'Browse' permission on the file's project.<br /> " + | |||
"One (and only one) of the following combination of parameters must be provided: " + | |||
"<ul>" + | |||
"<li>%s - get a specific test</li>" + | |||
"<li>%s - get the tests in a test file</li>" + | |||
"<li>%s - get the tests in a test file</li>" + | |||
"<li>%s and %6$s - get the tests that cover a specific line of code</li>" + | |||
"<li>%s and %6$s - get the tests that cover a specific line of code</li>" + | |||
"</ul>", | |||
TEST_ID, TEST_FILE_ID, TEST_FILE_KEY, SOURCE_FILE_ID, SOURCE_FILE_KEY, SOURCE_FILE_LINE_NUMBER)) | |||
.setSince("5.2") | |||
.setResponseExample(Resources.getResource(getClass(), "tests-example-list.json")) | |||
.setDeprecatedSince("5.6") | |||
.setHandler(this) | |||
.setChangelog(new Change("6.6", "\"fileBranch\" field is now returned")) | |||
.setChangelog(new Change("7.1", "\"filePullRequest\" field is now returned")) | |||
.addPagingParams(100, MAX_LIMIT); | |||
action | |||
.createParam(TEST_FILE_ID) | |||
.setDescription("ID of test file") | |||
.setExampleValue(Uuids.UUID_EXAMPLE_01); | |||
action | |||
.createParam(TEST_FILE_KEY) | |||
.setDescription("Key of test file") | |||
.setExampleValue("MY_PROJECT:src/test/java/foo/BarTest.java"); | |||
action | |||
.createParam(TEST_ID) | |||
.setDescription("ID of test") | |||
.setExampleValue(Uuids.UUID_EXAMPLE_02); | |||
action | |||
.createParam(SOURCE_FILE_ID) | |||
.setDescription("ID of source file. Must be provided with the source file line number.") | |||
.setExampleValue(Uuids.UUID_EXAMPLE_03); | |||
action | |||
.createParam(SOURCE_FILE_KEY) | |||
.setSince("5.4") | |||
.setDescription("Key of source file. Must be provided with the source file line number.") | |||
.setExampleValue(KeyExamples.KEY_FILE_EXAMPLE_001); | |||
action | |||
.createParam(SOURCE_FILE_LINE_NUMBER) | |||
.setDescription("Source file line number. Must be provided with the source file ID or key.") | |||
.setExampleValue("10"); | |||
action.createParam(PARAM_BRANCH) | |||
.setDescription("Branch key") | |||
.setSince("6.6") | |||
.setInternal(true) | |||
.setExampleValue(KEY_BRANCH_EXAMPLE_001); | |||
action.createParam(PARAM_PULL_REQUEST) | |||
.setDescription("Pull request id") | |||
.setSince("7.1") | |||
.setInternal(true) | |||
.setExampleValue(KEY_PULL_REQUEST_EXAMPLE_001); | |||
} | |||
@Override | |||
public void handle(Request request, Response response) throws Exception { | |||
String testUuid = request.param(TEST_ID); | |||
String testFileUuid = request.param(TEST_FILE_ID); | |||
String testFileKey = request.param(TEST_FILE_KEY); | |||
String sourceFileUuid = request.param(SOURCE_FILE_ID); | |||
String sourceFileKey = request.param(SOURCE_FILE_KEY); | |||
String branch = request.param(PARAM_BRANCH); | |||
String pullRequest = request.param(PARAM_PULL_REQUEST); | |||
Integer sourceFileLineNumber = request.paramAsInt(SOURCE_FILE_LINE_NUMBER); | |||
SearchOptions searchOptions = new SearchOptions().setPage( | |||
request.mandatoryParamAsInt(PAGE), | |||
request.mandatoryParamAsInt(PAGE_SIZE)); | |||
SearchResult<TestDoc> tests; | |||
Map<String, ComponentDto> componentsByTestFileUuid; | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
tests = searchTests(dbSession, testUuid, testFileUuid, testFileKey, sourceFileUuid, sourceFileKey, branch, pullRequest, sourceFileLineNumber, searchOptions); | |||
componentsByTestFileUuid = buildComponentsByTestFileUuid(dbSession, tests.getDocs()); | |||
} | |||
Tests.ListResponse.Builder responseBuilder = Tests.ListResponse.newBuilder(); | |||
responseBuilder.setPaging(Common.Paging.newBuilder() | |||
.setPageIndex(searchOptions.getPage()) | |||
.setPageSize(searchOptions.getLimit()) | |||
.setTotal((int) tests.getTotal()) | |||
.build()); | |||
for (TestDoc testDoc : tests.getDocs()) { | |||
Tests.Test.Builder testBuilder = Tests.Test.newBuilder(); | |||
testBuilder.setId(testDoc.testUuid()); | |||
testBuilder.setName(StringUtils.defaultString(testDoc.name())); | |||
testBuilder.setFileId(testDoc.fileUuid()); | |||
ComponentDto component = componentsByTestFileUuid.get(testDoc.fileUuid()); | |||
if (component != null) { | |||
testBuilder.setFileKey(component.getKey()); | |||
testBuilder.setFileName(component.longName()); | |||
setNullable(component.getBranch(), testBuilder::setFileBranch); | |||
setNullable(component.getPullRequest(), testBuilder::setFilePullRequest); | |||
} | |||
testBuilder.setStatus(Tests.TestStatus.valueOf(testDoc.status())); | |||
if (testDoc.durationInMs() != null) { | |||
testBuilder.setDurationInMs(testDoc.durationInMs()); | |||
} | |||
testBuilder.setCoveredLines(coveredLines(testDoc.coveredFiles())); | |||
if (testDoc.message() != null) { | |||
testBuilder.setMessage(testDoc.message()); | |||
} | |||
if (testDoc.stackTrace() != null) { | |||
testBuilder.setStacktrace(testDoc.stackTrace()); | |||
} | |||
responseBuilder.addTests(testBuilder.build()); | |||
} | |||
WsUtils.writeProtobuf(responseBuilder.build(), request, response); | |||
} | |||
private static int coveredLines(List<CoveredFileDoc> coveredFiles) { | |||
int numberOfLinesCovered = 0; | |||
for (CoveredFileDoc coveredFile : coveredFiles) { | |||
numberOfLinesCovered += coveredFile.coveredLines().size(); | |||
} | |||
return numberOfLinesCovered; | |||
} | |||
private Map<String, ComponentDto> buildComponentsByTestFileUuid(DbSession dbSession, List<TestDoc> tests) { | |||
List<String> fileUuids = Lists.transform(tests, new TestToFileUuidFunction()); | |||
List<ComponentDto> components = dbClient.componentDao().selectByUuids(dbSession, fileUuids); | |||
return Maps.uniqueIndex(components, ComponentDto::uuid); | |||
} | |||
private SearchResult<TestDoc> searchTests(DbSession dbSession, @Nullable String testUuid, @Nullable String testFileUuid, @Nullable String testFileKey, | |||
@Nullable String sourceFileUuid, @Nullable String sourceFileKey, @Nullable String branch, @Nullable String pullRequest, | |||
@Nullable Integer sourceFileLineNumber, SearchOptions searchOptions) { | |||
if (testUuid != null) { | |||
TestDoc testDoc = checkFoundWithOptional(testIndex.getNullableByTestUuid(testUuid), "Test with id '%s' is not found", testUuid); | |||
checkComponentUuidPermission(dbSession, testDoc.fileUuid()); | |||
return testIndex.searchByTestUuid(testUuid, searchOptions); | |||
} | |||
if (testFileUuid != null) { | |||
checkComponentUuidPermission(dbSession, testFileUuid); | |||
return testIndex.searchByTestFileUuid(testFileUuid, searchOptions); | |||
} | |||
if (testFileKey != null) { | |||
ComponentDto testFile = componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, testFileKey, branch, pullRequest); | |||
userSession.checkComponentPermission(CODEVIEWER, testFile); | |||
return testIndex.searchByTestFileUuid(testFile.uuid(), searchOptions); | |||
} | |||
if (sourceFileUuid != null && sourceFileLineNumber != null) { | |||
ComponentDto sourceFile = componentFinder.getByUuid(dbSession, sourceFileUuid); | |||
userSession.checkComponentPermission(CODEVIEWER, sourceFile); | |||
return testIndex.searchBySourceFileUuidAndLineNumber(sourceFile.uuid(), sourceFileLineNumber, searchOptions); | |||
} | |||
if (sourceFileKey != null && sourceFileLineNumber != null) { | |||
ComponentDto sourceFile = componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, sourceFileKey, branch, pullRequest); | |||
userSession.checkComponentPermission(CODEVIEWER, sourceFile); | |||
return testIndex.searchBySourceFileUuidAndLineNumber(sourceFile.uuid(), sourceFileLineNumber, searchOptions); | |||
} | |||
throw new IllegalArgumentException( | |||
"One (and only one) of the following combination of parameters must be provided: 1) test UUID. 2) test file UUID. " + | |||
"3) test file key. 4) source file ID or key with a source file line number."); | |||
} | |||
private void checkComponentUuidPermission(DbSession dbSession, String componentUuid) { | |||
ComponentDto component = componentFinder.getByUuid(dbSession, componentUuid); | |||
userSession.checkComponentPermission(CODEVIEWER, component); | |||
} | |||
private static class TestToFileUuidFunction implements Function<TestDoc, String> { | |||
@Override | |||
public String apply(@Nonnull TestDoc testDoc) { | |||
return testDoc.fileUuid(); | |||
} | |||
} | |||
} |
@@ -19,25 +19,34 @@ | |||
*/ | |||
package org.sonar.server.test.ws; | |||
import org.sonar.api.server.ws.Change; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.server.ws.RemovedWebServiceHandler; | |||
public class TestsWs implements WebService { | |||
private final TestsWsAction[] actions; | |||
public TestsWs(TestsWsAction... actions) { | |||
this.actions = actions; | |||
} | |||
@Override | |||
public void define(Context context) { | |||
NewController controller = context.createController("api/tests") | |||
.setSince("4.4") | |||
.setDescription("Get details on test files. See also api/sources. Deprecated since 5.6."); | |||
.setDescription("Removed in 7.6"); | |||
for (TestsWsAction action : actions) { | |||
action.define(controller); | |||
} | |||
controller.createAction("covered_files") | |||
.setDescription("This web API is no longer supported") | |||
.setSince("4.4") | |||
.setDeprecatedSince("5.6") | |||
.setChangelog(new Change("7.6", "This action has been removed")) | |||
.setResponseExample(RemovedWebServiceHandler.INSTANCE.getResponseExample()) | |||
.setHandler(RemovedWebServiceHandler.INSTANCE); | |||
controller | |||
.createAction("list") | |||
.setDescription("This web API is no longer supported") | |||
.setSince("5.2") | |||
.setDeprecatedSince("5.6") | |||
.setChangelog(new Change("7.6", "This action has been removed")) | |||
.setResponseExample(RemovedWebServiceHandler.INSTANCE.getResponseExample()) | |||
.setHandler(RemovedWebServiceHandler.INSTANCE); | |||
controller.done(); | |||
} |
@@ -1,26 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.ws; | |||
import org.sonar.server.ws.WsAction; | |||
public interface TestsWsAction extends WsAction { | |||
// marker interface | |||
} |
@@ -1,14 +0,0 @@ | |||
{ | |||
"files": [ | |||
{ | |||
"key": "org.codehaus.sonar:sonar-server:src/main/java/org/sonar/server/paging/PagedResult.java", | |||
"longName": "src/main/java/org/sonar/server/paging/PagedResult.java", | |||
"coveredLines": 5 | |||
}, | |||
{ | |||
"key": "org.codehaus.sonar:sonar-server:src/main/java/org/sonar/server/rule/RuleDocumentParser.java", | |||
"longName": "src/main/java/org/sonar/server/rule/RuleDocumentParser.java", | |||
"coveredLines": 38 | |||
} | |||
] | |||
} |
@@ -1,31 +0,0 @@ | |||
{ | |||
"paging": { | |||
"pageIndex": 1, | |||
"pageSize": 10, | |||
"total": 2 | |||
}, | |||
"tests": [ | |||
{ | |||
"id": "AU-TpxcB-iU5OvuD2FL7", | |||
"name": "find_by_params", | |||
"status": "OK", | |||
"fileId": "AU-TpxcB-iU5OvuD2Fd8", | |||
"fileKey": "org.codehaus.sonar:sonar-server:src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java", | |||
"fileName": "src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java", | |||
"durationInMs": 10, | |||
"coveredLines": 89 | |||
}, | |||
{ | |||
"id": "AU-TpxcB-iU5OvuD2FP9", | |||
"name": "find_rules_by_characteristics", | |||
"status": "ERROR", | |||
"fileId": "AU-TpxcB-iU5OvuD2FR2", | |||
"fileKey": "org.codehaus.sonar:sonar-server:src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java", | |||
"fileName": "src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java", | |||
"durationInMs": 97, | |||
"coveredLines": 0, | |||
"message": "expected:<true> but was:<false>", | |||
"stackTrace": "java.lang.AssertionError: expected:<true> but was:<false>\n\tat org.junit.Assert.fail(Assert.java:91)\n\tat org.junit.Assert.failNotEquals(Assert.java:645)\n\tat org.junit.Assert.assertEquals(Assert.java:126)\n\tat org.junit.Assert.assertEquals(Assert.java:145)\n\tat sonar.samples.testFailures.moduleA.FailTest.testAWithFailure(FailTest.java:12)\n" | |||
} | |||
] | |||
} |
@@ -268,7 +268,6 @@ public class ProjectDataLoaderTest { | |||
.setLineHashes(of("8d7b3d6b83c0a517eac07e1aac94b773")) | |||
.setCreatedAt(System.currentTimeMillis()) | |||
.setUpdatedAt(System.currentTimeMillis()) | |||
.setDataType(FileSourceDto.Type.SOURCE) | |||
.setRevision("123456789") | |||
.setSrcHash("123456"); | |||
} |
@@ -26,7 +26,6 @@ import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.protobuf.DbFileSources; | |||
import org.sonar.db.source.FileSourceDto; | |||
import org.sonar.server.component.TestComponentFinder; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
@@ -38,7 +37,6 @@ import org.sonar.server.ws.WsActionTester; | |||
import static java.lang.String.format; | |||
import static java.util.Collections.singletonList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE; | |||
import static org.sonar.api.web.UserRole.USER; | |||
import static org.sonar.db.component.ComponentTesting.newFileDto; | |||
@@ -66,20 +64,6 @@ public class HashActionTest { | |||
assertThat(request.execute().getInput()).isEqualTo("ABC"); | |||
} | |||
@Test | |||
public void show_hashes_on_test_file() { | |||
OrganizationDto organizationDto = db.organizations().insert(); | |||
ComponentDto project = db.components().insertPrivateProject(organizationDto); | |||
ComponentDto test = db.components().insertComponent(newFileDto(project).setQualifier(UNIT_TEST_FILE)); | |||
FileSourceDto fileSource = db.fileSources().insertFileSource(test, f -> f.setLineHashes(singletonList("ABC"))); | |||
FileSourceDto fileTest = db.fileSources().insertFileSource(test, f -> f.setTestData(singletonList(DbFileSources.Test.newBuilder().build()))); | |||
loginAsProjectViewer(project); | |||
TestRequest request = tester.newRequest().setParam("key", test.getKey()); | |||
assertThat(request.execute().getInput()).isEqualTo("ABC"); | |||
} | |||
@Test | |||
public void hashes_empty_if_no_source() { | |||
OrganizationDto organizationDto = db.organizations().insert(); |
@@ -1,159 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.ws; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.core.util.Uuids; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.protobuf.DbFileSources; | |||
import org.sonar.db.protobuf.DbFileSources.Test.CoveredFile; | |||
import org.sonar.db.source.FileSourceDto; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
import org.sonar.server.test.index.TestIndex; | |||
import org.sonar.server.test.index.TestIndexer; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.TestRequest; | |||
import org.sonar.server.ws.WsActionTester; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE; | |||
import static org.sonar.api.web.UserRole.CODEVIEWER; | |||
import static org.sonar.db.component.ComponentTesting.newFileDto; | |||
import static org.sonar.server.test.ws.CoveredFilesAction.TEST_ID; | |||
import static org.sonar.test.JsonAssert.assertJson; | |||
public class CoveredFilesActionTest { | |||
@Rule | |||
public UserSessionRule userSession = UserSessionRule.standalone(); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public EsTester es = EsTester.create(); | |||
@Rule | |||
public DbTester db = DbTester.create(); | |||
private TestIndex testIndex = new TestIndex(es.client(), System2.INSTANCE); | |||
private TestIndexer testIndexer = new TestIndexer(db.getDbClient(), es.client()); | |||
private WsActionTester ws = new WsActionTester(new CoveredFilesAction(db.getDbClient(), testIndex, userSession)); | |||
@Test | |||
public void define_covered_files() { | |||
WebService.Action action = ws.getDef(); | |||
assertThat(action).isNotNull(); | |||
assertThat(action.isInternal()).isFalse(); | |||
assertThat(action.isPost()).isFalse(); | |||
assertThat(action.handler()).isNotNull(); | |||
assertThat(action.responseExampleAsString()).isNotEmpty(); | |||
assertThat(action.params()).hasSize(3); | |||
} | |||
@Test | |||
public void covered_files() { | |||
ComponentDto project = db.components().insertPrivateProject(); | |||
ComponentDto mainFile1 = db.components().insertComponent(newFileDto(project)); | |||
ComponentDto mainFile2 = db.components().insertComponent(newFileDto(project)); | |||
ComponentDto testFile = db.components().insertComponent(newFileDto(project).setQualifier(UNIT_TEST_FILE)); | |||
userSession.addProjectPermission(CODEVIEWER, project, testFile); | |||
DbFileSources.Test test = DbFileSources.Test.newBuilder().setUuid(Uuids.create()) | |||
.addCoveredFile(CoveredFile.newBuilder() | |||
.setFileUuid(mainFile1.uuid()) | |||
.addAllCoveredLine(asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))) | |||
.addCoveredFile(CoveredFile.newBuilder() | |||
.setFileUuid(mainFile2.uuid()) | |||
.addAllCoveredLine(asList(1, 2, 3))) | |||
.build(); | |||
insertTests(testFile, test); | |||
TestRequest request = ws.newRequest().setParam(TEST_ID, test.getUuid()); | |||
assertJson(request.execute().getInput()).isSimilarTo("{\n" + | |||
" \"files\": [\n" + | |||
" {\n" + | |||
" \"id\": \"" + mainFile1.uuid() + "\",\n" + | |||
" \"key\": \"" + mainFile1.getKey() + "\",\n" + | |||
" \"longName\": \"" + mainFile1.longName() + "\",\n" + | |||
" \"coveredLines\": 10\n" + | |||
" },\n" + | |||
" {\n" + | |||
" \"id\": \"" + mainFile2.uuid() + "\",\n" + | |||
" \"key\": \"" + mainFile2.getKey() + "\",\n" + | |||
" \"longName\": \"" + mainFile2.longName() + "\",\n" + | |||
" \"coveredLines\": 3\n" + | |||
" }\n" + | |||
" ]\n" + | |||
"}"); | |||
} | |||
@Test | |||
public void covered_files_on_branch() { | |||
ComponentDto project = db.components().insertMainBranch(); | |||
ComponentDto branch = db.components().insertProjectBranch(project); | |||
ComponentDto mainFile = db.components().insertComponent(newFileDto(branch)); | |||
ComponentDto testFile = db.components().insertComponent(newFileDto(branch).setQualifier(UNIT_TEST_FILE)); | |||
userSession.addProjectPermission(CODEVIEWER, project, testFile); | |||
DbFileSources.Test test = DbFileSources.Test.newBuilder().setUuid(Uuids.create()) | |||
.addCoveredFile(CoveredFile.newBuilder() | |||
.setFileUuid(mainFile.uuid()) | |||
.addAllCoveredLine(asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))) | |||
.build(); | |||
insertTests(testFile, test); | |||
TestRequest request = ws.newRequest().setParam(TEST_ID, test.getUuid()); | |||
assertJson(request.execute().getInput()).isSimilarTo("{\n" + | |||
" \"files\": [\n" + | |||
" {\n" + | |||
" \"id\": \"" + mainFile.uuid() + "\",\n" + | |||
" \"key\": \"" + mainFile.getKey() + "\",\n" + | |||
" \"branch\": \"" + mainFile.getBranch() + "\",\n" + | |||
" \"longName\": \"" + mainFile.longName() + "\",\n" + | |||
" \"coveredLines\": 10\n" + | |||
" }\n" + | |||
" ]\n" + | |||
"}"); | |||
} | |||
@Test | |||
public void fail_when_test_uuid_is_unknown() { | |||
expectedException.expect(NotFoundException.class); | |||
expectedException.expectMessage("Test with id 'unknown' is not found"); | |||
ws.newRequest().setParam(TEST_ID, "unknown").execute(); | |||
} | |||
private void insertTests(ComponentDto testFile, DbFileSources.Test... tests) { | |||
db.getDbClient().fileSourceDao().insert(db.getSession(), new FileSourceDto() | |||
.setProjectUuid(testFile.projectUuid()) | |||
.setFileUuid(testFile.uuid()) | |||
.setTestData(asList(tests))); | |||
db.commit(); | |||
testIndexer.indexOnStartup(null); | |||
} | |||
} |
@@ -1,434 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.server.test.ws; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.protobuf.DbFileSources; | |||
import org.sonar.db.source.FileSourceDto; | |||
import org.sonar.server.component.TestComponentFinder; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
import org.sonar.server.test.index.TestIndex; | |||
import org.sonar.server.test.index.TestIndexer; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.TestRequest; | |||
import org.sonar.server.ws.WsActionTester; | |||
import org.sonarqube.ws.Tests; | |||
import org.sonarqube.ws.Tests.ListResponse; | |||
import static java.lang.String.format; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.tuple; | |||
import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE; | |||
import static org.sonar.api.web.UserRole.CODEVIEWER; | |||
import static org.sonar.api.web.UserRole.USER; | |||
import static org.sonar.db.component.BranchType.PULL_REQUEST; | |||
import static org.sonar.db.component.ComponentTesting.newFileDto; | |||
import static org.sonar.db.protobuf.DbFileSources.Test.TestStatus.OK; | |||
import static org.sonar.server.test.db.TestTesting.newTest; | |||
import static org.sonar.server.test.ws.ListAction.PARAM_PULL_REQUEST; | |||
import static org.sonar.server.test.ws.ListAction.SOURCE_FILE_ID; | |||
import static org.sonar.server.test.ws.ListAction.SOURCE_FILE_KEY; | |||
import static org.sonar.server.test.ws.ListAction.SOURCE_FILE_LINE_NUMBER; | |||
import static org.sonar.server.test.ws.ListAction.TEST_FILE_ID; | |||
import static org.sonar.server.test.ws.ListAction.TEST_FILE_KEY; | |||
import static org.sonar.server.test.ws.ListAction.TEST_ID; | |||
public class ListActionTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public EsTester es = EsTester.create(); | |||
@Rule | |||
public UserSessionRule userSessionRule = UserSessionRule.standalone(); | |||
@Rule | |||
public DbTester db = DbTester.create(); | |||
private DbClient dbClient = db.getDbClient(); | |||
private TestIndex testIndex = new TestIndex(es.client(), System2.INSTANCE); | |||
private TestIndexer testIndexer = new TestIndexer(db.getDbClient(), es.client()); | |||
private ComponentDto project; | |||
private ComponentDto mainFile; | |||
private ComponentDto testFile; | |||
private WsActionTester ws = new WsActionTester(new ListAction(dbClient, testIndex, userSessionRule, TestComponentFinder.from(db))); | |||
@Before | |||
public void setUp() throws Exception { | |||
project = db.components().insertComponent(ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization())); | |||
mainFile = db.components().insertComponent(newFileDto(project)); | |||
testFile = db.components().insertComponent(newFileDto(project).setQualifier(UNIT_TEST_FILE)); | |||
} | |||
@Test | |||
public void test_definition() { | |||
WebService.Action action = ws.getDef(); | |||
assertThat(action).isNotNull(); | |||
assertThat(action.isInternal()).isFalse(); | |||
assertThat(action.isPost()).isFalse(); | |||
assertThat(action.handler()).isNotNull(); | |||
assertThat(action.responseExampleAsString()).isNotEmpty(); | |||
assertThat(action.params()).hasSize(10); | |||
assertThat(action.description()).isEqualTo("Get the list of tests either in a test file or that test a given line of source code.<br /> " + | |||
"Requires 'Browse' permission on the file's project.<br /> " + | |||
"One (and only one) of the following combination of parameters must be provided: " + | |||
"<ul>" + | |||
"<li>testId - get a specific test</li>" + | |||
"<li>testFileId - get the tests in a test file</li>" + | |||
"<li>testFileKey - get the tests in a test file</li>" + | |||
"<li>sourceFileId and sourceFileLineNumber - get the tests that cover a specific line of code</li>" + | |||
"<li>sourceFileKey and sourceFileLineNumber - get the tests that cover a specific line of code</li>" + | |||
"</ul>"); | |||
} | |||
@Test | |||
public void list_tests() { | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
DbFileSources.Test test = newTest(mainFile, 10, 11, 12, 20, 21, 25).setStatus(OK).build(); | |||
insertTests(testFile, test); | |||
ListResponse request = call(ws.newRequest().setParam(TEST_ID, test.getUuid())); | |||
assertThat(request.getTestsList()).hasSize(1); | |||
Tests.Test result = request.getTests(0); | |||
assertThat(result.getId()).isEqualTo(test.getUuid()); | |||
assertThat(result.getName()).isEqualTo(test.getName()); | |||
assertThat(result.getStatus()).isEqualTo(Tests.TestStatus.OK); | |||
assertThat(result.getFileId()).isEqualTo(testFile.uuid()); | |||
assertThat(result.getFileKey()).isEqualTo(testFile.getDbKey()); | |||
assertThat(result.getFileName()).isEqualTo(testFile.path()); | |||
assertThat(result.getDurationInMs()).isEqualTo(test.getExecutionTimeMs()); | |||
assertThat(result.getMessage()).isEqualTo(test.getMsg()); | |||
assertThat(result.getStacktrace()).isEqualTo(test.getStacktrace()); | |||
assertThat(result.getCoveredLines()).isEqualTo(6); | |||
} | |||
@Test | |||
public void list_tests_by_test_uuid() { | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
DbFileSources.Test test1 = newTest(mainFile, 10).build(); | |||
DbFileSources.Test test2 = newTest(mainFile, 11).build(); | |||
insertTests(testFile, test1, test2); | |||
ListResponse request = call(ws.newRequest() | |||
.setParam(TEST_ID, test1.getUuid())); | |||
assertThat(request.getTestsList()) | |||
.extracting(Tests.Test::getId) | |||
.containsOnly(test1.getUuid()); | |||
} | |||
@Test | |||
public void list_tests_by_test_file_uuid() { | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
ComponentDto anotherTestFile = db.components().insertComponent(newFileDto(project)); | |||
DbFileSources.Test test1 = newTest(mainFile, 10).build(); | |||
DbFileSources.Test test2 = newTest(mainFile, 11).build(); | |||
DbFileSources.Test test3 = newTest(mainFile, 12).build(); | |||
insertTests(testFile, test1, test2); | |||
insertTests(anotherTestFile, test3); | |||
ListResponse request = call(ws.newRequest() | |||
.setParam(TEST_FILE_ID, testFile.uuid())); | |||
assertThat(request.getTestsList()) | |||
.extracting(Tests.Test::getId) | |||
.containsOnly(test1.getUuid(), test2.getUuid()); | |||
} | |||
@Test | |||
public void list_tests_by_test_file_key() { | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
ComponentDto anotherTestFile = db.components().insertComponent(newFileDto(project)); | |||
DbFileSources.Test test1 = newTest(mainFile, 10).build(); | |||
DbFileSources.Test test2 = newTest(mainFile, 11).build(); | |||
DbFileSources.Test test3 = newTest(mainFile, 12).build(); | |||
insertTests(testFile, test1, test2); | |||
insertTests(anotherTestFile, test3); | |||
ListResponse request = call(ws.newRequest() | |||
.setParam(TEST_FILE_KEY, testFile.getDbKey())); | |||
assertThat(request.getTestsList()) | |||
.extracting(Tests.Test::getId) | |||
.containsOnly(test1.getUuid(), test2.getUuid()); | |||
} | |||
@Test | |||
public void list_tests_by_test_file_key_and_branch() { | |||
ComponentDto project = db.components().insertMainBranch(); | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
ComponentDto branch = db.components().insertProjectBranch(project); | |||
ComponentDto mainFile = db.components().insertComponent(newFileDto(branch)); | |||
ComponentDto testFile = db.components().insertComponent(newFileDto(branch).setQualifier(UNIT_TEST_FILE)); | |||
DbFileSources.Test test1 = newTest(mainFile, 10).build(); | |||
DbFileSources.Test test2 = newTest(mainFile, 11).build(); | |||
insertTests(testFile, test1, test2); | |||
ListResponse request = call(ws.newRequest() | |||
.setParam(TEST_FILE_KEY, testFile.getKey()) | |||
.setParam("branch", testFile.getBranch())); | |||
assertThat(request.getTestsList()) | |||
.extracting(Tests.Test::getId, Tests.Test::getFileKey, Tests.Test::getFileBranch) | |||
.containsOnly( | |||
tuple(test1.getUuid(), testFile.getKey(), testFile.getBranch()), | |||
tuple(test2.getUuid(), testFile.getKey(), testFile.getBranch())); | |||
} | |||
@Test | |||
public void list_tests_by_test_file_key_and_pull_request() { | |||
ComponentDto project = db.components().insertMainBranch(); | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
ComponentDto pullRequest = db.components().insertProjectBranch(project, b -> b.setBranchType(PULL_REQUEST)); | |||
ComponentDto mainFile = db.components().insertComponent(newFileDto(pullRequest)); | |||
ComponentDto testFile = db.components().insertComponent(newFileDto(pullRequest).setQualifier(UNIT_TEST_FILE)); | |||
DbFileSources.Test test1 = newTest(mainFile, 10).build(); | |||
DbFileSources.Test test2 = newTest(mainFile, 11).build(); | |||
insertTests(testFile, test1, test2); | |||
ListResponse request = call(ws.newRequest() | |||
.setParam(TEST_FILE_KEY, testFile.getKey()) | |||
.setParam(PARAM_PULL_REQUEST, testFile.getPullRequest())); | |||
assertThat(request.getTestsList()) | |||
.extracting(Tests.Test::getId, Tests.Test::getFileKey, Tests.Test::getFilePullRequest) | |||
.containsOnly( | |||
tuple(test1.getUuid(), testFile.getKey(), testFile.getPullRequest()), | |||
tuple(test2.getUuid(), testFile.getKey(), testFile.getPullRequest())); | |||
} | |||
@Test | |||
public void list_tests_by_source_file_uuid_and_line_number() { | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
ComponentDto anotherMainFile = db.components().insertComponent(newFileDto(project)); | |||
DbFileSources.Test test1 = newTest(mainFile, 10, 11, 12).build(); | |||
DbFileSources.Test test2 = newTest(mainFile, 9, 11).build(); | |||
DbFileSources.Test test3 = newTest(mainFile, 10, 12).build(); | |||
DbFileSources.Test test4 = newTest(anotherMainFile, 11).build(); | |||
insertTests(testFile, test1, test2, test3, test4); | |||
ListResponse request = call(ws.newRequest() | |||
.setParam(SOURCE_FILE_ID, mainFile.uuid()) | |||
.setParam(SOURCE_FILE_LINE_NUMBER, "11")); | |||
assertThat(request.getTestsList()).extracting(Tests.Test::getId).containsOnly(test1.getUuid(), test2.getUuid()); | |||
} | |||
@Test | |||
public void list_tests_by_source_file_key_and_line_number() { | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
ComponentDto anotherMainFile = db.components().insertComponent(newFileDto(project)); | |||
DbFileSources.Test test1 = newTest(mainFile, 10, 11, 12).build(); | |||
DbFileSources.Test test2 = newTest(mainFile, 9, 11).build(); | |||
DbFileSources.Test test3 = newTest(mainFile, 10, 12).build(); | |||
DbFileSources.Test test4 = newTest(anotherMainFile, 11).build(); | |||
insertTests(testFile, test1, test2, test3, test4); | |||
ListResponse request = call(ws.newRequest() | |||
.setParam(SOURCE_FILE_KEY, mainFile.getDbKey()) | |||
.setParam(SOURCE_FILE_LINE_NUMBER, "10")); | |||
assertThat(request.getTestsList()) | |||
.extracting(Tests.Test::getId) | |||
.containsOnly(test1.getUuid(), test3.getUuid()); | |||
} | |||
@Test | |||
public void list_tests_by_source_file_key_and_branch_and_line_number() { | |||
ComponentDto project = db.components().insertMainBranch(); | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
ComponentDto branch = db.components().insertProjectBranch(project); | |||
ComponentDto mainFile = db.components().insertComponent(newFileDto(branch)); | |||
ComponentDto testFile = db.components().insertComponent(newFileDto(branch).setQualifier(UNIT_TEST_FILE)); | |||
DbFileSources.Test test1 = newTest(mainFile, 10, 11, 12).build(); | |||
DbFileSources.Test test2 = newTest(mainFile, 9, 11).build(); | |||
DbFileSources.Test test3 = newTest(mainFile, 10, 12).build(); | |||
insertTests(testFile, test1, test2, test3); | |||
ListResponse request = call(ws.newRequest() | |||
.setParam(SOURCE_FILE_KEY, mainFile.getKey()) | |||
.setParam(SOURCE_FILE_LINE_NUMBER, "10") | |||
.setParam("branch", testFile.getBranch())); | |||
assertThat(request.getTestsList()) | |||
.extracting(Tests.Test::getId, Tests.Test::getFileKey, Tests.Test::getFileBranch) | |||
.containsOnly( | |||
tuple(test1.getUuid(), testFile.getKey(), testFile.getBranch()), | |||
tuple(test3.getUuid(), testFile.getKey(), testFile.getBranch())); | |||
} | |||
@Test | |||
public void tests_are_paginated() { | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
insertTests(testFile, newTest(mainFile, 10).build(), newTest(mainFile, 11).build(), newTest(mainFile, 12).build()); | |||
ListResponse request = call(ws.newRequest().setParam(TEST_FILE_ID, testFile.uuid())); | |||
assertThat(request.getPaging().getPageIndex()).isEqualTo(1); | |||
assertThat(request.getPaging().getPageSize()).isEqualTo(100); | |||
assertThat(request.getPaging().getTotal()).isEqualTo(3); | |||
} | |||
@Test | |||
public void fail_when_no_argument() { | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
expectedException.expect(IllegalArgumentException.class); | |||
call(ws.newRequest()); | |||
} | |||
@Test | |||
public void fail_when_source_file_uuid_without_line_number() { | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
expectedException.expect(IllegalArgumentException.class); | |||
call(ws.newRequest().setParam(SOURCE_FILE_ID, mainFile.uuid())); | |||
} | |||
@Test | |||
public void fail_when_not_enough_privilege_on_test_uuid() { | |||
userSessionRule.addProjectPermission(USER, project); | |||
DbFileSources.Test test = newTest(mainFile, 10).build(); | |||
insertTests(testFile, test); | |||
expectedException.expect(ForbiddenException.class); | |||
call(ws.newRequest().setParam(TEST_ID, test.getUuid())); | |||
} | |||
@Test | |||
public void fail_when_no_enough_privilege_on_test_file_id() { | |||
userSessionRule.addProjectPermission(USER, project); | |||
insertTests(testFile, newTest(mainFile, 10).build()); | |||
expectedException.expect(ForbiddenException.class); | |||
call(ws.newRequest().setParam(TEST_FILE_ID, testFile.uuid())); | |||
} | |||
@Test | |||
public void fail_when_not_enough_privilege_on_test_file_key() { | |||
userSessionRule.addProjectPermission(USER, project); | |||
insertTests(testFile, newTest(mainFile, 10).build()); | |||
expectedException.expect(ForbiddenException.class); | |||
call(ws.newRequest().setParam(TEST_FILE_KEY, testFile.getDbKey())); | |||
} | |||
@Test | |||
public void fail_when_not_enough_privilege_on_main_file_uuid() { | |||
userSessionRule.addProjectPermission(USER, project); | |||
insertTests(testFile, newTest(mainFile, 10).build()); | |||
expectedException.expect(ForbiddenException.class); | |||
call(ws.newRequest().setParam(SOURCE_FILE_ID, mainFile.uuid()).setParam(SOURCE_FILE_LINE_NUMBER, "10")); | |||
} | |||
@Test | |||
public void fail_when_test_uuid_is_unknown() { | |||
expectedException.expect(NotFoundException.class); | |||
call(ws.newRequest().setParam(TEST_ID, "unknown")); | |||
} | |||
@Test | |||
public void fail_when_test_file_id_is_unknown() { | |||
expectedException.expect(NotFoundException.class); | |||
call(ws.newRequest().setParam(TEST_FILE_ID, "unknown")); | |||
} | |||
@Test | |||
public void fail_when_test_file_key_is_unknown() { | |||
expectedException.expect(NotFoundException.class); | |||
call(ws.newRequest().setParam(TEST_FILE_KEY, "unknown")); | |||
} | |||
@Test | |||
public void fail_when_test_branch_is_unknown() { | |||
ComponentDto project = db.components().insertMainBranch(); | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
ComponentDto branch = db.components().insertProjectBranch(project); | |||
ComponentDto testFile = db.components().insertComponent(newFileDto(branch).setQualifier(UNIT_TEST_FILE)); | |||
expectedException.expect(NotFoundException.class); | |||
expectedException.expectMessage(format("Component '%s' on branch 'unknown' not found", testFile.getKey())); | |||
call(ws.newRequest() | |||
.setParam(TEST_FILE_KEY, testFile.getKey()) | |||
.setParam("branch", "unknown")); | |||
} | |||
@Test | |||
public void fail_when_source_file_id_is_unknown() { | |||
expectedException.expect(NotFoundException.class); | |||
call(ws.newRequest().setParam(SOURCE_FILE_ID, "unknown").setParam(SOURCE_FILE_LINE_NUMBER, "10")); | |||
} | |||
@Test | |||
public void fail_when_source_file_key_is_unknown() { | |||
expectedException.expect(NotFoundException.class); | |||
call(ws.newRequest().setParam(SOURCE_FILE_KEY, "unknown").setParam(SOURCE_FILE_LINE_NUMBER, "10")); | |||
} | |||
@Test | |||
public void fail_when_source_branch_is_unknown() { | |||
ComponentDto project = db.components().insertMainBranch(); | |||
userSessionRule.addProjectPermission(CODEVIEWER, project); | |||
ComponentDto branch = db.components().insertProjectBranch(project); | |||
ComponentDto mainFile = db.components().insertComponent(newFileDto(branch)); | |||
expectedException.expect(NotFoundException.class); | |||
expectedException.expectMessage(format("Component '%s' on branch 'unknown' not found", mainFile.getKey())); | |||
call(ws.newRequest() | |||
.setParam(SOURCE_FILE_KEY, mainFile.getKey()) | |||
.setParam("branch", "unknown") | |||
.setParam(SOURCE_FILE_LINE_NUMBER, "10")); | |||
} | |||
private void insertTests(ComponentDto testFile, DbFileSources.Test... tests) { | |||
db.getDbClient().fileSourceDao().insert(db.getSession(), new FileSourceDto() | |||
.setProjectUuid(testFile.projectUuid()) | |||
.setFileUuid(testFile.uuid()) | |||
.setTestData(asList(tests))); | |||
db.commit(); | |||
testIndexer.indexOnStartup(null); | |||
} | |||
private static ListResponse call(TestRequest request) { | |||
return request | |||
.executeProtobuf(ListResponse.class); | |||
} | |||
} |
@@ -1,16 +0,0 @@ | |||
{ | |||
"files": [ | |||
{ | |||
"id": "FILE1", | |||
"key": "org.foo.Bar.java", | |||
"longName": "src/main/java/org/foo/Bar.java", | |||
"coveredLines": 10 | |||
}, | |||
{ | |||
"id": "FILE2", | |||
"key": "org.foo.File.java", | |||
"longName": "src/main/java/org/foo/File.java", | |||
"coveredLines": 3 | |||
} | |||
] | |||
} |
@@ -1,34 +0,0 @@ | |||
{ | |||
"paging": { | |||
"pageIndex": 1, | |||
"pageSize": 100, | |||
"total": 2 | |||
}, | |||
"tests": [ | |||
{ | |||
"id": "TEST-UUID-1", | |||
"name": "test1", | |||
"status": "OK", | |||
"fileId": "ABCD", | |||
"fileKey": "org.foo.BarTest.java", | |||
"fileName": "src/test/java/org/foo/BarTest.java", | |||
"durationInMs": 10, | |||
"coveredLines": 4, | |||
"message": "MESSAGE-1", | |||
"stacktrace": "STACKTRACE-1" | |||
}, | |||
{ | |||
"id": "TEST-UUID-2", | |||
"name": "test2", | |||
"status": "ERROR", | |||
"fileId": "BCDE", | |||
"fileKey": "org.foo.FileTest.java", | |||
"fileName": "src/test/java/org/foo/FileTest.java", | |||
"durationInMs": 97, | |||
"coveredLines": 4, | |||
"message": "MESSAGE-2", | |||
"stacktrace": "STACKTRACE-2" | |||
} | |||
] | |||
} |
@@ -1,16 +0,0 @@ | |||
{ | |||
"tests": [ | |||
{ | |||
"id": "TEST-UUID-1", | |||
"name": "test1", | |||
"status": "OK", | |||
"fileId": "ABCD", | |||
"fileKey": "org.foo.BarTest.java", | |||
"fileName": "src/test/java/org/foo/BarTest.java", | |||
"durationInMs": 10, | |||
"coveredLines": 4, | |||
"message": "MESSAGE-1", | |||
"stacktrace": "STACKTRACE-1" | |||
} | |||
] | |||
} |
@@ -21,7 +21,6 @@ package org.sonar.scanner.mediumtest; | |||
import com.google.common.collect.Iterators; | |||
import com.google.common.collect.Lists; | |||
import java.io.InputStream; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
@@ -29,7 +28,6 @@ import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import javax.annotation.CheckForNull; | |||
import org.apache.commons.io.FileUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.sonar.api.batch.fs.InputComponent; | |||
@@ -254,38 +252,6 @@ public class AnalysisResult implements AnalysisObserver { | |||
return null; | |||
} | |||
public ScannerReport.Test firstTestExecutionForName(InputFile testFile, String testName) { | |||
int ref = ((DefaultInputComponent) testFile).scannerId(); | |||
try (InputStream inputStream = FileUtils.openInputStream(getReportReader().readTests(ref))) { | |||
ScannerReport.Test test = ScannerReport.Test.parser().parseDelimitedFrom(inputStream); | |||
while (test != null) { | |||
if (test.getName().equals(testName)) { | |||
return test; | |||
} | |||
test = ScannerReport.Test.parser().parseDelimitedFrom(inputStream); | |||
} | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
return null; | |||
} | |||
public ScannerReport.CoverageDetail coveragePerTestFor(InputFile testFile, String testName) { | |||
int ref = ((DefaultInputComponent) testFile).scannerId(); | |||
try (InputStream inputStream = FileUtils.openInputStream(getReportReader().readCoverageDetails(ref))) { | |||
ScannerReport.CoverageDetail details = ScannerReport.CoverageDetail.parser().parseDelimitedFrom(inputStream); | |||
while (details != null) { | |||
if (details.getTestName().equals(testName)) { | |||
return details; | |||
} | |||
details = ScannerReport.CoverageDetail.parser().parseDelimitedFrom(inputStream); | |||
} | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
return null; | |||
} | |||
public List<ScannerReport.AdHocRule> adHocRules() { | |||
List<ScannerReport.AdHocRule> result = new ArrayList<>(); | |||
try (CloseableIterator<ScannerReport.AdHocRule> it = getReportReader().readAdHocRules()) { |
@@ -1,126 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.protocol.output.ScannerReportWriter; | |||
import org.sonar.scanner.scan.branch.BranchConfiguration; | |||
import org.sonar.scanner.scan.filesystem.InputComponentStore; | |||
import static java.util.stream.Collectors.toList; | |||
public class TestExecutionAndCoveragePublisher implements ReportPublisherStep { | |||
private final InputComponentStore componentStore; | |||
private final TestPlanBuilder testPlanBuilder; | |||
private final BranchConfiguration branchConfiguration; | |||
public TestExecutionAndCoveragePublisher(InputComponentStore componentStore, TestPlanBuilder testPlanBuilder, BranchConfiguration branchConfiguration) { | |||
this.componentStore = componentStore; | |||
this.testPlanBuilder = testPlanBuilder; | |||
this.branchConfiguration = branchConfiguration; | |||
} | |||
@Override | |||
public void publish(ScannerReportWriter writer) { | |||
if (branchConfiguration.isShortOrPullRequest()) { | |||
return; | |||
} | |||
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.scannerId(), | |||
StreamSupport.stream(testPlan.testCases().spliterator(), false) | |||
.map(testCase -> toProtobufTest(testBuilder, testNamesWithCoverage, testCase)) | |||
.collect(toList())); | |||
writer.writeCoverageDetails(component.scannerId(), 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.scannerId()); | |||
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(); | |||
} | |||
} |
@@ -80,7 +80,6 @@ import org.sonar.scanner.report.MeasuresPublisher; | |||
import org.sonar.scanner.report.MetadataPublisher; | |||
import org.sonar.scanner.report.ReportPublisher; | |||
import org.sonar.scanner.report.SourcePublisher; | |||
import org.sonar.scanner.report.TestExecutionAndCoveragePublisher; | |||
import org.sonar.scanner.repository.ContextPropertiesCache; | |||
import org.sonar.scanner.repository.DefaultProjectRepositoriesLoader; | |||
import org.sonar.scanner.repository.DefaultQualityProfileLoader; | |||
@@ -294,8 +293,7 @@ public class ProjectScanContainer extends ComponentContainer { | |||
MeasuresPublisher.class, | |||
CoveragePublisher.class, | |||
SourcePublisher.class, | |||
ChangedLinesPublisher.class, | |||
TestExecutionAndCoveragePublisher.class); | |||
ChangedLinesPublisher.class); | |||
} | |||
private void addIssueTrackingComponents() { |
@@ -1,147 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.mediumtest.tests; | |||
import com.google.common.collect.ImmutableMap; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
import org.apache.commons.io.FileUtils; | |||
import org.hamcrest.Description; | |||
import org.hamcrest.TypeSafeMatcher; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.scanner.mediumtest.ScannerMediumTester; | |||
import org.sonar.scanner.mediumtest.AnalysisResult; | |||
import org.sonar.xoo.XooPlugin; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class CoveragePerTestMediumTest { | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
@Rule | |||
public ExpectedException exception = ExpectedException.none(); | |||
@Rule | |||
public ScannerMediumTester tester = new ScannerMediumTester() | |||
.registerPlugin("xoo", new XooPlugin()) | |||
.addDefaultQProfile("xoo", "Sonar Way"); | |||
@Test | |||
// SONAR-6183 | |||
public void invalidCoverage() throws IOException { | |||
File baseDir = createTestFiles(); | |||
File srcDir = new File(baseDir, "src"); | |||
File coverageFile = new File(srcDir, "sample.xoo.coverage"); | |||
FileUtils.write(coverageFile, "0:2\n", StandardCharsets.UTF_8); | |||
exception.expect(IllegalStateException.class); | |||
exception.expectMessage("Error processing line 1 of file"); | |||
exception.expectCause(new TypeSafeMatcher<Throwable>() { | |||
@Override | |||
public void describeTo(Description description) { | |||
// nothing to do | |||
} | |||
@Override | |||
protected boolean matchesSafely(Throwable item) { | |||
return item.getMessage().contains("Line number must be strictly positive"); | |||
} | |||
}); | |||
runTask(baseDir); | |||
} | |||
@Test | |||
public void coveragePerTestInReport() throws IOException { | |||
File baseDir = createTestFiles(); | |||
File testDir = new File(baseDir, "test"); | |||
File xooTestExecutionFile = new File(testDir, "sampleTest.xoo.test"); | |||
FileUtils.write(xooTestExecutionFile, "some test:4:::OK:UNIT\n" + | |||
"another test:10:::OK:UNIT\n" + | |||
"test without coverage:10:::OK:UNIT\n", StandardCharsets.UTF_8); | |||
File xooCoveragePerTestFile = new File(testDir, "sampleTest.xoo.testcoverage"); | |||
FileUtils.write(xooCoveragePerTestFile, "some test;src/sample.xoo,10,11;src/sample2.xoo,1,2\n" + | |||
"another test;src/sample.xoo,10,20\n", StandardCharsets.UTF_8); | |||
AnalysisResult result = runTask(baseDir); | |||
InputFile file = result.inputFile("test/sampleTest.xoo"); | |||
org.sonar.scanner.protocol.output.ScannerReport.CoverageDetail someTest = result.coveragePerTestFor(file, "some test"); | |||
assertThat(someTest.getCoveredFileList()).hasSize(2); | |||
assertThat(someTest.getCoveredFile(0).getFileRef()).isGreaterThan(0); | |||
assertThat(someTest.getCoveredFile(0).getCoveredLineList()).containsExactly(10, 11); | |||
assertThat(someTest.getCoveredFile(1).getFileRef()).isGreaterThan(0); | |||
assertThat(someTest.getCoveredFile(1).getCoveredLineList()).containsExactly(1, 2); | |||
org.sonar.scanner.protocol.output.ScannerReport.CoverageDetail anotherTest = result.coveragePerTestFor(file, "another test"); | |||
assertThat(anotherTest.getCoveredFileList()).hasSize(1); | |||
assertThat(anotherTest.getCoveredFile(0).getFileRef()).isGreaterThan(0); | |||
assertThat(anotherTest.getCoveredFile(0).getCoveredLineList()).containsExactly(10, 20); | |||
} | |||
private AnalysisResult runTask(File baseDir) { | |||
return tester.newAnalysis() | |||
.properties(ImmutableMap.<String, String>builder() | |||
.put("sonar.task", "scan") | |||
.put("sonar.projectBaseDir", baseDir.getAbsolutePath()) | |||
.put("sonar.projectKey", "com.foo.project") | |||
.put("sonar.projectName", "Foo Project") | |||
.put("sonar.projectVersion", "1.0-SNAPSHOT") | |||
.put("sonar.projectDescription", "Description of Foo Project") | |||
.put("sonar.sources", "src") | |||
.put("sonar.tests", "test") | |||
.build()) | |||
.execute(); | |||
} | |||
private File createTestFiles() throws IOException { | |||
File baseDir = temp.getRoot(); | |||
File srcDir = new File(baseDir, "src"); | |||
srcDir.mkdir(); | |||
File testDir = new File(baseDir, "test"); | |||
testDir.mkdir(); | |||
File xooFile = new File(srcDir, "sample.xoo"); | |||
FileUtils.write(xooFile, "foo", StandardCharsets.UTF_8); | |||
File xooFile2 = new File(srcDir, "sample2.xoo"); | |||
FileUtils.write(xooFile2, "foo", StandardCharsets.UTF_8); | |||
File xooTestFile = new File(testDir, "sampleTest.xoo"); | |||
FileUtils.write(xooTestFile, "failure\nerror\nok\nskipped", StandardCharsets.UTF_8); | |||
File xooTestFile2 = new File(testDir, "sample2Test.xoo"); | |||
FileUtils.write(xooTestFile2, "test file tests", StandardCharsets.UTF_8); | |||
return baseDir; | |||
} | |||
} |
@@ -19,22 +19,15 @@ | |||
*/ | |||
package org.sonar.scanner.mediumtest.tests; | |||
import com.google.common.collect.ImmutableMap; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.measures.CoreMetrics; | |||
import org.sonar.scanner.mediumtest.ScannerMediumTester; | |||
import org.sonar.scanner.mediumtest.AnalysisResult; | |||
import org.sonar.scanner.protocol.output.ScannerReport; | |||
import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus; | |||
import org.sonar.scanner.mediumtest.ScannerMediumTester; | |||
import org.sonar.xoo.XooPlugin; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -43,63 +36,13 @@ import static org.assertj.core.api.Assertions.tuple; | |||
public class GenericTestExecutionMediumTest { | |||
private final List<String> logs = new ArrayList<>(); | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
@Rule | |||
public ScannerMediumTester tester = new ScannerMediumTester() | |||
.registerPlugin("xoo", new XooPlugin()) | |||
.addDefaultQProfile("xoo", "Sonar Way"); | |||
@Test | |||
public void unitTests() throws IOException { | |||
File baseDir = temp.getRoot(); | |||
File srcDir = new File(baseDir, "src"); | |||
srcDir.mkdir(); | |||
File testDir = new File(baseDir, "test"); | |||
testDir.mkdir(); | |||
File xooFile = new File(srcDir, "sample.xoo"); | |||
FileUtils.write(xooFile, "foo", StandardCharsets.UTF_8); | |||
File xooTestFile = new File(testDir, "sampleTest.xoo"); | |||
FileUtils.write(xooTestFile, "failure\nerror\nok\nskipped", StandardCharsets.UTF_8); | |||
File xooTestExecutionFile = new File(testDir, "sampleTest.xoo.test"); | |||
FileUtils.write(xooTestExecutionFile, "skipped::::SKIPPED:UNIT\n" + | |||
"failure:2:Failure::FAILURE:UNIT\n" + | |||
"error:2:Error:The stack:ERROR:UNIT\n" + | |||
"success:4:::OK:INTEGRATION", StandardCharsets.UTF_8); | |||
AnalysisResult result = tester | |||
.newAnalysis() | |||
.properties(ImmutableMap.<String, String>builder() | |||
.put("sonar.task", "scan") | |||
.put("sonar.projectBaseDir", baseDir.getAbsolutePath()) | |||
.put("sonar.projectKey", "com.foo.project") | |||
.put("sonar.projectName", "Foo Project") | |||
.put("sonar.projectVersion", "1.0-SNAPSHOT") | |||
.put("sonar.projectDescription", "Description of Foo Project") | |||
.put("sonar.sources", "src") | |||
.put("sonar.tests", "test") | |||
.build()) | |||
.execute(); | |||
InputFile file = result.inputFile("test/sampleTest.xoo"); | |||
org.sonar.scanner.protocol.output.ScannerReport.Test success = result.firstTestExecutionForName(file, "success"); | |||
assertThat(success.getDurationInMs()).isEqualTo(4); | |||
assertThat(success.getStatus()).isEqualTo(TestStatus.OK); | |||
org.sonar.scanner.protocol.output.ScannerReport.Test error = result.firstTestExecutionForName(file, "error"); | |||
assertThat(error.getDurationInMs()).isEqualTo(2); | |||
assertThat(error.getStatus()).isEqualTo(TestStatus.ERROR); | |||
assertThat(error.getMsg()).isEqualTo("Error"); | |||
assertThat(error.getStacktrace()).isEqualTo("The stack"); | |||
} | |||
@Test | |||
public void singleReport() throws IOException { | |||
public void singleReport() { | |||
File projectDir = new File("test-resources/mediumtest/xoo/sample-generic-test-exec"); | |||
@@ -110,28 +53,6 @@ public class GenericTestExecutionMediumTest { | |||
.execute(); | |||
InputFile testFile = result.inputFile("testx/ClassOneTest.xoo"); | |||
ScannerReport.Test success = result.firstTestExecutionForName(testFile, "test1"); | |||
assertThat(success.getDurationInMs()).isEqualTo(5); | |||
assertThat(success.getStatus()).isEqualTo(TestStatus.OK); | |||
ScannerReport.Test skipped = result.firstTestExecutionForName(testFile, "test2"); | |||
assertThat(skipped.getDurationInMs()).isEqualTo(500); | |||
assertThat(skipped.getStatus()).isEqualTo(TestStatus.SKIPPED); | |||
assertThat(skipped.getMsg()).isEqualTo("short message"); | |||
assertThat(skipped.getStacktrace()).isEqualTo("other"); | |||
ScannerReport.Test failed = result.firstTestExecutionForName(testFile, "test3"); | |||
assertThat(failed.getDurationInMs()).isEqualTo(100); | |||
assertThat(failed.getStatus()).isEqualTo(TestStatus.FAILURE); | |||
assertThat(failed.getMsg()).isEqualTo("short"); | |||
assertThat(failed.getStacktrace()).isEqualTo("stacktrace"); | |||
ScannerReport.Test error = result.firstTestExecutionForName(testFile, "test4"); | |||
assertThat(error.getDurationInMs()).isEqualTo(500); | |||
assertThat(error.getStatus()).isEqualTo(TestStatus.ERROR); | |||
assertThat(error.getMsg()).isEqualTo("short"); | |||
assertThat(error.getStacktrace()).isEqualTo("stacktrace"); | |||
assertThat(result.allMeasures().get(testFile.key())).extracting("metricKey", "intValue.value", "longValue.value") | |||
.containsOnly( | |||
tuple(CoreMetrics.TESTS_KEY, 3, 0L), | |||
@@ -139,12 +60,12 @@ public class GenericTestExecutionMediumTest { | |||
tuple(CoreMetrics.TEST_ERRORS_KEY, 1, 0L), | |||
tuple(CoreMetrics.TEST_EXECUTION_TIME_KEY, 0, 1105L), | |||
tuple(CoreMetrics.TEST_FAILURES_KEY, 1, 0L)); | |||
assertThat(logs).noneMatch(l -> l.contains("Please use 'sonar.testExecutionReportPaths'")); | |||
} | |||
@Test | |||
public void twoReports() throws IOException { | |||
public void twoReports() { | |||
File projectDir = new File("test-resources/mediumtest/xoo/sample-generic-test-exec"); | |||
@@ -155,32 +76,6 @@ public class GenericTestExecutionMediumTest { | |||
.execute(); | |||
InputFile testFile = result.inputFile("testx/ClassOneTest.xoo"); | |||
ScannerReport.Test success = result.firstTestExecutionForName(testFile, "test1"); | |||
assertThat(success.getDurationInMs()).isEqualTo(5); | |||
assertThat(success.getStatus()).isEqualTo(TestStatus.OK); | |||
ScannerReport.Test success2 = result.firstTestExecutionForName(testFile, "test1b"); | |||
assertThat(success2.getDurationInMs()).isEqualTo(5); | |||
assertThat(success2.getStatus()).isEqualTo(TestStatus.OK); | |||
ScannerReport.Test skipped = result.firstTestExecutionForName(testFile, "test2"); | |||
assertThat(skipped.getDurationInMs()).isEqualTo(500); | |||
assertThat(skipped.getStatus()).isEqualTo(TestStatus.SKIPPED); | |||
assertThat(skipped.getMsg()).isEqualTo("short message"); | |||
assertThat(skipped.getStacktrace()).isEqualTo("other"); | |||
ScannerReport.Test failed = result.firstTestExecutionForName(testFile, "test3"); | |||
assertThat(failed.getDurationInMs()).isEqualTo(100); | |||
assertThat(failed.getStatus()).isEqualTo(TestStatus.FAILURE); | |||
assertThat(failed.getMsg()).isEqualTo("short"); | |||
assertThat(failed.getStacktrace()).isEqualTo("stacktrace"); | |||
ScannerReport.Test error = result.firstTestExecutionForName(testFile, "test4"); | |||
assertThat(error.getDurationInMs()).isEqualTo(500); | |||
assertThat(error.getStatus()).isEqualTo(TestStatus.ERROR); | |||
assertThat(error.getMsg()).isEqualTo("short"); | |||
assertThat(error.getStacktrace()).isEqualTo("stacktrace"); | |||
assertThat(result.allMeasures().get(testFile.key())).extracting("metricKey", "intValue.value", "longValue.value") | |||
.containsOnly( | |||
tuple(CoreMetrics.TESTS_KEY, 4, 0L), | |||
@@ -188,7 +83,7 @@ public class GenericTestExecutionMediumTest { | |||
tuple(CoreMetrics.TEST_ERRORS_KEY, 1, 0L), | |||
tuple(CoreMetrics.TEST_EXECUTION_TIME_KEY, 0, 1610L), | |||
tuple(CoreMetrics.TEST_FAILURES_KEY, 1, 0L)); | |||
assertThat(logs).noneMatch(l -> l.contains("Please use 'sonar.testExecutionReportPaths'")); | |||
} | |||
@@ -1,93 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.mediumtest.tests; | |||
import com.google.common.collect.ImmutableMap; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.scanner.mediumtest.ScannerMediumTester; | |||
import org.sonar.scanner.mediumtest.AnalysisResult; | |||
import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus; | |||
import org.sonar.xoo.XooPlugin; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class TestExecutionMediumTest { | |||
@org.junit.Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
@Rule | |||
public ScannerMediumTester tester = new ScannerMediumTester() | |||
.registerPlugin("xoo", new XooPlugin()) | |||
.addDefaultQProfile("xoo", "Sonar Way"); | |||
@Test | |||
public void unitTests() throws IOException { | |||
File baseDir = temp.getRoot(); | |||
File srcDir = new File(baseDir, "src"); | |||
srcDir.mkdir(); | |||
File testDir = new File(baseDir, "test"); | |||
testDir.mkdir(); | |||
File xooFile = new File(srcDir, "sample.xoo"); | |||
FileUtils.write(xooFile, "foo"); | |||
File xooTestFile = new File(testDir, "sampleTest.xoo"); | |||
FileUtils.write(xooTestFile, "failure\nerror\nok\nskipped"); | |||
File xooTestExecutionFile = new File(testDir, "sampleTest.xoo.test"); | |||
FileUtils.write(xooTestExecutionFile, "skipped::::SKIPPED:UNIT\n" + | |||
"failure:2:Failure::FAILURE:UNIT\n" + | |||
"error:2:Error:The stack:ERROR:UNIT\n" + | |||
"success:4:::OK:INTEGRATION"); | |||
AnalysisResult result = tester.newAnalysis() | |||
.properties(ImmutableMap.<String, String>builder() | |||
.put("sonar.task", "scan") | |||
.put("sonar.projectBaseDir", baseDir.getAbsolutePath()) | |||
.put("sonar.projectKey", "com.foo.project") | |||
.put("sonar.projectName", "Foo Project") | |||
.put("sonar.projectVersion", "1.0-SNAPSHOT") | |||
.put("sonar.projectDescription", "Description of Foo Project") | |||
.put("sonar.sources", "src") | |||
.put("sonar.tests", "test") | |||
.build()) | |||
.execute(); | |||
InputFile file = result.inputFile("test/sampleTest.xoo"); | |||
org.sonar.scanner.protocol.output.ScannerReport.Test success = result.firstTestExecutionForName(file, "success"); | |||
assertThat(success.getDurationInMs()).isEqualTo(4); | |||
assertThat(success.getStatus()).isEqualTo(TestStatus.OK); | |||
org.sonar.scanner.protocol.output.ScannerReport.Test error = result.firstTestExecutionForName(file, "error"); | |||
assertThat(error.getDurationInMs()).isEqualTo(2); | |||
assertThat(error.getStatus()).isEqualTo(TestStatus.ERROR); | |||
assertThat(error.getMsg()).isEqualTo("Error"); | |||
assertThat(error.getStacktrace()).isEqualTo("The stack"); | |||
} | |||
} |
@@ -1,68 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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 java.io.File; | |||
import java.io.IOException; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.scanner.protocol.output.ScannerReportWriter; | |||
import org.sonar.scanner.scan.branch.BranchConfiguration; | |||
import org.sonar.scanner.scan.filesystem.InputComponentStore; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verifyZeroInteractions; | |||
import static org.mockito.Mockito.when; | |||
public class TestExecutionAndCoveragePublisherTest { | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
@Test | |||
public void do_nothing_for_short_living_branches() throws IOException { | |||
BranchConfiguration branchConfiguration = mock(BranchConfiguration.class); | |||
when(branchConfiguration.isShortOrPullRequest()).thenReturn(true); | |||
InputComponentStore componentStore = mock(InputComponentStore.class); | |||
TestExecutionAndCoveragePublisher publisher = new TestExecutionAndCoveragePublisher(componentStore, null, branchConfiguration); | |||
File outputDir = temp.newFolder(); | |||
ScannerReportWriter writer = new ScannerReportWriter(outputDir); | |||
publisher.publish(writer); | |||
verifyZeroInteractions(componentStore); | |||
} | |||
@Test | |||
public void do_nothing_for_pull_requests() throws IOException { | |||
BranchConfiguration branchConfiguration = mock(BranchConfiguration.class); | |||
when(branchConfiguration.isShortOrPullRequest()).thenReturn(true); | |||
InputComponentStore componentStore = mock(InputComponentStore.class); | |||
TestExecutionAndCoveragePublisher publisher = new TestExecutionAndCoveragePublisher(componentStore, null, branchConfiguration); | |||
File outputDir = temp.newFolder(); | |||
ScannerReportWriter writer = new ScannerReportWriter(outputDir); | |||
publisher.publish(writer); | |||
verifyZeroInteractions(componentStore); | |||
} | |||
} |
@@ -20,7 +20,6 @@ | |||
package org.sonar.scanner.protocol.output; | |||
import java.io.File; | |||
import javax.annotation.concurrent.Immutable; | |||
/** | |||
@@ -40,8 +39,6 @@ public class FileStructure { | |||
CHANGESETS("changesets-", Domain.PB), | |||
SYMBOLS("symbols-", Domain.PB), | |||
COVERAGES("coverages-", Domain.PB), | |||
TESTS("tests-", Domain.PB), | |||
COVERAGE_DETAILS("coverage-details-", Domain.PB), | |||
SOURCE("source-", ".txt"), | |||
SGNIFICANT_CODE("sgnificant-code-", Domain.PB), | |||
CHANGED_LINES("changed-lines-", Domain.PB); |
@@ -181,26 +181,6 @@ public class ScannerReportReader { | |||
return null; | |||
} | |||
@CheckForNull | |||
public File readTests(int testFileRef) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.TESTS, testFileRef); | |||
if (fileExists(file)) { | |||
return file; | |||
} | |||
return null; | |||
} | |||
@CheckForNull | |||
public File readCoverageDetails(int testFileRef) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.COVERAGE_DETAILS, testFileRef); | |||
if (fileExists(file)) { | |||
return file; | |||
} | |||
return null; | |||
} | |||
public CloseableIterator<ScannerReport.ContextProperty> readContextProperties() { | |||
File file = fileStructure.contextProperties(); | |||
if (!fileExists(file)) { |
@@ -154,18 +154,6 @@ public class ScannerReportWriter { | |||
return file; | |||
} | |||
public File writeTests(int componentRef, Iterable<ScannerReport.Test> tests) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.TESTS, componentRef); | |||
Protobuf.writeStream(tests, file, false); | |||
return file; | |||
} | |||
public File writeCoverageDetails(int componentRef, Iterable<ScannerReport.CoverageDetail> tests) { | |||
File file = fileStructure.fileFor(FileStructure.Domain.COVERAGE_DETAILS, componentRef); | |||
Protobuf.writeStream(tests, file, false); | |||
return file; | |||
} | |||
public File writeContextProperties(Iterable<ScannerReport.ContextProperty> properties) { | |||
File file = fileStructure.contextProperties(); | |||
Protobuf.writeStream(properties, file, false); |
@@ -25,7 +25,6 @@ import java.awt.Dimension; | |||
import java.awt.EventQueue; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.PrintWriter; | |||
import java.io.StringWriter; | |||
import java.nio.charset.StandardCharsets; | |||
@@ -256,7 +255,6 @@ public class ScannerReportViewerApp { | |||
updateSymbols(component); | |||
updateSource(component); | |||
updateCoverage(component); | |||
updateTests(component); | |||
updateDuplications(component); | |||
updateIssues(component); | |||
updateExternalIssues(component); | |||
@@ -348,23 +346,6 @@ public class ScannerReportViewerApp { | |||
} | |||
} | |||
private void updateTests(Component component) { | |||
testsEditor.setText(""); | |||
File tests = reader.readTests(component.getRef()); | |||
if (tests == null) { | |||
return; | |||
} | |||
try (InputStream inputStream = FileUtils.openInputStream(tests)) { | |||
ScannerReport.Test test = ScannerReport.Test.parser().parseDelimitedFrom(inputStream); | |||
while (test != null) { | |||
testsEditor.getDocument().insertString(testsEditor.getDocument().getEndPosition().getOffset(), test + "\n", null); | |||
test = ScannerReport.Test.parser().parseDelimitedFrom(inputStream); | |||
} | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
private void updateSource(Component component) { | |||
File sourceFile = reader.getFileStructure().fileFor(Domain.SOURCE, component.getRef()); | |||
sourceEditor.setText(""); |
@@ -321,32 +321,6 @@ message SyntaxHighlightingRule { | |||
} | |||
} | |||
message Test { | |||
string name = 1; | |||
TestStatus status = 2; | |||
int64 duration_in_ms = 3; | |||
string stacktrace = 4; | |||
string msg = 5; | |||
enum TestStatus { | |||
UNSET = 0; | |||
OK = 1; | |||
FAILURE = 2; | |||
ERROR = 3; | |||
SKIPPED = 4; | |||
} | |||
} | |||
message CoverageDetail { | |||
string test_name = 1; | |||
repeated CoveredFile covered_file = 2; | |||
message CoveredFile { | |||
int32 file_ref = 1; | |||
repeated int32 covered_line = 2 [packed = true]; | |||
} | |||
} | |||
message AnalysisWarning { | |||
string text = 1; | |||
int64 timestamp = 2; |
@@ -32,7 +32,6 @@ import org.junit.rules.TemporaryFolder; | |||
import org.sonar.core.util.CloseableIterator; | |||
import org.sonar.scanner.protocol.output.ScannerReport.Measure.StringValue; | |||
import org.sonar.scanner.protocol.output.ScannerReport.SyntaxHighlightingRule.HighlightingType; | |||
import org.sonar.scanner.protocol.output.ScannerReport.Test.TestStatus; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.singletonList; | |||
@@ -45,9 +44,9 @@ public class ScannerReportReaderTest { | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
File dir; | |||
private File dir; | |||
ScannerReportReader underTest; | |||
private ScannerReportReader underTest; | |||
@Before | |||
public void setUp() throws Exception { | |||
@@ -211,7 +210,7 @@ public class ScannerReportReaderTest { | |||
} | |||
@Test | |||
public void read_syntax_highlighting() throws Exception { | |||
public void read_syntax_highlighting() { | |||
ScannerReportWriter writer = new ScannerReportWriter(dir); | |||
writer.writeMetadata(ScannerReport.Metadata.newBuilder() | |||
.setRootComponentRef(1) | |||
@@ -276,7 +275,7 @@ public class ScannerReportReaderTest { | |||
} | |||
@Test | |||
public void read_coverage() throws Exception { | |||
public void read_coverage() { | |||
ScannerReportWriter writer = new ScannerReportWriter(dir); | |||
writer.writeMetadata(ScannerReport.Metadata.newBuilder() | |||
.setRootComponentRef(1) | |||
@@ -323,55 +322,6 @@ public class ScannerReportReaderTest { | |||
assertThat(sourceFile).isEqualTo(file); | |||
} | |||
@Test | |||
public void read_tests() throws Exception { | |||
ScannerReportWriter writer = new ScannerReportWriter(dir); | |||
writer.writeTests(1, asList( | |||
ScannerReport.Test.newBuilder() | |||
.setDurationInMs(60_000) | |||
.setStacktrace("stacktrace") | |||
.setMsg("message") | |||
.setStatus(TestStatus.OK) | |||
.build())); | |||
try (InputStream inputStream = FileUtils.openInputStream(underTest.readTests(1))) { | |||
ScannerReport.Test testResult = ScannerReport.Test.parser().parseDelimitedFrom(inputStream); | |||
assertThat(testResult.getDurationInMs()).isEqualTo(60_000); | |||
assertThat(testResult.getStacktrace()).isEqualTo("stacktrace"); | |||
assertThat(testResult.getMsg()).isEqualTo("message"); | |||
assertThat(testResult.getStatus()).isEqualTo(TestStatus.OK); | |||
} | |||
} | |||
@Test | |||
public void null_if_no_test_found() { | |||
assertThat(underTest.readTests(UNKNOWN_COMPONENT_REF)).isNull(); | |||
} | |||
@Test | |||
public void read_coverage_details() throws Exception { | |||
ScannerReportWriter writer = new ScannerReportWriter(dir); | |||
writer.writeCoverageDetails(1, asList( | |||
ScannerReport.CoverageDetail.newBuilder() | |||
.setTestName("test-name") | |||
.addCoveredFile(ScannerReport.CoverageDetail.CoveredFile.newBuilder() | |||
.addAllCoveredLine(asList(1, 2, 3, 5, 7)) | |||
.setFileRef(2)) | |||
.build())); | |||
try (InputStream inputStream = FileUtils.openInputStream(underTest.readCoverageDetails(1))) { | |||
ScannerReport.CoverageDetail coverageDetail = ScannerReport.CoverageDetail.parser().parseDelimitedFrom(inputStream); | |||
assertThat(coverageDetail.getTestName()).isEqualTo("test-name"); | |||
assertThat(coverageDetail.getCoveredFile(0).getFileRef()).isEqualTo(2); | |||
assertThat(coverageDetail.getCoveredFile(0).getCoveredLineList()).containsExactly(1, 2, 3, 5, 7); | |||
} | |||
} | |||
@Test | |||
public void null_if_no_coverage_detail_found() { | |||
assertThat(underTest.readCoverageDetails(UNKNOWN_COMPONENT_REF)).isNull(); | |||
} | |||
@Test | |||
public void read_file_source() throws Exception { | |||
ScannerReportWriter writer = new ScannerReportWriter(dir); | |||
@@ -385,7 +335,7 @@ public class ScannerReportReaderTest { | |||
} | |||
@Test | |||
public void return_null_when_no_file_source() throws Exception { | |||
public void return_null_when_no_file_source() { | |||
assertThat(underTest.readFileSource(UNKNOWN_COMPONENT_REF)).isNull(); | |||
} | |||
} |
@@ -353,24 +353,4 @@ public class ScannerReportWriterTest { | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGES, 1)).isTrue(); | |||
} | |||
@Test | |||
public void write_tests() { | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.TESTS, 1)).isFalse(); | |||
underTest.writeTests(1, asList( | |||
ScannerReport.Test.getDefaultInstance())); | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.TESTS, 1)).isTrue(); | |||
} | |||
@Test | |||
public void write_coverage_details() { | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGE_DETAILS, 1)).isFalse(); | |||
underTest.writeCoverageDetails(1, asList( | |||
ScannerReport.CoverageDetail.getDefaultInstance())); | |||
assertThat(underTest.hasComponentData(FileStructure.Domain.COVERAGE_DETAILS, 1)).isTrue(); | |||
} | |||
} |
@@ -65,7 +65,6 @@ import org.sonarqube.ws.client.settings.SettingsService; | |||
import org.sonarqube.ws.client.sources.SourcesService; | |||
import org.sonarqube.ws.client.support.SupportService; | |||
import org.sonarqube.ws.client.system.SystemService; | |||
import org.sonarqube.ws.client.tests.TestsService; | |||
import org.sonarqube.ws.client.timemachine.TimemachineService; | |||
import org.sonarqube.ws.client.updatecenter.UpdatecenterService; | |||
import org.sonarqube.ws.client.usergroups.UserGroupsService; | |||
@@ -130,7 +129,6 @@ class DefaultWsClient implements WsClient { | |||
private final SourcesService sourcesService; | |||
private final SupportService supportService; | |||
private final SystemService systemService; | |||
private final TestsService testsService; | |||
private final TimemachineService timemachineService; | |||
private final UpdatecenterService updatecenterService; | |||
private final UserGroupsService userGroupsService; | |||
@@ -189,7 +187,6 @@ class DefaultWsClient implements WsClient { | |||
this.sourcesService = new SourcesService(wsConnector); | |||
this.supportService = new SupportService(wsConnector); | |||
this.systemService = new SystemService(wsConnector); | |||
this.testsService = new TestsService(wsConnector); | |||
this.timemachineService = new TimemachineService(wsConnector); | |||
this.updatecenterService = new UpdatecenterService(wsConnector); | |||
this.userGroupsService = new UserGroupsService(wsConnector); | |||
@@ -424,11 +421,6 @@ class DefaultWsClient implements WsClient { | |||
return systemService; | |||
} | |||
@Override | |||
public TestsService tests() { | |||
return testsService; | |||
} | |||
@Override | |||
public TimemachineService timemachine() { | |||
return timemachineService; |
@@ -65,7 +65,6 @@ import org.sonarqube.ws.client.settings.SettingsService; | |||
import org.sonarqube.ws.client.sources.SourcesService; | |||
import org.sonarqube.ws.client.support.SupportService; | |||
import org.sonarqube.ws.client.system.SystemService; | |||
import org.sonarqube.ws.client.tests.TestsService; | |||
import org.sonarqube.ws.client.timemachine.TimemachineService; | |||
import org.sonarqube.ws.client.updatecenter.UpdatecenterService; | |||
import org.sonarqube.ws.client.usergroups.UserGroupsService; | |||
@@ -185,8 +184,6 @@ public interface WsClient { | |||
SystemService system(); | |||
TestsService tests(); | |||
TimemachineService timemachine(); | |||
UpdatecenterService updatecenter(); |
@@ -1,74 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.sonarqube.ws.client.tests; | |||
import java.util.List; | |||
import javax.annotation.Generated; | |||
/** | |||
* This is part of the internal API. | |||
* This is a POST request. | |||
* @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/tests/covered_files">Further information about this action online (including a response example)</a> | |||
* @since 4.4 | |||
*/ | |||
@Generated("sonar-ws-generator") | |||
public class CoveredFilesRequest { | |||
private String p; | |||
private String ps; | |||
private String testId; | |||
/** | |||
* Example value: "42" | |||
*/ | |||
public CoveredFilesRequest setP(String p) { | |||
this.p = p; | |||
return this; | |||
} | |||
public String getP() { | |||
return p; | |||
} | |||
/** | |||
* Example value: "20" | |||
*/ | |||
public CoveredFilesRequest setPs(String ps) { | |||
this.ps = ps; | |||
return this; | |||
} | |||
public String getPs() { | |||
return ps; | |||
} | |||
/** | |||
* This is a mandatory parameter. | |||
* Example value: "AU-Tpxb--iU5OvuD2FLy" | |||
*/ | |||
public CoveredFilesRequest setTestId(String testId) { | |||
this.testId = testId; | |||
return this; | |||
} | |||
public String getTestId() { | |||
return testId; | |||
} | |||
} |
@@ -1,166 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.sonarqube.ws.client.tests; | |||
import java.util.List; | |||
import javax.annotation.Generated; | |||
/** | |||
* This is part of the internal API. | |||
* This is a POST request. | |||
* @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/tests/list">Further information about this action online (including a response example)</a> | |||
* @since 5.2 | |||
*/ | |||
@Generated("sonar-ws-generator") | |||
public class ListRequest { | |||
private String branch; | |||
private String p; | |||
private String ps; | |||
private String pullRequest; | |||
private String sourceFileId; | |||
private String sourceFileKey; | |||
private String sourceFileLineNumber; | |||
private String testFileId; | |||
private String testFileKey; | |||
private String testId; | |||
/** | |||
* This is part of the internal API. | |||
* Example value: "feature/my_branch" | |||
*/ | |||
public ListRequest setBranch(String branch) { | |||
this.branch = branch; | |||
return this; | |||
} | |||
public String getBranch() { | |||
return branch; | |||
} | |||
/** | |||
* Example value: "42" | |||
*/ | |||
public ListRequest setP(String p) { | |||
this.p = p; | |||
return this; | |||
} | |||
public String getP() { | |||
return p; | |||
} | |||
/** | |||
* Example value: "20" | |||
*/ | |||
public ListRequest setPs(String ps) { | |||
this.ps = ps; | |||
return this; | |||
} | |||
public String getPs() { | |||
return ps; | |||
} | |||
/** | |||
* This is part of the internal API. | |||
* Example value: "5461" | |||
*/ | |||
public ListRequest setPullRequest(String pullRequest) { | |||
this.pullRequest = pullRequest; | |||
return this; | |||
} | |||
public String getPullRequest() { | |||
return pullRequest; | |||
} | |||
/** | |||
* Example value: "AU-TpxcA-iU5OvuD2FL0" | |||
*/ | |||
public ListRequest setSourceFileId(String sourceFileId) { | |||
this.sourceFileId = sourceFileId; | |||
return this; | |||
} | |||
public String getSourceFileId() { | |||
return sourceFileId; | |||
} | |||
/** | |||
* Example value: "my_project:/src/foo/Bar.php" | |||
*/ | |||
public ListRequest setSourceFileKey(String sourceFileKey) { | |||
this.sourceFileKey = sourceFileKey; | |||
return this; | |||
} | |||
public String getSourceFileKey() { | |||
return sourceFileKey; | |||
} | |||
/** | |||
* Example value: "10" | |||
*/ | |||
public ListRequest setSourceFileLineNumber(String sourceFileLineNumber) { | |||
this.sourceFileLineNumber = sourceFileLineNumber; | |||
return this; | |||
} | |||
public String getSourceFileLineNumber() { | |||
return sourceFileLineNumber; | |||
} | |||
/** | |||
* Example value: "AU-Tpxb--iU5OvuD2FLy" | |||
*/ | |||
public ListRequest setTestFileId(String testFileId) { | |||
this.testFileId = testFileId; | |||
return this; | |||
} | |||
public String getTestFileId() { | |||
return testFileId; | |||
} | |||
/** | |||
* Example value: "MY_PROJECT:src/test/java/foo/BarTest.java" | |||
*/ | |||
public ListRequest setTestFileKey(String testFileKey) { | |||
this.testFileKey = testFileKey; | |||
return this; | |||
} | |||
public String getTestFileKey() { | |||
return testFileKey; | |||
} | |||
/** | |||
* Example value: "AU-TpxcA-iU5OvuD2FLz" | |||
*/ | |||
public ListRequest setTestId(String testId) { | |||
this.testId = testId; | |||
return this; | |||
} | |||
public String getTestId() { | |||
return testId; | |||
} | |||
} |
@@ -1,84 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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.sonarqube.ws.client.tests; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.Generated; | |||
import org.sonarqube.ws.MediaTypes; | |||
import org.sonarqube.ws.client.BaseService; | |||
import org.sonarqube.ws.client.GetRequest; | |||
import org.sonarqube.ws.client.PostRequest; | |||
import org.sonarqube.ws.client.WsConnector; | |||
import org.sonarqube.ws.Tests.CoveredFilesResponse; | |||
import org.sonarqube.ws.Tests.ListResponse; | |||
/** | |||
* @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/tests">Further information about this web service online</a> | |||
*/ | |||
@Generated("sonar-ws-generator") | |||
public class TestsService extends BaseService { | |||
public TestsService(WsConnector wsConnector) { | |||
super(wsConnector, "api/tests"); | |||
} | |||
/** | |||
* | |||
* This is part of the internal API. | |||
* This is a GET request. | |||
* @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/tests/covered_files">Further information about this action online (including a response example)</a> | |||
* @since 4.4 | |||
* @deprecated since 5.6 | |||
*/ | |||
@Deprecated | |||
public CoveredFilesResponse coveredFiles(CoveredFilesRequest request) { | |||
return call( | |||
new GetRequest(path("covered_files")) | |||
.setParam("p", request.getP()) | |||
.setParam("ps", request.getPs()) | |||
.setParam("testId", request.getTestId()), | |||
CoveredFilesResponse.parser()); | |||
} | |||
/** | |||
* | |||
* This is part of the internal API. | |||
* This is a GET request. | |||
* @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/tests/list">Further information about this action online (including a response example)</a> | |||
* @since 5.2 | |||
* @deprecated since 5.6 | |||
*/ | |||
@Deprecated | |||
public ListResponse list(ListRequest request) { | |||
return call( | |||
new GetRequest(path("list")) | |||
.setParam("branch", request.getBranch()) | |||
.setParam("p", request.getP()) | |||
.setParam("ps", request.getPs()) | |||
.setParam("pullRequest", request.getPullRequest()) | |||
.setParam("sourceFileId", request.getSourceFileId()) | |||
.setParam("sourceFileKey", request.getSourceFileKey()) | |||
.setParam("sourceFileLineNumber", request.getSourceFileLineNumber()) | |||
.setParam("testFileId", request.getTestFileId()) | |||
.setParam("testFileKey", request.getTestFileKey()) | |||
.setParam("testId", request.getTestId()), | |||
ListResponse.parser()); | |||
} | |||
} |
@@ -1,26 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2019 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. | |||
*/ | |||
@ParametersAreNonnullByDefault | |||
@Generated("sonar-ws-generator") | |||
package org.sonarqube.ws.client.tests; | |||
import javax.annotation.ParametersAreNonnullByDefault; | |||
import javax.annotation.Generated; | |||