Browse Source

Refactor persisting of sources

tags/7.5
Duarte Meneses 5 years ago
parent
commit
11f1dc51c3
11 changed files with 654 additions and 517 deletions
  1. 4
    5
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/FormulaExecutorComponentVisitor.java
  2. 0
    92
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceData.java
  3. 105
    0
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputer.java
  4. 114
    0
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactory.java
  5. 1
    2
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLinesHashRepositoryImpl.java
  6. 1
    0
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/linereader/LineReader.java
  7. 15
    91
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStep.java
  8. 0
    86
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceDataTest.java
  9. 103
    0
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputerTest.java
  10. 162
    0
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactoryTest.java
  11. 149
    241
      server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStepTest.java

+ 4
- 5
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/FormulaExecutorComponentVisitor.java View File

@@ -27,13 +27,12 @@ import java.util.Map;
import javax.annotation.CheckForNull;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.component.ComponentVisitor;
import org.sonar.ce.task.projectanalysis.component.PathAwareVisitorAdapter;
import org.sonar.ce.task.projectanalysis.metric.Metric;
import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
import org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit;
import org.sonar.ce.task.projectanalysis.component.PathAwareVisitorAdapter;
import org.sonar.ce.task.projectanalysis.measure.Measure;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepository;

import org.sonar.ce.task.projectanalysis.metric.Metric;
import org.sonar.ce.task.projectanalysis.metric.MetricRepository;

import static java.util.Objects.requireNonNull;

@@ -217,7 +216,7 @@ public class FormulaExecutorComponentVisitor extends PathAwareVisitorAdapter<For
}
}

