]> source.dussan.org Git - sonarqube.git/blob
dc1c6b98f564582f61e9f2cabccff66cf91de7a6
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2017 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.server.computation.task.projectanalysis.scm;
21
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;
45
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;
51
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;
57
58   static Analysis baseProjectAnalysis = new Analysis.Builder()
59     .setId(1)
60     .setUuid("uuid_1")
61     .setCreatedAt(123456789L)
62     .build();
63
64   @Rule
65   public LogTester logTester = new LogTester();
66   @Rule
67   public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
68   @Rule
69   public DbTester dbTester = DbTester.create(System2.INSTANCE);
70   @Rule
71   public BatchReportReaderRule reportReader = new BatchReportReaderRule();
72
73   private Branch branch = mock(Branch.class);
74   private SourceHashRepositoryImpl sourceHashRepository = new SourceHashRepositoryImpl(new SourceLinesRepositoryImpl(reportReader));
75   private MergeBranchComponentUuids mergeBranchComponentUuids = mock(MergeBranchComponentUuids.class);
76
77   private ScmInfoDbLoader underTest = new ScmInfoDbLoader(analysisMetadataHolder, dbTester.getDbClient(), sourceHashRepository, mergeBranchComponentUuids);
78
79   @Test
80   public void dont_check_hash_for_unmodified_files_incremental_analysis() {
81     analysisMetadataHolder.setIncrementalAnalysis(true);
82     analysisMetadataHolder.setBranch(null);
83     analysisMetadataHolder.setBaseAnalysis(baseProjectAnalysis);
84
85     addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1));
86
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);
90
91     assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'FILE_UUID'");
92   }
93
94   @Test
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);
99
100     addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1));
101     addFileSourceInReport(1);
102
103     ScmInfo scmInfo = underTest.getScmInfoFromDb(FILE);
104     assertThat(scmInfo.getAllChangesets()).hasSize(1);
105
106     assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'FILE_UUID'");
107   }
108
109   @Test
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";
115
116     when(mergeBranchComponentUuids.getUuid(FILE.getKey())).thenReturn(mergeFileUuid);
117     addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1), mergeFileUuid);
118     addFileSourceInReport(1);
119
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'");
123   }
124
125   @Test
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";
131
132     when(mergeBranchComponentUuids.getUuid(FILE.getKey())).thenReturn(mergeFileUuid);
133     addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1) + "dif", mergeFileUuid);
134     addFileSourceInReport(1);
135
136     assertThat(underTest.getScmInfoFromDb(FILE)).isEqualTo(NoScmInfo.INSTANCE);
137     assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'mergeFileUuid'");
138   }
139
140   @Test
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);
145
146     addFileSourceInReport(1);
147     addFileSourceInDb("henry", DATE_1, "rev-1", computeSourceHash(1) + "_different");
148
149     assertThat(underTest.getScmInfoFromDb(FILE)).isEqualTo(NoScmInfo.INSTANCE);
150     assertThat(logTester.logs(TRACE)).containsOnly("Reading SCM info from db for file 'FILE_UUID'");
151   }
152
153   @Test
154   public void not_read_in_db_on_first_analysis() throws Exception {
155     analysisMetadataHolder.setBaseAnalysis(null);
156     analysisMetadataHolder.setBranch(null);
157
158     addFileSourceInReport(1);
159
160     assertThat(underTest.getScmInfoFromDb(FILE)).isEqualTo(NoScmInfo.INSTANCE);
161     assertThat(logTester.logs(TRACE)).isEmpty();
162   }
163
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);
168     }
169     return builder.build();
170   }
171
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());
177     }
178     return sourceHashComputer.getHash();
179   }
180
181   private void addFileSourceInDb(@Nullable String author, @Nullable Long date, @Nullable String revision, String srcHash) {
182     addFileSourceInDb(author, date, revision, srcHash, FILE.getUuid());
183   }
184
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()
188       .setLine(1);
189     if (author != null) {
190       builder.setScmAuthor(author);
191     }
192     if (date != null) {
193       builder.setScmDate(date);
194     }
195     if (revision != null) {
196       builder.setScmRevision(revision);
197     }
198     dbTester.getDbClient().fileSourceDao().insert(dbTester.getSession(), new FileSourceDto()
199       .setFileUuid(fileUuid)
200       .setProjectUuid("PROJECT_UUID")
201       .setSourceData(fileDataBuilder.build())
202       .setSrcHash(srcHash));
203     dbTester.commit();
204   }
205
206   private void addFileSourceInReport(int lineCount) {
207     reportReader.putFileSourceLines(FILE_REF, generateLines(lineCount));
208     reportReader.putComponent(ScannerReport.Component.newBuilder()
209       .setRef(FILE_REF)
210       .setLines(lineCount)
211       .build());
212   }
213 }