From 11f1dc51c363b70f5d6c44425944415209d2a037 Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Wed, 15 Aug 2018 09:46:56 +0200 Subject: [PATCH] Refactor persisting of sources --- .../FormulaExecutorComponentVisitor.java | 9 +- .../source/ComputeFileSourceData.java | 92 ----- .../source/FileSourceDataComputer.java | 105 +++++ .../source/SourceLineReadersFactory.java | 114 +++++ .../source/SourceLinesHashRepositoryImpl.java | 3 +- .../source/linereader/LineReader.java | 1 + .../step/PersistFileSourcesStep.java | 106 +---- .../source/ComputeFileSourceDataTest.java | 86 ---- .../source/FileSourceDataComputerTest.java | 103 +++++ .../source/SourceLineReadersFactoryTest.java | 162 ++++++++ .../step/PersistFileSourcesStepTest.java | 390 +++++++----------- 11 files changed, 654 insertions(+), 517 deletions(-) delete mode 100644 server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceData.java create mode 100644 server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputer.java create mode 100644 server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactory.java delete mode 100644 server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceDataTest.java create mode 100644 server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputerTest.java create mode 100644 server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactoryTest.java diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/FormulaExecutorComponentVisitor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/FormulaExecutorComponentVisitor.java index 5cd56d376523..8f172573644e 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/FormulaExecutorComponentVisitor.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/formula/FormulaExecutorComponentVisitor.java @@ -27,13 +27,12 @@ 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 Counter getCounter(Formula formula) { } } - private class CreateMeasureContextImpl implements CreateMeasureContext { + private static class CreateMeasureContextImpl implements CreateMeasureContext { private final Component component; private final Metric metric; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceData.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceData.java deleted file mode 100644 index 37abda331622..000000000000 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceData.java +++ /dev/null @@ -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 lineReaders; - private final Iterator linesIterator; - private final SourceHashComputer sourceHashComputer; - private final LineHashesComputer lineHashesComputer; - - public ComputeFileSourceData(Iterator sourceLinesIterator, List 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 lineHashes; - private final String srcHash; - - private Data(DbFileSources.Data fileSourceData, List lineHashes, String srcHash) { - this.fileSourceData = fileSourceData; - this.lineHashes = lineHashes; - this.srcHash = srcHash; - } - - public String getSrcHash() { - return srcHash; - } - - public List getLineHashes() { - return lineHashes; - } - - public DbFileSources.Data getFileSourceData() { - return fileSourceData; - } - } - -} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputer.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputer.java new file mode 100644 index 000000000000..de2ebfe4b5f3 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputer.java @@ -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 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 lineHashes; + private final String srcHash; + private final Changeset latestChangeWithRevision; + + public Data(DbFileSources.Data fileSourceData, List 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 getLineHashes() { + return lineHashes; + } + + public DbFileSources.Data getLineData() { + return fileSourceData; + } + + @CheckForNull + public Changeset getLatestChangeWithRevision() { + return latestChangeWithRevision; + } + } + +} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactory.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactory.java new file mode 100644 index 000000000000..82f3858e4fd1 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactory.java @@ -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 readers = new ArrayList<>(); + List> closeables = new ArrayList<>(); + ScmLineReader scmLineReader = null; + + int componentRef = component.getReportAttributes().getRef(); + CloseableIterator coverageIt = reportReader.readComponentCoverage(componentRef); + closeables.add(coverageIt); + readers.add(new CoverageLineReader(coverageIt)); + + Optional scmInfoOptional = scmInfoRepository.getScmInfo(component); + if (scmInfoOptional.isPresent()) { + scmLineReader = new ScmLineReader(scmInfoOptional.get()); + readers.add(scmLineReader); + } + + RangeOffsetConverter rangeOffsetConverter = new RangeOffsetConverter(); + CloseableIterator highlightingIt = reportReader.readComponentSyntaxHighlighting(componentRef); + closeables.add(highlightingIt); + readers.add(new HighlightingLineReader(component, highlightingIt, rangeOffsetConverter)); + + CloseableIterator 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 readers; + @Nullable + final ScmLineReader scmLineReader; + final List> closeables; + + LineReaders(List readers, @Nullable ScmLineReader scmLineReader, List> 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(); + } + } + +} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLinesHashRepositoryImpl.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLinesHashRepositoryImpl.java index 5bf405516f2b..52e7b043bf9b 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLinesHashRepositoryImpl.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/SourceLinesHashRepositoryImpl.java @@ -27,7 +27,6 @@ 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 @@ private List createLineHashes(Component component, Optional return processor.getResult(); } - public static interface LineHashesComputer { + public interface LineHashesComputer { void addLine(String line); List getResult(); diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/linereader/LineReader.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/linereader/LineReader.java index 2057c701a1a6..fa1a4153e023 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/linereader/LineReader.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/source/linereader/LineReader.java @@ -21,6 +21,7 @@ import org.sonar.db.protobuf.DbFileSources; +@FunctionalInterface public interface LineReader { void read(DbFileSources.Line.Builder lineBuilder); diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStep.java index ca933bd5a7ac..50c61d5f9412 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStep.java @@ -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 void execute(ComputationStep.Context context) { } private class FileSourceVisitor extends TypeAwareVisitorAdapter { - private final DbSession session; private Map previousFileSourcesByUuid = new HashMap<>(); @@ -118,22 +93,19 @@ public void visitProject(Component project) { @Override public void visitFile(Component file) { - try (CloseableIterator 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 lineHashes = fileSourceData.getLineHashes(); Integer lineHashesVersion = sourceLinesHash.getLineHashesVersion(file); @@ -144,7 +116,7 @@ private void persistSource(ComputeFileSourceData.Data fileSourceData, Component .setProjectUuid(projectUuid) .setFileUuid(file.getUuid()) .setDataType(Type.SOURCE) - .setBinaryData(data) + .setBinaryData(binaryData) .setSrcHash(srcHash) .setDataHash(dataHash) .setLineHashes(lineHashes) @@ -160,10 +132,10 @@ private void persistSource(ComputeFileSourceData.Data fileSourceData, Component 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 @@ private String computeRevision(@Nullable Changeset latestChangeWithRevision) { } } - private static class LineReaders implements AutoCloseable { - private final List readers = new ArrayList<>(); - private final List> closeables = new ArrayList<>(); - @CheckForNull - private final ScmLineReader scmLineReader; - - LineReaders(BatchReportReader reportReader, ScmInfoRepository scmInfoRepository, DuplicationRepository duplicationRepository, Component component) { - int componentRef = component.getReportAttributes().getRef(); - CloseableIterator coverageIt = reportReader.readComponentCoverage(componentRef); - closeables.add(coverageIt); - readers.add(new CoverageLineReader(coverageIt)); - - Optional 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 highlightingIt = reportReader.readComponentSyntaxHighlighting(componentRef); - closeables.add(highlightingIt); - readers.add(new HighlightingLineReader(component, highlightingIt, rangeOffsetConverter)); - - CloseableIterator symbolsIt = reportReader.readComponentSymbols(componentRef); - closeables.add(symbolsIt); - readers.add(new SymbolsLineReader(component, symbolsIt, rangeOffsetConverter)); - readers.add(new DuplicationLineReader(duplicationRepository.getDuplications(component))); - } - - List 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"; diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceDataTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceDataTest.java deleted file mode 100644 index 3bdaf738b34d..000000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/ComputeFileSourceDataTest.java +++ /dev/null @@ -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()); - } - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputerTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputerTest.java new file mode 100644 index 000000000000..7e052242fbd5 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/FileSourceDataComputerTest.java @@ -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 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 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); + } + +} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactoryTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactoryTest.java new file mode 100644 index 000000000000..2942a4ba6172 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/SourceLineReadersFactoryTest.java @@ -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); + // } + } + +} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStepTest.java index 245602dcb3f3..7d2b6bd644ce 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistFileSourcesStepTest.java @@ -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.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 @@ protected ComputationStep step() { @Test public void persist_sources() { - initBasicReport(2); - when(lineHashesComputer.getResult()).thenReturn(Lists.newArrayList("137f72c3708c6bd0de00a0e5a69c699b", "e6251bcf1a7dc3ba5e7933e325bbe605")); + List 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 void persist_sources() { @Test public void persist_source_hashes() { - initBasicReport(2); - when(lineHashesComputer.getResult()).thenReturn(Lists.newArrayList("137f72c3708c6bd0de00a0e5a69c699b", "e6251bcf1a7dc3ba5e7933e325bbe605")); + List 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 void persist_source_hashes() { @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 void persist_scm_some_lines() { 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 void save_revision() { @Test public void not_save_revision() { - initBasicReport(1); + setComputedData(DbFileSources.Data.newBuilder().build()); underTest.execute(new TestComputationStepContext()); @@ -326,41 +297,20 @@ public void not_save_revision() { @Test public void not_update_sources_when_nothing_has_changed() { - // Existing sources - long past = 150000L; - String srcHash = "137f72c3708c6bd0de00a0e5a69c699b"; - List 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 void update_sources_when_source_updated() { .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 void update_sources_when_source_updated() { .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 void update_sources_when_source_updated() { @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 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 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 @@ private void initBasicReport(int numberOfLines) { .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); - } } }