private class CreateMeasureContextImpl implements CreateMeasureContext {
private static class CreateMeasureContextImpl implements CreateMeasureContext {
private final Component component;
private final Metric metric;


+ 0
- 92
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceData.java View File

@@ -1,92 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2018 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.source;

import java.util.Iterator;
import java.util.List;
import org.sonar.core.hash.SourceHashComputer;
import org.sonar.db.protobuf.DbFileSources;
import org.sonar.ce.task.projectanalysis.source.SourceLinesHashRepositoryImpl.LineHashesComputer;
import org.sonar.ce.task.projectanalysis.source.linereader.LineReader;

public class ComputeFileSourceData {
private final List<LineReader> lineReaders;
private final Iterator<String> linesIterator;
private final SourceHashComputer sourceHashComputer;
private final LineHashesComputer lineHashesComputer;

public ComputeFileSourceData(Iterator<String> sourceLinesIterator, List<LineReader> dataLineReaders, LineHashesComputer lineHashesComputer) {
this.lineReaders = dataLineReaders;
this.linesIterator = sourceLinesIterator;
this.lineHashesComputer = lineHashesComputer;
this.sourceHashComputer = new SourceHashComputer();
}

public Data compute() {
DbFileSources.Data.Builder fileSourceBuilder = DbFileSources.Data.newBuilder();
int currentLine = 0;

while (linesIterator.hasNext()) {
currentLine++;
read(fileSourceBuilder, currentLine, linesIterator.next(), linesIterator.hasNext());
}

return new Data(fileSourceBuilder.build(), lineHashesComputer.getResult(), sourceHashComputer.getHash());
}

private void read(DbFileSources.Data.Builder fileSourceBuilder, int currentLine, String lineSource, boolean hasNextLine) {
sourceHashComputer.addLine(lineSource, hasNextLine);
lineHashesComputer.addLine(lineSource);

DbFileSources.Line.Builder lineBuilder = fileSourceBuilder
.addLinesBuilder()
.setSource(lineSource)
.setLine(currentLine);

for (LineReader lineReader : lineReaders) {
lineReader.read(lineBuilder);
}
}

public static class Data {
private final DbFileSources.Data fileSourceData;
private final List<String> lineHashes;
private final String srcHash;

private Data(DbFileSources.Data fileSourceData, List<String> lineHashes, String srcHash) {
this.fileSourceData = fileSourceData;
this.lineHashes = lineHashes;
this.srcHash = srcHash;
}

public String getSrcHash() {
return srcHash;
}

public List<String> getLineHashes() {
return lineHashes;
}

public DbFileSources.Data getFileSourceData() {
return fileSourceData;
}
}

}

+ 105
- 0
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputer.java View File

@@ -0,0 +1,105 @@
/*
* SonarQube
* Copyright (C) 2009-2018 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.source;

import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.scm.Changeset;
import org.sonar.core.hash.SourceHashComputer;
import org.sonar.core.util.CloseableIterator;
import org.sonar.db.protobuf.DbFileSources;

public class FileSourceDataComputer {
private final SourceLinesRepository sourceLinesRepository;
private final SourceLineReadersFactory sourceLineReadersFactory;
private final SourceLinesHashRepository sourceLinesHash;
private final SourceHashComputer sourceHashComputer;

public FileSourceDataComputer(SourceLinesRepository sourceLinesRepository, SourceLineReadersFactory sourceLineReadersFactory, SourceLinesHashRepository sourceLinesHash) {
this.sourceLinesRepository = sourceLinesRepository;
this.sourceLineReadersFactory = sourceLineReadersFactory;
this.sourceLinesHash = sourceLinesHash;
this.sourceHashComputer = new SourceHashComputer();
}

public Data compute(Component file) {
try (CloseableIterator<String> linesIterator = sourceLinesRepository.readLines(file);
SourceLineReadersFactory.LineReaders lineReaders = sourceLineReadersFactory.getLineReaders(file)) {

SourceLinesHashRepositoryImpl.LineHashesComputer lineHashesComputer = sourceLinesHash.getLineHashesComputerToPersist(file);
DbFileSources.Data.Builder fileSourceBuilder = DbFileSources.Data.newBuilder();
int currentLine = 0;

while (linesIterator.hasNext()) {
currentLine++;
read(fileSourceBuilder, lineHashesComputer, lineReaders, currentLine, linesIterator.next(), linesIterator.hasNext());
}

return new Data(fileSourceBuilder.build(), lineHashesComputer.getResult(), sourceHashComputer.getHash(), lineReaders.getLatestChangeWithRevision());
}
}

private void read(DbFileSources.Data.Builder fileSourceBuilder, SourceLinesHashRepositoryImpl.LineHashesComputer lineHashesComputer,
SourceLineReadersFactory.LineReaders lineReaders, int currentLine, String lineSource, boolean hasNextLine) {
sourceHashComputer.addLine(lineSource, hasNextLine);
lineHashesComputer.addLine(lineSource);

DbFileSources.Line.Builder lineBuilder = fileSourceBuilder
.addLinesBuilder()
.setSource(lineSource)
.setLine(currentLine);

lineReaders.read(lineBuilder);
}

public static class Data {
private final DbFileSources.Data fileSourceData;
private final List<String> lineHashes;
private final String srcHash;
private final Changeset latestChangeWithRevision;

public Data(DbFileSources.Data fileSourceData, List<String> lineHashes, String srcHash, @Nullable Changeset latestChangeWithRevision) {
this.fileSourceData = fileSourceData;
this.lineHashes = lineHashes;
this.srcHash = srcHash;
this.latestChangeWithRevision = latestChangeWithRevision;
}

public String getSrcHash() {
return srcHash;
}

public List<String> getLineHashes() {
return lineHashes;
}

public DbFileSources.Data getLineData() {
return fileSourceData;
}

@CheckForNull
public Changeset getLatestChangeWithRevision() {
return latestChangeWithRevision;
}
}

}

+ 114
- 0
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactory.java View File

@@ -0,0 +1,114 @@
/*
* SonarQube
* Copyright (C) 2009-2018 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.source;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.duplication.DuplicationRepository;
import org.sonar.ce.task.projectanalysis.scm.Changeset;
import org.sonar.ce.task.projectanalysis.scm.ScmInfo;
import org.sonar.ce.task.projectanalysis.scm.ScmInfoRepository;
import org.sonar.ce.task.projectanalysis.source.linereader.CoverageLineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.DuplicationLineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.HighlightingLineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.LineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.RangeOffsetConverter;
import org.sonar.ce.task.projectanalysis.source.linereader.ScmLineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.SymbolsLineReader;
import org.sonar.core.util.CloseableIterator;
import org.sonar.db.protobuf.DbFileSources;
import org.sonar.scanner.protocol.output.ScannerReport;

public class SourceLineReadersFactory {
private final BatchReportReader reportReader;
private final ScmInfoRepository scmInfoRepository;
private final DuplicationRepository duplicationRepository;

SourceLineReadersFactory(BatchReportReader reportReader, ScmInfoRepository scmInfoRepository, DuplicationRepository duplicationRepository) {
this.reportReader = reportReader;
this.scmInfoRepository = scmInfoRepository;
this.duplicationRepository = duplicationRepository;
}

public LineReaders getLineReaders(Component component) {
List<LineReader> readers = new ArrayList<>();
List<CloseableIterator<?>> closeables = new ArrayList<>();
ScmLineReader scmLineReader = null;

int componentRef = component.getReportAttributes().getRef();
CloseableIterator<ScannerReport.LineCoverage> coverageIt = reportReader.readComponentCoverage(componentRef);
closeables.add(coverageIt);
readers.add(new CoverageLineReader(coverageIt));

Optional<ScmInfo> scmInfoOptional = scmInfoRepository.getScmInfo(component);
if (scmInfoOptional.isPresent()) {
scmLineReader = new ScmLineReader(scmInfoOptional.get());
readers.add(scmLineReader);
}

RangeOffsetConverter rangeOffsetConverter = new RangeOffsetConverter();
CloseableIterator<ScannerReport.SyntaxHighlightingRule> highlightingIt = reportReader.readComponentSyntaxHighlighting(componentRef);
closeables.add(highlightingIt);
readers.add(new HighlightingLineReader(component, highlightingIt, rangeOffsetConverter));

CloseableIterator<ScannerReport.Symbol> symbolsIt = reportReader.readComponentSymbols(componentRef);
closeables.add(symbolsIt);
readers.add(new SymbolsLineReader(component, symbolsIt, rangeOffsetConverter));
readers.add(new DuplicationLineReader(duplicationRepository.getDuplications(component)));

return new LineReaders(readers, scmLineReader, closeables);
}

static class LineReaders implements AutoCloseable, LineReader {
final List<LineReader> readers;
@Nullable
final ScmLineReader scmLineReader;
final List<CloseableIterator<?>> closeables;

LineReaders(List<LineReader> readers, @Nullable ScmLineReader scmLineReader, List<CloseableIterator<?>> closeables) {
this.readers = readers;
this.scmLineReader = scmLineReader;
this.closeables = closeables;
}

@Override public void close() {
for (CloseableIterator<?> reportIterator : closeables) {
reportIterator.close();
}
}

@Override public void read(DbFileSources.Line.Builder lineBuilder) {
for (LineReader r : readers) {
r.read(lineBuilder);
}
}

@CheckForNull
public Changeset getLatestChangeWithRevision() {
return scmLineReader == null ? null : scmLineReader.getLatestChangeWithRevision();
}
}

}

+ 1
- 2
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLinesHashRepositoryImpl.java View File

@@ -27,7 +27,6 @@ import org.sonar.core.hash.LineRange;
import org.sonar.core.hash.SourceLineHashesComputer;
import org.sonar.core.util.CloseableIterator;
import org.sonar.db.source.LineHashVersion;
import org.sonar.ce.task.projectanalysis.component.Component;

public class SourceLinesHashRepositoryImpl implements SourceLinesHashRepository {
private final SourceLinesRepository sourceLinesRepository;
@@ -95,7 +94,7 @@ public class SourceLinesHashRepositoryImpl implements SourceLinesHashRepository
return processor.getResult();
}

public static interface LineHashesComputer {
public interface LineHashesComputer {
void addLine(String line);

List<String> getResult();

+ 1
- 0
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/linereader/LineReader.java View File

@@ -21,6 +21,7 @@ package org.sonar.ce.task.projectanalysis.source.linereader;

import org.sonar.db.protobuf.DbFileSources;

@FunctionalInterface
public interface LineReader {

void read(DbFileSources.Line.Builder lineBuilder);

+ 15
- 91
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStep.java View File

@@ -20,69 +20,45 @@
package org.sonar.ce.task.projectanalysis.step;

import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.ObjectUtils;
import org.sonar.api.utils.System2;
import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
import org.sonar.ce.task.projectanalysis.component.Component;
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.projectanalysis.duplication.DuplicationRepository;
import org.sonar.ce.task.projectanalysis.scm.Changeset;
import org.sonar.ce.task.projectanalysis.scm.ScmInfo;
import org.sonar.ce.task.projectanalysis.scm.ScmInfoRepository;
import org.sonar.ce.task.projectanalysis.source.ComputeFileSourceData;
import org.sonar.ce.task.projectanalysis.source.FileSourceDataComputer;
import org.sonar.ce.task.projectanalysis.source.SourceLinesHashRepository;
import org.sonar.ce.task.projectanalysis.source.SourceLinesHashRepositoryImpl.LineHashesComputer;
import org.sonar.ce.task.projectanalysis.source.SourceLinesRepository;
import org.sonar.ce.task.projectanalysis.source.linereader.CoverageLineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.DuplicationLineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.HighlightingLineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.LineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.RangeOffsetConverter;
import org.sonar.ce.task.projectanalysis.source.linereader.ScmLineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.SymbolsLineReader;
import org.sonar.ce.task.step.ComputationStep;
import org.sonar.core.util.CloseableIterator;
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 static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER;

public class PersistFileSourcesStep implements ComputationStep {

private final DbClient dbClient;
private final System2 system2;
private final TreeRootHolder treeRootHolder;
private final BatchReportReader reportReader;
private final SourceLinesRepository sourceLinesRepository;
private final ScmInfoRepository scmInfoRepository;
private final DuplicationRepository duplicationRepository;
private final SourceLinesHashRepository sourceLinesHash;
private final FileSourceDataComputer fileSourceDataComputer;

public PersistFileSourcesStep(DbClient dbClient, System2 system2, TreeRootHolder treeRootHolder, BatchReportReader reportReader, SourceLinesRepository sourceLinesRepository,
ScmInfoRepository scmInfoRepository, DuplicationRepository duplicationRepository, SourceLinesHashRepository sourceLinesHash) {
public PersistFileSourcesStep(DbClient dbClient, System2 system2, TreeRootHolder treeRootHolder,
SourceLinesHashRepository sourceLinesHash, FileSourceDataComputer fileSourceDataComputer) {
this.dbClient = dbClient;
this.system2 = system2;
this.treeRootHolder = treeRootHolder;
this.reportReader = reportReader;
this.sourceLinesRepository = sourceLinesRepository;
this.scmInfoRepository = scmInfoRepository;
this.duplicationRepository = duplicationRepository;
this.sourceLinesHash = sourceLinesHash;
this.fileSourceDataComputer = fileSourceDataComputer;
}

@Override
@@ -95,7 +71,6 @@ public class PersistFileSourcesStep implements ComputationStep {
}

private class FileSourceVisitor extends TypeAwareVisitorAdapter {

private final DbSession session;

private Map<String, FileSourceDto> previousFileSourcesByUuid = new HashMap<>();
@@ -118,22 +93,19 @@ public class PersistFileSourcesStep implements ComputationStep {

@Override
public void visitFile(Component file) {
try (CloseableIterator<String> linesIterator = sourceLinesRepository.readLines(file);
LineReaders lineReaders = new LineReaders(reportReader, scmInfoRepository, duplicationRepository, file)) {
LineHashesComputer lineHashesComputer = sourceLinesHash.getLineHashesComputerToPersist(file);
ComputeFileSourceData computeFileSourceData = new ComputeFileSourceData(linesIterator, lineReaders.readers(), lineHashesComputer);
ComputeFileSourceData.Data fileSourceData = computeFileSourceData.compute();
persistSource(fileSourceData, file, lineReaders.getLatestChangeWithRevision());
try {
FileSourceDataComputer.Data fileSourceData = fileSourceDataComputer.compute(file);
persistSource(fileSourceData, file, fileSourceData.getLatestChangeWithRevision());
} catch (Exception e) {
throw new IllegalStateException(String.format("Cannot persist sources of %s", file.getKey()), e);
}
}

private void persistSource(ComputeFileSourceData.Data fileSourceData, Component file, @Nullable Changeset latestChangeWithRevision) {
DbFileSources.Data fileData = fileSourceData.getFileSourceData();
private void persistSource(FileSourceDataComputer.Data fileSourceData, Component file, @Nullable Changeset latestChangeWithRevision) {
DbFileSources.Data lineData = fileSourceData.getLineData();

byte[] data = FileSourceDto.encodeSourceData(fileData);
String dataHash = DigestUtils.md5Hex(data);
byte[] binaryData = FileSourceDto.encodeSourceData(lineData);
String dataHash = DigestUtils.md5Hex(binaryData);
String srcHash = fileSourceData.getSrcHash();
List<String> lineHashes = fileSourceData.getLineHashes();
Integer lineHashesVersion = sourceLinesHash.getLineHashesVersion(file);
@@ -144,7 +116,7 @@ public class PersistFileSourcesStep implements ComputationStep {
.setProjectUuid(projectUuid)
.setFileUuid(file.getUuid())
.setDataType(Type.SOURCE)
.setBinaryData(data)
.setBinaryData(binaryData)
.setSrcHash(srcHash)
.setDataHash(dataHash)
.setLineHashes(lineHashes)
@@ -160,10 +132,10 @@ public class PersistFileSourcesStep implements ComputationStep {
boolean srcHashUpdated = !srcHash.equals(previousDto.getSrcHash());
String revision = computeRevision(latestChangeWithRevision);
boolean revisionUpdated = !ObjectUtils.equals(revision, previousDto.getRevision());
boolean lineHashesVersionUpdated = previousDto.getLineHashesVersion() != lineHashesVersion;
boolean lineHashesVersionUpdated = !previousDto.getLineHashesVersion().equals(lineHashesVersion);
if (binaryDataUpdated || srcHashUpdated || revisionUpdated || lineHashesVersionUpdated) {
previousDto
.setBinaryData(data)
.setBinaryData(binaryData)
.setDataHash(dataHash)
.setSrcHash(srcHash)
.setLineHashes(lineHashes)
@@ -185,54 +157,6 @@ public class PersistFileSourcesStep implements ComputationStep {
}
}

private static class LineReaders implements AutoCloseable {
private final List<LineReader> readers = new ArrayList<>();
private final List<CloseableIterator<?>> closeables = new ArrayList<>();
@CheckForNull
private final ScmLineReader scmLineReader;

LineReaders(BatchReportReader reportReader, ScmInfoRepository scmInfoRepository, DuplicationRepository duplicationRepository, Component component) {
int componentRef = component.getReportAttributes().getRef();
CloseableIterator<ScannerReport.LineCoverage> coverageIt = reportReader.readComponentCoverage(componentRef);
closeables.add(coverageIt);
readers.add(new CoverageLineReader(coverageIt));

Optional<ScmInfo> scmInfoOptional = scmInfoRepository.getScmInfo(component);
if (scmInfoOptional.isPresent()) {
this.scmLineReader = new ScmLineReader(scmInfoOptional.get());
readers.add(scmLineReader);
} else {
this.scmLineReader = null;
}

RangeOffsetConverter rangeOffsetConverter = new RangeOffsetConverter();
CloseableIterator<ScannerReport.SyntaxHighlightingRule> highlightingIt = reportReader.readComponentSyntaxHighlighting(componentRef);
closeables.add(highlightingIt);
readers.add(new HighlightingLineReader(component, highlightingIt, rangeOffsetConverter));

CloseableIterator<ScannerReport.Symbol> symbolsIt = reportReader.readComponentSymbols(componentRef);
closeables.add(symbolsIt);
readers.add(new SymbolsLineReader(component, symbolsIt, rangeOffsetConverter));
readers.add(new DuplicationLineReader(duplicationRepository.getDuplications(component)));
}

List<LineReader> readers() {
return readers;
}

@Override
public void close() {
for (CloseableIterator<?> reportIterator : closeables) {
reportIterator.close();
}
}

@CheckForNull
public Changeset getLatestChangeWithRevision() {
return scmLineReader == null ? null : scmLineReader.getLatestChangeWithRevision();
}
}

@Override
public String getDescription() {
return "Persist sources";

+ 0
- 86
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceDataTest.java View File

@@ -1,86 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2018 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.source;

import com.google.common.collect.Lists;
import org.junit.Test;
import org.sonar.ce.task.projectanalysis.source.SourceLinesHashRepositoryImpl.LineHashesComputer;
import org.sonar.ce.task.projectanalysis.source.linereader.LineReader;
import org.sonar.db.protobuf.DbFileSources;

import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

public class ComputeFileSourceDataTest {

private LineHashesComputer lineHashesComputer = mock(LineHashesComputer.class);

@Test
public void compute_one_line() {
when(lineHashesComputer.getResult()).thenReturn(Lists.newArrayList("137f72c3708c6bd0de00a0e5a69c699b"));
ComputeFileSourceData computeFileSourceData = new ComputeFileSourceData(
newArrayList("line1").iterator(),
Lists.newArrayList(new MockLineReader()),
lineHashesComputer);

ComputeFileSourceData.Data data = computeFileSourceData.compute();
assertThat(data.getLineHashes()).containsOnly("137f72c3708c6bd0de00a0e5a69c699b");
assertThat(data.getSrcHash()).isEqualTo("137f72c3708c6bd0de00a0e5a69c699b");
assertThat(data.getFileSourceData().getLinesList()).hasSize(1);
assertThat(data.getFileSourceData().getLines(0).getHighlighting()).isEqualTo("h-1");

verify(lineHashesComputer).addLine("line1");
verify(lineHashesComputer).getResult();
verifyNoMoreInteractions(lineHashesComputer);
}

@Test
public void compute_two_lines() {
when(lineHashesComputer.getResult()).thenReturn(Lists.newArrayList("137f72c3708c6bd0de00a0e5a69c699b", "e6251bcf1a7dc3ba5e7933e325bbe605"));

ComputeFileSourceData computeFileSourceData = new ComputeFileSourceData(
newArrayList("line1", "line2").iterator(),
Lists.newArrayList(new MockLineReader()),
lineHashesComputer);

ComputeFileSourceData.Data data = computeFileSourceData.compute();
assertThat(data.getLineHashes()).containsOnly("137f72c3708c6bd0de00a0e5a69c699b", "e6251bcf1a7dc3ba5e7933e325bbe605");
assertThat(data.getSrcHash()).isEqualTo("ee5a58024a155466b43bc559d953e018");
assertThat(data.getFileSourceData().getLinesList()).hasSize(2);
assertThat(data.getFileSourceData().getLines(0).getHighlighting()).isEqualTo("h-1");
assertThat(data.getFileSourceData().getLines(1).getHighlighting()).isEqualTo("h-2");

verify(lineHashesComputer).addLine("line1");
verify(lineHashesComputer).addLine("line2");
verify(lineHashesComputer).getResult();
verifyNoMoreInteractions(lineHashesComputer);
}

private static class MockLineReader implements LineReader {
@Override
public void read(DbFileSources.Line.Builder lineBuilder) {
lineBuilder.setHighlighting("h-" + lineBuilder.getLine());
}
}
}

+ 103
- 0
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputerTest.java View File

@@ -0,0 +1,103 @@
/*
* SonarQube
* Copyright (C) 2009-2018 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.source;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.component.ReportComponent;
import org.sonar.ce.task.projectanalysis.source.SourceLinesHashRepositoryImpl.LineHashesComputer;
import org.sonar.ce.task.projectanalysis.source.linereader.LineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.ScmLineReader;
import org.sonar.core.util.CloseableIterator;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

public class FileSourceDataComputerTest {
private static final Component FILE = ReportComponent.builder(Component.Type.FILE, 1).build();

private SourceLinesRepository sourceLinesRepository = mock(SourceLinesRepository.class);
private LineHashesComputer lineHashesComputer = mock(LineHashesComputer.class);
private SourceLineReadersFactory sourceLineReadersFactory = mock(SourceLineReadersFactory.class);
private SourceLinesHashRepository sourceLinesHashRepository = mock(SourceLinesHashRepository.class);
private ScmLineReader scmLineReader = mock(ScmLineReader.class);
private CloseableIterator closeableIterator = mock(CloseableIterator.class);

private FileSourceDataComputer fileSourceDataComputer;

@Before
public void before() {
when(sourceLinesHashRepository.getLineHashesComputerToPersist(FILE)).thenReturn(lineHashesComputer);
LineReader reader = line -> line.setHighlighting("h-" + line.getLine());
SourceLineReadersFactory.LineReaders lineReaders = new SourceLineReadersFactory.LineReaders(Collections.singletonList(reader), scmLineReader,
Collections.singletonList(closeableIterator));
when(sourceLineReadersFactory.getLineReaders(FILE)).thenReturn(lineReaders);

fileSourceDataComputer = new FileSourceDataComputer(sourceLinesRepository, sourceLineReadersFactory, sourceLinesHashRepository);
}

@Test
public void compute_one_line() {
List<String> lineHashes = Collections.singletonList("lineHash");
when(sourceLinesRepository.readLines(FILE)).thenReturn(CloseableIterator.from(Collections.singletonList("line1").iterator()));
when(lineHashesComputer.getResult()).thenReturn(lineHashes);

FileSourceDataComputer.Data data = fileSourceDataComputer.compute(FILE);

assertThat(data.getLineHashes()).isEqualTo(lineHashes);
assertThat(data.getSrcHash()).isEqualTo("137f72c3708c6bd0de00a0e5a69c699b");
assertThat(data.getLineData().getLinesList()).hasSize(1);
assertThat(data.getLineData().getLines(0).getHighlighting()).isEqualTo("h-1");

verify(lineHashesComputer).addLine("line1");
verify(lineHashesComputer).getResult();
verify(closeableIterator).close();
verifyNoMoreInteractions(lineHashesComputer);
}

@Test
public void compute_two_lines() {
List<String> lineHashes = Arrays.asList("137f72c3708c6bd0de00a0e5a69c699b", "e6251bcf1a7dc3ba5e7933e325bbe605");
when(sourceLinesRepository.readLines(FILE)).thenReturn(CloseableIterator.from(Arrays.asList("line1", "line2").iterator()));
when(lineHashesComputer.getResult()).thenReturn(lineHashes);

FileSourceDataComputer.Data data = fileSourceDataComputer.compute(FILE);

assertThat(data.getLineHashes()).isEqualTo(lineHashes);
assertThat(data.getSrcHash()).isEqualTo("ee5a58024a155466b43bc559d953e018");
assertThat(data.getLineData().getLinesList()).hasSize(2);
assertThat(data.getLineData().getLines(0).getHighlighting()).isEqualTo("h-1");
assertThat(data.getLineData().getLines(1).getHighlighting()).isEqualTo("h-2");

verify(lineHashesComputer).addLine("line1");
verify(lineHashesComputer).addLine("line2");
verify(lineHashesComputer).getResult();
verify(closeableIterator).close();
verifyNoMoreInteractions(lineHashesComputer);
}

}

+ 162
- 0
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactoryTest.java View File

@@ -0,0 +1,162 @@
/*
* SonarQube
* Copyright (C) 2009-2018 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.source;

import java.util.Arrays;
import java.util.Collections;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
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.projectanalysis.duplication.DuplicationRepositoryRule;
import org.sonar.ce.task.projectanalysis.scm.Changeset;
import org.sonar.ce.task.projectanalysis.scm.ScmInfoRepositoryRule;
import org.sonar.ce.task.projectanalysis.source.linereader.LineReader;
import org.sonar.ce.task.projectanalysis.source.linereader.ScmLineReader;
import org.sonar.core.util.CloseableIterator;
import org.sonar.db.protobuf.DbFileSources;
import org.sonar.scanner.protocol.output.ScannerReport;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

public class SourceLineReadersFactoryTest {
private static final int FILE1_REF = 3;
private static final String PROJECT_UUID = "PROJECT";
private static final String PROJECT_KEY = "PROJECT_KEY";
private static final String FILE1_UUID = "FILE1";
private static final long NOW = 123456789L;

@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
@Rule
public BatchReportReaderRule reportReader = new BatchReportReaderRule();
@Rule
public ScmInfoRepositoryRule scmInfoRepository = new ScmInfoRepositoryRule();
@Rule
public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);

private SourceLineReadersFactory underTest;

@Before
public void setUp() {
underTest = new SourceLineReadersFactory(reportReader, scmInfoRepository, duplicationRepository);
}

@Test
public void should_create_readers() {
initBasicReport(10);
SourceLineReadersFactory.LineReaders lineReaders = underTest.getLineReaders(fileComponent());

assertThat(lineReaders).isNotNull();
assertThat(lineReaders.closeables).hasSize(3);
assertThat(lineReaders.readers).hasSize(4);
}

@Test
public void line_readers_should_close_all_closeables() {
LineReader r1 = mock(LineReader.class);
LineReader r2 = mock(LineReader.class);
CloseableIterator c1 = mock(CloseableIterator.class);
CloseableIterator c2 = mock(CloseableIterator.class);

SourceLineReadersFactory.LineReaders lineReaders = new SourceLineReadersFactory.LineReaders(Arrays.asList(r1, r2), null, Arrays.asList(c1, c2));
lineReaders.close();

verify(c1).close();
verify(c2).close();
verifyNoMoreInteractions(c1, c2);
verifyZeroInteractions(r1, r2);
}

@Test
public void line_readers_should_call_all_readers() {
LineReader r1 = mock(LineReader.class);
LineReader r2 = mock(LineReader.class);
CloseableIterator c1 = mock(CloseableIterator.class);
CloseableIterator c2 = mock(CloseableIterator.class);

SourceLineReadersFactory.LineReaders lineReaders = new SourceLineReadersFactory.LineReaders(Arrays.asList(r1, r2), null, Arrays.asList(c1, c2));
DbFileSources.Line.Builder builder = DbFileSources.Line.newBuilder();
lineReaders.read(builder);

verify(r1).read(builder);
verify(r2).read(builder);
verifyNoMoreInteractions(r1, r2);
verifyZeroInteractions(c1, c2);
}

@Test
public void should_delegate_latest_changeset() {
ScmLineReader scmLineReader = mock(ScmLineReader.class);
Changeset changeset = Changeset.newChangesetBuilder().setDate(0L).build();
when(scmLineReader.getLatestChangeWithRevision()).thenReturn(changeset);
SourceLineReadersFactory.LineReaders lineReaders = new SourceLineReadersFactory.LineReaders(Collections.emptyList(), scmLineReader, Collections.emptyList());
assertThat(lineReaders.getLatestChangeWithRevision()).isEqualTo(changeset);
}

@Test
public void should_not_delegate_latest_changeset() {
SourceLineReadersFactory.LineReaders lineReaders = new SourceLineReadersFactory.LineReaders(Collections.emptyList(), null, Collections.emptyList());
assertThat(lineReaders.getLatestChangeWithRevision()).isNull();
}

private Component fileComponent() {
return ReportComponent.builder(Component.Type.FILE, FILE1_REF).build();
}

private void initBasicReport(int numberOfLines) {
treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_UUID).setKey(PROJECT_KEY).addChildren(
ReportComponent.builder(Component.Type.MODULE, 2).setUuid("MODULE").setKey("MODULE_KEY").addChildren(
ReportComponent.builder(Component.Type.FILE, FILE1_REF).setUuid(FILE1_UUID).setKey("MODULE_KEY:src/Foo.java")
.setFileAttributes(new FileAttributes(false, null, numberOfLines)).build())
.build())
.build());

reportReader.putComponent(ScannerReport.Component.newBuilder()
.setRef(1)
.setType(ScannerReport.Component.ComponentType.PROJECT)
.addChildRef(2)
.build());
reportReader.putComponent(ScannerReport.Component.newBuilder()
.setRef(2)
.setType(ScannerReport.Component.ComponentType.MODULE)
.addChildRef(FILE1_REF)
.build());
reportReader.putComponent(ScannerReport.Component.newBuilder()
.setRef(FILE1_REF)
.setType(ScannerReport.Component.ComponentType.FILE)
.setLines(numberOfLines)
.build());

// for (int i = 1; i <= numberOfLines; i++) {
// fileSourceRepository.addLine(FILE1_REF, "line" + i);
// }
}

}

+ 149
- 241
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStepTest.java View File

@@ -19,29 +19,25 @@
*/
package org.sonar.ce.task.projectanalysis.step;

import com.google.common.collect.Lists;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import org.apache.commons.codec.digest.DigestUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
import org.sonar.api.utils.System2;
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.projectanalysis.duplication.Duplication;
import org.sonar.ce.task.projectanalysis.duplication.DuplicationRepositoryRule;
import org.sonar.ce.task.projectanalysis.duplication.InnerDuplicate;
import org.sonar.ce.task.projectanalysis.duplication.TextBlock;
import org.sonar.ce.task.projectanalysis.scm.Changeset;
import org.sonar.ce.task.projectanalysis.scm.ScmInfoRepositoryRule;
import org.sonar.ce.task.projectanalysis.source.FileSourceDataComputer;
import org.sonar.ce.task.projectanalysis.source.SourceLinesHashRepository;
import org.sonar.ce.task.projectanalysis.source.SourceLinesHashRepositoryImpl;
import org.sonar.ce.task.projectanalysis.source.SourceLinesRepositoryRule;
import org.sonar.ce.task.step.ComputationStep;
import org.sonar.ce.task.step.TestComputationStepContext;
import org.sonar.db.DbClient;
@@ -51,12 +47,7 @@ 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 org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType;
import org.sonar.scanner.protocol.output.ScannerReport.SyntaxHighlightingRule.HighlightingType;

import static com.google.common.collect.ImmutableList.of;
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -68,6 +59,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
private static final String PROJECT_KEY = "PROJECT_KEY";
private static final String FILE1_UUID = "FILE1";
private static final long NOW = 123456789L;
private static final long PAST = 15000L;

private System2 system2 = mock(System2.class);

@@ -77,18 +69,11 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
public DbTester dbTester = DbTester.create(system2);
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
@Rule
public BatchReportReaderRule reportReader = new BatchReportReaderRule();
@Rule
public ScmInfoRepositoryRule scmInfoRepository = new ScmInfoRepositoryRule();
@Rule
public SourceLinesRepositoryRule fileSourceRepository = new SourceLinesRepositoryRule();
@Rule
public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);

private SourceLinesHashRepository sourceLinesHashRepository = mock(SourceLinesHashRepository.class);
private SourceLinesHashRepositoryImpl.LineHashesComputer lineHashesComputer = mock(SourceLinesHashRepositoryImpl.LineHashesComputer.class);

private FileSourceDataComputer fileSourceDataComputer = mock(FileSourceDataComputer.class);
private DbClient dbClient = dbTester.getDbClient();
private DbSession session = dbTester.getSession();

@@ -98,8 +83,8 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
public void setup() {
when(system2.now()).thenReturn(NOW);
when(sourceLinesHashRepository.getLineHashesComputerToPersist(Mockito.any(Component.class))).thenReturn(lineHashesComputer);
underTest = new PersistFileSourcesStep(dbClient, system2, treeRootHolder, reportReader, fileSourceRepository, scmInfoRepository,
duplicationRepository, sourceLinesHashRepository);
underTest = new PersistFileSourcesStep(dbClient, system2, treeRootHolder, sourceLinesHashRepository, fileSourceDataComputer);
initBasicReport(1);
}

@Override
@@ -109,8 +94,16 @@ public class PersistFileSourcesStepTest extends BaseStepTest {

@Test
public void persist_sources() {
initBasicReport(2);
when(lineHashesComputer.getResult()).thenReturn(Lists.newArrayList("137f72c3708c6bd0de00a0e5a69c699b", "e6251bcf1a7dc3ba5e7933e325bbe605"));
List<String> lineHashes = Arrays.asList("137f72c3708c6bd0de00a0e5a69c699b", "e6251bcf1a7dc3ba5e7933e325bbe605");
String sourceHash = "ee5a58024a155466b43bc559d953e018";
DbFileSources.Data fileSourceData = DbFileSources.Data.newBuilder()
.addAllLines(Arrays.asList(
DbFileSources.Line.newBuilder().setSource("line1").setLine(1).build(),
DbFileSources.Line.newBuilder().setSource("line2").setLine(2).build()
))
.build();
when(fileSourceDataComputer.compute(fileComponent())).thenReturn(new FileSourceDataComputer.Data(fileSourceData, lineHashes, sourceHash, null));

underTest.execute(new TestComputationStepContext());

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
@@ -134,8 +127,10 @@ public class PersistFileSourcesStepTest extends BaseStepTest {

@Test
public void persist_source_hashes() {
initBasicReport(2);
when(lineHashesComputer.getResult()).thenReturn(Lists.newArrayList("137f72c3708c6bd0de00a0e5a69c699b", "e6251bcf1a7dc3ba5e7933e325bbe605"));
List<String> lineHashes = Arrays.asList("137f72c3708c6bd0de00a0e5a69c699b", "e6251bcf1a7dc3ba5e7933e325bbe605");
String sourceHash = "ee5a58024a155466b43bc559d953e018";
setComputedData(DbFileSources.Data.newBuilder().build(), lineHashes, sourceHash, null);

underTest.execute(new TestComputationStepContext());

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
@@ -146,72 +141,67 @@ public class PersistFileSourcesStepTest extends BaseStepTest {

@Test
public void persist_coverage() {
initBasicReport(1);

reportReader.putCoverage(FILE1_REF, newArrayList(ScannerReport.LineCoverage.newBuilder()
.setLine(1)
.setConditions(10)
.setHits(true)
.setCoveredConditions(2)
.build()));
DbFileSources.Data dbData = DbFileSources.Data.newBuilder().addLines(
DbFileSources.Line.newBuilder()
.setConditions(10)
.setCoveredConditions(2)
.setLineHits(1)
.setLine(1)
.build())
.build();
setComputedData(dbData);

underTest.execute(new TestComputationStepContext());

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
DbFileSources.Data data = fileSourceDto.getSourceData();

assertThat(data.getLinesList()).hasSize(1);
assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData);
}

assertThat(data.getLines(0).getLineHits()).isEqualTo(1);
assertThat(data.getLines(0).getConditions()).isEqualTo(10);
assertThat(data.getLines(0).getCoveredConditions()).isEqualTo(2);
private Component fileComponent() {
return ReportComponent.builder(Component.Type.FILE, FILE1_REF).build();
}

@Test
public void persist_scm() {
initBasicReport(1);
scmInfoRepository.setScmInfo(FILE1_REF, Changeset.newChangesetBuilder()
.setAuthor("john")
.setDate(123456789L)
.setRevision("rev-1")
.build());
DbFileSources.Data dbData = DbFileSources.Data.newBuilder().addLines(
DbFileSources.Line.newBuilder()
.setScmAuthor("john")
.setScmDate(123456789L)
.setScmRevision("rev-1")
.build())
.build();
setComputedData(dbData);

underTest.execute(new TestComputationStepContext());

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);

assertThat(fileSourceDto.getRevision()).isEqualTo("rev-1");

DbFileSources.Data data = fileSourceDto.getSourceData();

assertThat(data.getLinesList()).hasSize(1);

assertThat(data.getLines(0).getScmAuthor()).isEqualTo("john");
assertThat(data.getLines(0).getScmDate()).isEqualTo(123456789L);
assertThat(data.getLines(0).getScmRevision()).isEqualTo("rev-1");
assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData);
assertThat(fileSourceDto.getRevision()).isNull();
}

@Test
public void persist_scm_some_lines() {
initBasicReport(3);
scmInfoRepository.setScmInfo(FILE1_REF, Changeset.newChangesetBuilder()
.setAuthor("john")
.setDate(123456789L)
.setRevision("rev-1")
.build(),
Changeset.newChangesetBuilder()
.setDate(223456789L)
.build());
DbFileSources.Data dbData = DbFileSources.Data.newBuilder().addAllLines(Arrays.asList(
DbFileSources.Line.newBuilder()
.setScmAuthor("john")
.setScmDate(123456789L)
.setScmRevision("rev-1")
.build(),
DbFileSources.Line.newBuilder()
.setScmDate(223456789L)
.build(),
DbFileSources.Line.newBuilder()
.build()
)).build();
setComputedData(dbData);

underTest.execute(new TestComputationStepContext());

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);

assertThat(fileSourceDto.getRevision()).isEqualTo("rev-1");

DbFileSources.Data data = fileSourceDto.getSourceData();

assertThat(data.getLinesList()).hasSize(3);
@@ -227,86 +217,67 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
assertThat(data.getLines(2).getScmAuthor()).isEmpty();
assertThat(data.getLines(2).getScmDate()).isEqualTo(0);
assertThat(data.getLines(2).getScmRevision()).isEmpty();

}

@Test
public void persist_highlighting() {
initBasicReport(1);

reportReader.putSyntaxHighlighting(FILE1_REF, newArrayList(ScannerReport.SyntaxHighlightingRule.newBuilder()
.setRange(ScannerReport.TextRange.newBuilder()
.setStartLine(1).setEndLine(1)
.setStartOffset(2).setEndOffset(4)
.build())
.setType(HighlightingType.ANNOTATION)
.build()));
DbFileSources.Data dbData = DbFileSources.Data.newBuilder().addLines(
DbFileSources.Line.newBuilder()
.setHighlighting("2,4,a")
.build()
).build();
setComputedData(dbData);

underTest.execute(new TestComputationStepContext());

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
DbFileSources.Data data = fileSourceDto.getSourceData();
assertThat(data).isEqualTo(dbData);
assertThat(data.getLinesList()).hasSize(1);

assertThat(data.getLines(0).getHighlighting()).isEqualTo("2,4,a");
}

@Test
public void persist_symbols() {
initBasicReport(3);

reportReader.putSymbols(FILE1_REF, newArrayList(
ScannerReport.Symbol.newBuilder()
.setDeclaration(ScannerReport.TextRange.newBuilder()
.setStartLine(1).setEndLine(1).setStartOffset(2).setEndOffset(4)
.build())
.addReference(ScannerReport.TextRange.newBuilder()
.setStartLine(3).setEndLine(3).setStartOffset(1).setEndOffset(3)
.build())
.build()));
DbFileSources.Data dbData = DbFileSources.Data.newBuilder().addAllLines(Arrays.asList(
DbFileSources.Line.newBuilder()
.setSymbols("2,4,1")
.build(),
DbFileSources.Line.newBuilder().build(),
DbFileSources.Line.newBuilder()
.setSymbols("1,3,1")
.build()
)).build();
setComputedData(dbData);

underTest.execute(new TestComputationStepContext());

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
DbFileSources.Data data = fileSourceDto.getSourceData();

assertThat(data.getLinesList()).hasSize(3);

assertThat(data.getLines(0).getSymbols()).isEqualTo("2,4,1");
assertThat(data.getLines(1).getSymbols()).isEmpty();
assertThat(data.getLines(2).getSymbols()).isEqualTo("1,3,1");
assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData);
}

@Test
public void persist_duplication() {
initBasicReport(1);

duplicationRepository.add(
FILE1_REF,
new Duplication(new TextBlock(1, 2), Arrays.asList(new InnerDuplicate(new TextBlock(3, 4)))));
DbFileSources.Data dbData = DbFileSources.Data.newBuilder().addLines(
DbFileSources.Line.newBuilder()
.addDuplication(2)
.build()
).build();
setComputedData(dbData);

underTest.execute(new TestComputationStepContext());

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
DbFileSources.Data data = fileSourceDto.getSourceData();

assertThat(data.getLinesList()).hasSize(1);

assertThat(data.getLines(0).getDuplicationList()).hasSize(1);
assertThat(fileSourceDto.getSourceData()).isEqualTo(dbData);
}

@Test
public void save_revision() {
initBasicReport(1);
scmInfoRepository.setScmInfo(FILE1_REF, Changeset.newChangesetBuilder()
.setAuthor("john")
.setDate(123456789L)
.setRevision("rev-1")
.build());
Changeset latest = Changeset.newChangesetBuilder().setDate(0L).setRevision("rev-1").build();
setComputedData(DbFileSources.Data.newBuilder().build(), Collections.singletonList("lineHashes"), "srcHash", latest);

underTest.execute(new TestComputationStepContext());

@@ -316,7 +287,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {

@Test
public void not_save_revision() {
initBasicReport(1);
setComputedData(DbFileSources.Data.newBuilder().build());

underTest.execute(new TestComputationStepContext());

@@ -326,41 +297,20 @@ public class PersistFileSourcesStepTest extends BaseStepTest {

@Test
public void not_update_sources_when_nothing_has_changed() {
// Existing sources
long past = 150000L;
String srcHash = "137f72c3708c6bd0de00a0e5a69c699b";
List<String> lineHashes = of("137f72c3708c6bd0de00a0e5a69c699b");
String dataHash = "29f25900140c94db38035128cb6de6a2";

dbClient.fileSourceDao().insert(dbTester.getSession(), new FileSourceDto()
.setProjectUuid(PROJECT_UUID)
.setFileUuid(FILE1_UUID)
.setSrcHash(srcHash)
.setLineHashes(lineHashes)
.setDataHash(dataHash)
.setLineHashesVersion(LineHashVersion.WITHOUT_SIGNIFICANT_CODE.getDbValue())
.setSourceData(DbFileSources.Data.newBuilder()
.addLines(DbFileSources.Line.newBuilder()
.setLine(1)
.setSource("line1")
.build())
.build())
.setCreatedAt(past)
.setUpdatedAt(past));
dbClient.fileSourceDao().insert(dbTester.getSession(), createDto());
dbTester.getSession().commit();

// Sources from the report
initBasicReport(1);
Changeset changeset = Changeset.newChangesetBuilder().setDate(1L).setRevision("rev-1").build();
setComputedData(DbFileSources.Data.newBuilder().build(), Collections.singletonList("lineHash"), "sourceHash", changeset);

underTest.execute(new TestComputationStepContext());

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
assertThat(fileSourceDto.getSrcHash()).isEqualTo(srcHash);
assertThat(fileSourceDto.getLineHashes()).isEqualTo(lineHashes);
assertThat(fileSourceDto.getDataHash()).isEqualTo(dataHash);
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(past);
assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(past);
assertThat(fileSourceDto.getSrcHash()).isEqualTo("sourceHash");
assertThat(fileSourceDto.getLineHashes()).isEqualTo(Collections.singletonList("lineHash"));
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(PAST);
assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(PAST);
}

@Test
@@ -372,7 +322,7 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
.setFileUuid(FILE1_UUID)
.setDataType(Type.SOURCE)
.setSrcHash("5b4bd9815cdb17b8ceae19eb1810c34c")
.setLineHashes(of("6438c669e0d0de98e6929c2cc0fac474", ""))
.setLineHashes(Collections.singletonList("6438c669e0d0de98e6929c2cc0fac474"))
.setDataHash("6cad150e3d065976c230cddc5a09efaa")
.setSourceData(DbFileSources.Data.newBuilder()
.addLines(DbFileSources.Line.newBuilder()
@@ -385,13 +335,18 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
.setRevision("rev-0"));
dbTester.getSession().commit();

initBasicReport(1);
DbFileSources.Data newSourceData = DbFileSources.Data.newBuilder()
.addLines(DbFileSources.Line.newBuilder()
.setLine(1)
.setSource("old line")
.setScmDate(123456789L)
.setScmRevision("rev-1")
.setScmAuthor("john")
.build())
.build();

scmInfoRepository.setScmInfo(FILE1_REF, Changeset.newChangesetBuilder()
.setAuthor("john")
.setDate(123456789L)
.setRevision("rev-1")
.build());
Changeset changeset = Changeset.newChangesetBuilder().setDate(1L).setRevision("rev-1").build();
setComputedData(newSourceData, Collections.singletonList("6438c669e0d0de98e6929c2cc0fac474"), "5b4bd9815cdb17b8ceae19eb1810c34c", changeset);

underTest.execute(new TestComputationStepContext());

@@ -404,106 +359,79 @@ public class PersistFileSourcesStepTest extends BaseStepTest {

@Test
public void update_sources_when_src_hash_is_missing() {
// Existing sources
long past = 150000L;
dbClient.fileSourceDao().insert(dbTester.getSession(), new FileSourceDto()
.setProjectUuid(PROJECT_UUID)
.setFileUuid(FILE1_UUID)
.setDataType(Type.SOURCE)
// Source hash is missing, update will be made
.setLineHashes(of("137f72c3708c6bd0de00a0e5a69c699b"))
.setDataHash("29f25900140c94db38035128cb6de6a2")
.setSourceData(DbFileSources.Data.newBuilder()
.addLines(DbFileSources.Line.newBuilder()
.setLine(1)
.setSource("line")
.build())
.build())
.setCreatedAt(past)
.setUpdatedAt(past));
dbClient.fileSourceDao().insert(dbTester.getSession(), createDto(dto -> dto.setSrcHash(null)));
dbTester.getSession().commit();

initBasicReport(1);
DbFileSources.Data sourceData = DbFileSources.Data.newBuilder().build();
setComputedData(sourceData, Collections.singletonList("lineHash"), "newSourceHash", null);

underTest.execute(new TestComputationStepContext());

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(past);
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(PAST);
assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(NOW);
assertThat(fileSourceDto.getSrcHash()).isEqualTo("137f72c3708c6bd0de00a0e5a69c699b");
assertThat(fileSourceDto.getSrcHash()).isEqualTo("newSourceHash");
}

@Test
public void update_sources_when_revision_is_missing() {
// Existing sources
long past = 150000L;
dbClient.fileSourceDao().insert(dbTester.getSession(), new FileSourceDto()
.setProjectUuid(PROJECT_UUID)
.setFileUuid(FILE1_UUID)
.setDataType(Type.SOURCE)
.setSrcHash("137f72c3708c6bd0de00a0e5a69c699b")
.setLineHashes(of("137f72c3708c6bd0de00a0e5a69c699b"))
.setDataHash("8e84c0d961cfe364e43833c4cc4ddef5")
// Revision is missing, update will be made
.setSourceData(DbFileSources.Data.newBuilder()
.addLines(DbFileSources.Line.newBuilder()
.setLine(1)
.setSource("line")
.build())
DbFileSources.Data sourceData = DbFileSources.Data.newBuilder()
.addLines(DbFileSources.Line.newBuilder()
.setLine(1)
.setSource("line")
.build())
.setCreatedAt(past)
.setUpdatedAt(past));
dbTester.getSession().commit();
.build();

scmInfoRepository.setScmInfo(FILE1_REF, Changeset.newChangesetBuilder()
.setAuthor("john")
.setDate(123456789L)
.setRevision("rev-1")
.build());
dbClient.fileSourceDao().insert(dbTester.getSession(), createDto(dto -> dto.setRevision(null)));
dbTester.getSession().commit();

initBasicReport(1);
Changeset changeset = Changeset.newChangesetBuilder().setDate(1L).setRevision("revision").build();
setComputedData(sourceData, Collections.singletonList("137f72c3708c6bd0de00a0e5a69c699b"), "29f25900140c94db38035128cb6de6a2", changeset);

underTest.execute(new TestComputationStepContext());

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(past);
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(PAST);
assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(NOW);
assertThat(fileSourceDto.getRevision()).isEqualTo("rev-1");
assertThat(fileSourceDto.getRevision()).isEqualTo("revision");
}

@Test
public void clear_revision_when_no_ChangeSet() {
// Existing sources
long past = 150000L;
dbClient.fileSourceDao().insert(dbTester.getSession(), new FileSourceDto()
private FileSourceDto createDto() {
return createDto(dto -> {
});
}

private FileSourceDto createDto(Consumer<FileSourceDto> modifier) {
DbFileSources.Data sourceData = DbFileSources.Data.newBuilder().build();
byte[] data = FileSourceDto.encodeSourceData(sourceData);
String dataHash = DigestUtils.md5Hex(data);

FileSourceDto dto = new FileSourceDto()
.setProjectUuid(PROJECT_UUID)
.setFileUuid(FILE1_UUID)
.setDataType(Type.SOURCE)
.setSrcHash("137f72c3708c6bd0de00a0e5a69c699b")
.setLineHashes(of("137f72c3708c6bd0de00a0e5a69c699b"))
.setDataHash("8e84c0d961cfe364e43833c4cc4ddef5")
// Revision is missing, update will be made
.setSourceData(DbFileSources.Data.newBuilder()
.addLines(DbFileSources.Line.newBuilder()
.setLine(1)
.setSource("line")
.build())
.build())
.setCreatedAt(past)
.setUpdatedAt(past));
dbTester.getSession().commit();
.setSrcHash("sourceHash")
.setLineHashes(Collections.singletonList("lineHash"))
.setDataHash(dataHash)
.setRevision("rev-1")
.setSourceData(sourceData)
.setCreatedAt(PAST)
.setUpdatedAt(PAST);

initBasicReport(1);
modifier.accept(dto);
return dto;
}

underTest.execute(new TestComputationStepContext());
private void setComputedData(DbFileSources.Data data, List<String> lineHashes, String sourceHash, Changeset latestChangeWithRevision) {
FileSourceDataComputer.Data computedData = new FileSourceDataComputer.Data(data, lineHashes, sourceHash, latestChangeWithRevision);
when(fileSourceDataComputer.compute(fileComponent())).thenReturn(computedData);
}

assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
assertThat(fileSourceDto.getCreatedAt()).isEqualTo(past);
assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(NOW);
assertThat(fileSourceDto.getRevision()).isNull();
private void setComputedData(DbFileSources.Data data) {
FileSourceDataComputer.Data computedData = new FileSourceDataComputer.Data(data, Collections.emptyList(), "", null);
when(fileSourceDataComputer.compute(fileComponent())).thenReturn(computedData);
}

private void initBasicReport(int numberOfLines) {
@@ -513,25 +441,5 @@ public class PersistFileSourcesStepTest extends BaseStepTest {
.setFileAttributes(new FileAttributes(false, null, numberOfLines)).build())
.build())
.build());

reportReader.putComponent(ScannerReport.Component.newBuilder()
.setRef(1)
.setType(ComponentType.PROJECT)
.addChildRef(2)
.build());
reportReader.putComponent(ScannerReport.Component.newBuilder()
.setRef(2)
.setType(ComponentType.MODULE)
.addChildRef(FILE1_REF)
.build());
reportReader.putComponent(ScannerReport.Component.newBuilder()
.setRef(FILE1_REF)
.setType(ComponentType.FILE)
.setLines(numberOfLines)
.build());

for (int i = 1; i <= numberOfLines; i++) {
fileSourceRepository.addLine(FILE1_REF, "line" + i);
}
}
}

Loading…
Cancel
Save