3 * Copyright (C) 2009-2017 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.computation.task.projectanalysis.scm;
22 import com.google.common.collect.ImmutableList;
23 import java.util.Iterator;
24 import java.util.List;
25 import javax.annotation.Nullable;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.sonar.api.utils.System2;
29 import org.sonar.api.utils.log.LogTester;
30 import org.sonar.core.hash.SourceHashComputer;
31 import org.sonar.db.DbTester;
32 import org.sonar.db.protobuf.DbFileSources;
33 import org.sonar.db.source.FileSourceDto;
34 import org.sonar.scanner.protocol.output.ScannerReport;
35 import org.sonar.server.computation.task.projectanalysis.analysis.Analysis;
36 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
37 import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
38 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
39 import org.sonar.server.computation.task.projectanalysis.component.Component;
40 import org.sonar.server.computation.task.projectanalysis.component.Component.Status;
41 import org.sonar.server.computation.task.projectanalysis.component.MergeBranchComponentUuids;
42 import org.sonar.server.computation.task.projectanalysis.scm.ScmInfoRepositoryImpl.NoScmInfo;
43 import org.sonar.server.computation.task.projectanalysis.source.SourceHashRepositoryImpl;
44 import org.sonar.server.computation.task.projectanalysis.source.SourceLinesRepositoryImpl;
46 import static org.assertj.core.api.Assertions.assertThat;
47 import static org.mockito.Mockito.mock;
48 import static org.mockito.Mockito.when;
49 import static org.sonar.api.utils.log.LoggerLevel.TRACE;
50 import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
52 public class ScmInfoDbLoaderTest {
53 static final int FILE_REF = 1;
54 static final Component FILE = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").build();
55 static final long DATE_1 = 123456789L;
56 static final long DATE_2 = 1234567810L;
58 static Analysis baseProjectAnalysis = new Analysis.Builder()
61 .setCreatedAt(123456789L)
65 public LogTester logTester = new LogTester();
67 public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
69 public DbTester dbTester = DbTester.create(System2.INSTANCE);
71 public BatchReportReaderRule reportReader = new BatchReportReaderRule();
73 private Branch branch = mock(Branch.class);
74 private SourceHashRepositoryImpl sourceHashRepository = new SourceHashRepositoryImpl(new SourceLinesRepositoryImpl(reportReader));
75 private MergeBranchComponentUuids mergeBranchComponentUuids = mock(MergeBranchComponentUuids.class);
77 private ScmInfoDbLoader underTest = new ScmInfoDbLoader(analysisMetadataHolder, dbTester.getDbClient(), sourceHashRepository, mergeBranchComponentUuids);
80 public void dont_check_hash_for_unmodified_files_incremental_analysis() {
81 analysisMetadataHolder.setIncrementalAnalysis(true);
82 analysisMetadataHolder.setBranch(null);
83 analysisMetadataHolder.setBaseAnalysis(baseProjectAnalysis);
85 addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1));
87 Component file = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").setStatus(Status.SAME).build();
88 ScmInfo scmInfo = underTest.getScmInfoFromDb(file);
89 assertThat(scmInfo.getAllChangesets()).hasSize(1);
91 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'FILE_UUID'");
95 public void returns_ScmInfo_from_DB_if_hashes_are_the_same() throws Exception {
96 analysisMetadataHolder.setBaseAnalysis(baseProjectAnalysis);
97 analysisMetadataHolder.setBranch(null);
98 analysisMetadataHolder.setIncrementalAnalysis(false);
100 addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1));
101 addFileSourceInReport(1);
103 ScmInfo scmInfo = underTest.getScmInfoFromDb(FILE);
104 assertThat(scmInfo.getAllChangesets()).hasSize(1);
106 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'FILE_UUID'");
110 public void read_from_merge_branch_if_no_base() {
111 analysisMetadataHolder.setBaseAnalysis(null);
112 analysisMetadataHolder.setBranch(branch);
113 analysisMetadataHolder.setIncrementalAnalysis(false);
114 String mergeFileUuid = "mergeFileUuid";
116 when(mergeBranchComponentUuids.getUuid(FILE.getKey())).thenReturn(mergeFileUuid);
117 addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1), mergeFileUuid);
118 addFileSourceInReport(1);
120 ScmInfo scmInfo = underTest.getScmInfoFromDb(FILE);
121 assertThat(scmInfo.getAllChangesets()).hasSize(1);
122 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'mergeFileUuid'");
126 public void returns_absent_when_branch_and_source_is_different() {
127 analysisMetadataHolder.setBaseAnalysis(null);
128 analysisMetadataHolder.setBranch(branch);
129 analysisMetadataHolder.setIncrementalAnalysis(false);
130 String mergeFileUuid = "mergeFileUuid";
132 when(mergeBranchComponentUuids.getUuid(FILE.getKey())).thenReturn(mergeFileUuid);
133 addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1) + "dif", mergeFileUuid);
134 addFileSourceInReport(1);
136 assertThat(underTest.getScmInfoFromDb(FILE)).isEqualTo(NoScmInfo.INSTANCE);
137 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'mergeFileUuid'");
141 public void returns_absent_when__hashes_are_not_the_same() throws Exception {
142 analysisMetadataHolder.setBaseAnalysis(baseProjectAnalysis);
143 analysisMetadataHolder.setBranch(null);
144 analysisMetadataHolder.setIncrementalAnalysis(false);
146 addFileSourceInReport(1);
147 addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1) + "_different");
149 assertThat(underTest.getScmInfoFromDb(FILE)).isEqualTo(NoScmInfo.INSTANCE);
150 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'FILE_UUID'");
154 public void not_read_in_db_on_first_analysis() throws Exception {
155 analysisMetadataHolder.setBaseAnalysis(null);
156 analysisMetadataHolder.setBranch(null);
158 addFileSourceInReport(1);
160 assertThat(underTest.getScmInfoFromDb(FILE)).isEqualTo(NoScmInfo.INSTANCE);
161 assertThat(logTester.logs(TRACE)).isEmpty();
164 private static List<String> generateLines(int lineCount) {
165 ImmutableList.Builder<String> builder = ImmutableList.builder();
166 for (int i = 0; i < lineCount; i++) {
167 builder.add("line " + i);
169 return builder.build();
172 private static String computeSourceHash(int lineCount) {
173 SourceHashComputer sourceHashComputer = new SourceHashComputer();
174 Iterator<String> lines = generateLines(lineCount).iterator();
175 while (lines.hasNext()) {
176 sourceHashComputer.addLine(lines.next(), lines.hasNext());
178 return sourceHashComputer.getHash();
181 private void addFileSourceInDb(@Nullable String author, @Nullable Long date, @Nullable String revision, String srcHash) {
182 addFileSourceInDb(author, date, revision, srcHash, FILE.getUuid());
185 private void addFileSourceInDb(@Nullable String author, @Nullable Long date, @Nullable String revision, String srcHash, String fileUuid) {
186 DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder();
187 DbFileSources.Line.Builder builder = fileDataBuilder.addLinesBuilder()
189 if (author != null) {
190 builder.setScmAuthor(author);
193 builder.setScmDate(date);
195 if (revision != null) {
196 builder.setScmRevision(revision);
198 dbTester.getDbClient().fileSourceDao().insert(dbTester.getSession(), new FileSourceDto()
199 .setFileUuid(fileUuid)
200 .setProjectUuid("PROJECT_UUID")
201 .setSourceData(fileDataBuilder.build())
202 .setSrcHash(srcHash));
206 private void addFileSourceInReport(int lineCount) {
207 reportReader.putFileSourceLines(FILE_REF, generateLines(lineCount));
208 reportReader.putComponent(ScannerReport.Component.newBuilder()