3 * Copyright (C) 2009-2020 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.ce.task.projectanalysis.scm;
22 import com.google.common.collect.ImmutableList;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Optional;
27 import javax.annotation.Nullable;
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.sonar.api.utils.System2;
31 import org.sonar.api.utils.log.LogTester;
32 import org.sonar.ce.task.projectanalysis.analysis.Analysis;
33 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
34 import org.sonar.ce.task.projectanalysis.analysis.Branch;
35 import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule;
36 import org.sonar.ce.task.projectanalysis.component.Component;
37 import org.sonar.ce.task.projectanalysis.component.ReferenceBranchComponentUuids;
38 import org.sonar.core.hash.SourceHashComputer;
39 import org.sonar.db.DbTester;
40 import org.sonar.db.component.BranchType;
41 import org.sonar.db.protobuf.DbFileSources;
42 import org.sonar.db.source.FileSourceDto;
44 import static org.assertj.core.api.Assertions.assertThat;
45 import static org.mockito.Mockito.mock;
46 import static org.mockito.Mockito.when;
47 import static org.sonar.api.utils.log.LoggerLevel.TRACE;
48 import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder;
50 public class ScmInfoDbLoaderTest {
51 static final int FILE_REF = 1;
52 static final Component FILE = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").build();
53 static final long DATE_1 = 123456789L;
54 static final long DATE_2 = 1234567810L;
56 static Analysis baseProjectAnalysis = new Analysis.Builder()
59 .setCreatedAt(123456789L)
63 public LogTester logTester = new LogTester();
65 public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
67 public DbTester dbTester = DbTester.create(System2.INSTANCE);
69 public BatchReportReaderRule reportReader = new BatchReportReaderRule();
71 private Branch branch = mock(Branch.class);
72 private ReferenceBranchComponentUuids referenceBranchComponentUuids = mock(ReferenceBranchComponentUuids.class);
74 private ScmInfoDbLoader underTest = new ScmInfoDbLoader(analysisMetadataHolder, dbTester.getDbClient(), referenceBranchComponentUuids);
77 public void returns_ScmInfo_from_DB() {
78 analysisMetadataHolder.setBaseAnalysis(baseProjectAnalysis);
79 analysisMetadataHolder.setBranch(null);
81 String hash = computeSourceHash(1);
82 addFileSourceInDb("henry", DATE_1, "rev-1", hash);
84 DbScmInfo scmInfo = underTest.getScmInfo(FILE).get();
85 assertThat(scmInfo.getAllChangesets()).hasSize(1);
86 assertThat(scmInfo.fileHash()).isEqualTo(hash);
88 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from DB for file 'FILE_UUID'");
92 public void read_from_reference_branch_if_no_base() {
93 analysisMetadataHolder.setBaseAnalysis(null);
94 analysisMetadataHolder.setBranch(branch);
96 String referenceFileUuid = "referenceFileUuid";
97 String hash = computeSourceHash(1);
99 when(referenceBranchComponentUuids.getComponentUuid(FILE.getDbKey())).thenReturn(referenceFileUuid);
100 addFileSourceInDb("henry", DATE_1, "rev-1", hash, referenceFileUuid);
102 DbScmInfo scmInfo = underTest.getScmInfo(FILE).get();
103 assertThat(scmInfo.getAllChangesets()).hasSize(1);
104 assertThat(scmInfo.fileHash()).isEqualTo(hash);
105 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from DB for file 'referenceFileUuid'");
109 public void read_from_target_if_pullrequest() {
110 Branch branch = mock(Branch.class);
111 when(branch.getType()).thenReturn(BranchType.PULL_REQUEST);
112 analysisMetadataHolder.setBaseAnalysis(null);
113 analysisMetadataHolder.setBranch(branch);
115 String targetBranchFileUuid = "targetBranchFileUuid";
116 String hash = computeSourceHash(1);
118 when(referenceBranchComponentUuids.getComponentUuid(FILE.getDbKey())).thenReturn(targetBranchFileUuid);
119 addFileSourceInDb("henry", DATE_1, "rev-1", hash, targetBranchFileUuid);
121 DbScmInfo scmInfo = underTest.getScmInfo(FILE).get();
122 assertThat(scmInfo.getAllChangesets()).hasSize(1);
123 assertThat(scmInfo.fileHash()).isEqualTo(hash);
124 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from DB for file 'targetBranchFileUuid'");
128 public void return_empty_if_no_dto_available() {
129 analysisMetadataHolder.setBaseAnalysis(baseProjectAnalysis);
130 analysisMetadataHolder.setBranch(null);
132 Optional<DbScmInfo> scmInfo = underTest.getScmInfo(FILE);
134 assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from DB for file 'FILE_UUID'");
135 assertThat(scmInfo).isEmpty();
139 public void do_not_read_from_db_on_first_analysis_if_there_is_no_reference_branch() {
140 Branch branch = mock(Branch.class);
141 when(branch.getType()).thenReturn(BranchType.PULL_REQUEST);
142 analysisMetadataHolder.setBaseAnalysis(null);
143 analysisMetadataHolder.setBranch(branch);
145 assertThat(underTest.getScmInfo(FILE)).isEmpty();
146 assertThat(logTester.logs(TRACE)).isEmpty();
149 private static List<String> generateLines(int lineCount) {
150 ImmutableList.Builder<String> builder = ImmutableList.builder();
151 for (int i = 0; i < lineCount; i++) {
152 builder.add("line " + i);
154 return builder.build();
157 private static String computeSourceHash(int lineCount) {
158 SourceHashComputer sourceHashComputer = new SourceHashComputer();
159 Iterator<String> lines = generateLines(lineCount).iterator();
160 while (lines.hasNext()) {
161 sourceHashComputer.addLine(lines.next(), lines.hasNext());
163 return sourceHashComputer.getHash();
166 private void addFileSourceInDb(@Nullable String author, @Nullable Long date, @Nullable String revision, String srcHash) {
167 addFileSourceInDb(author, date, revision, srcHash, FILE.getUuid());
170 private void addFileSourceInDb(@Nullable String author, @Nullable Long date, @Nullable String revision, String srcHash, String fileUuid) {
171 DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder();
172 DbFileSources.Line.Builder builder = fileDataBuilder.addLinesBuilder()
174 if (author != null) {
175 builder.setScmAuthor(author);
178 builder.setScmDate(date);
180 if (revision != null) {
181 builder.setScmRevision(revision);
183 dbTester.getDbClient().fileSourceDao().insert(dbTester.getSession(), new FileSourceDto()
184 .setLineHashes(Collections.singletonList("lineHash"))
185 .setFileUuid(fileUuid)
186 .setProjectUuid("PROJECT_UUID")
187 .setSourceData(fileDataBuilder.build())
188 .setSrcHash(srcHash));