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.MergeBranchComponentUuids;
41 import org.sonar.server.computation.task.projectanalysis.scm.ScmInfoRepositoryImpl.NoScmInfo;
42 import org.sonar.server.computation.task.projectanalysis.source.SourceHashRepositoryImpl;
43 import org.sonar.server.computation.task.projectanalysis.source.SourceLinesRepositoryImpl;
45 import static org.assertj.core.api.Assertions.assertThat;
46 import static org.mockito.Mockito.mock;
47 import static org.mockito.Mockito.when;
48 import static org.sonar.api.utils.log.LoggerLevel.TRACE;
49 import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
51 public class ScmInfoDbLoaderTest {
52 static final int FILE_REF = 1;
53 static final Component FILE = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").build();
54 static final long DATE_1 = 123456789L;
55 static final long DATE_2 = 1234567810L;
57 static Analysis baseProjectAnalysis = new Analysis.Builder()
60 .setCreatedAt(123456789L)
64 public LogTester logTester = new LogTester();
66 public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
68 public DbTester dbTester = DbTester.create(System2.INSTANCE);
70 public BatchReportReaderRule reportReader = new BatchReportReaderRule();
72 private Branch branch = mock(Branch.class);
73 private SourceHashRepositoryImpl sourceHashRepository = new SourceHashRepositoryImpl(new SourceLinesRepositoryImpl(reportReader));
74 private MergeBranchComponentUuids mergeBranchComponentUuids = mock(MergeBranchComponentUuids.class);
76 private ScmInfoDbLoader underTest = new ScmInfoDbLoader(analysisMetadataHolder, dbTester.getDbClient(), sourceHashRepository, mergeBranchComponentUuids);
79 public void returns_ScmInfo_from_DB_if_hashes_are_the_same() throws Exception {
80 analysisMetadataHolder.setBaseAnalysis(baseProjectAnalysis);
81 analysisMetadataHolder.setBranch(null);
83 addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1));
84 addFileSourceInReport(1);
86 ScmInfo scmInfo = underTest.getScmInfoFromDb(FILE);
87 assertThat(scmInfo.getAllChangesets()).hasSize(1);
89 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'FILE_UUID'");
93 public void read_from_merge_branch_if_no_base() {
94 analysisMetadataHolder.setBaseAnalysis(null);
95 analysisMetadataHolder.setBranch(branch);
96 String mergeFileUuid = "mergeFileUuid";
98 when(mergeBranchComponentUuids.getUuid(FILE.getKey())).thenReturn(mergeFileUuid);
99 addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1), mergeFileUuid);
100 addFileSourceInReport(1);
102 ScmInfo scmInfo = underTest.getScmInfoFromDb(FILE);
103 assertThat(scmInfo.getAllChangesets()).hasSize(1);
104 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'mergeFileUuid'");
108 public void returns_absent_when_branch_and_source_is_different() {
109 analysisMetadataHolder.setBaseAnalysis(null);
110 analysisMetadataHolder.setBranch(branch);
111 String mergeFileUuid = "mergeFileUuid";
113 when(mergeBranchComponentUuids.getUuid(FILE.getKey())).thenReturn(mergeFileUuid);
114 addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1) + "dif", mergeFileUuid);
115 addFileSourceInReport(1);
117 assertThat(underTest.getScmInfoFromDb(FILE)).isEqualTo(NoScmInfo.INSTANCE);
118 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'mergeFileUuid'");
122 public void returns_absent_when__hashes_are_not_the_same() throws Exception {
123 analysisMetadataHolder.setBaseAnalysis(baseProjectAnalysis);
124 analysisMetadataHolder.setBranch(null);
126 addFileSourceInReport(1);
127 addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1) + "_different");
129 assertThat(underTest.getScmInfoFromDb(FILE)).isEqualTo(NoScmInfo.INSTANCE);
130 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'FILE_UUID'");
134 public void not_read_in_db_on_first_analysis() throws Exception {
135 analysisMetadataHolder.setBaseAnalysis(null);
136 analysisMetadataHolder.setBranch(null);
138 addFileSourceInReport(1);
140 assertThat(underTest.getScmInfoFromDb(FILE)).isEqualTo(NoScmInfo.INSTANCE);
141 assertThat(logTester.logs(TRACE)).isEmpty();
144 private static List<String> generateLines(int lineCount) {
145 ImmutableList.Builder<String> builder = ImmutableList.builder();
146 for (int i = 0; i < lineCount; i++) {
147 builder.add("line " + i);
149 return builder.build();
152 private static String computeSourceHash(int lineCount) {
153 SourceHashComputer sourceHashComputer = new SourceHashComputer();
154 Iterator<String> lines = generateLines(lineCount).iterator();
155 while (lines.hasNext()) {
156 sourceHashComputer.addLine(lines.next(), lines.hasNext());
158 return sourceHashComputer.getHash();
161 private void addFileSourceInDb(@Nullable String author, @Nullable Long date, @Nullable String revision, String srcHash) {
162 addFileSourceInDb(author, date, revision, srcHash, FILE.getUuid());
165 private void addFileSourceInDb(@Nullable String author, @Nullable Long date, @Nullable String revision, String srcHash, String fileUuid) {
166 DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder();
167 DbFileSources.Line.Builder builder = fileDataBuilder.addLinesBuilder()
169 if (author != null) {
170 builder.setScmAuthor(author);
173 builder.setScmDate(date);
175 if (revision != null) {
176 builder.setScmRevision(revision);
178 dbTester.getDbClient().fileSourceDao().insert(dbTester.getSession(), new FileSourceDto()
179 .setFileUuid(fileUuid)
180 .setProjectUuid("PROJECT_UUID")
181 .setSourceData(fileDataBuilder.build())
182 .setSrcHash(srcHash));
186 private void addFileSourceInReport(int lineCount) {
187 reportReader.putFileSourceLines(FILE_REF, generateLines(lineCount));
188 reportReader.putComponent(ScannerReport.Component.newBuilder()