]> source.dussan.org Git - sonarqube.git/blob
f77eb52d62476703837e91adbf3f0bc8c5cba21a
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2023 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.ce.task.projectanalysis.component;
21
22 import com.tngtech.java.junit.dataprovider.DataProvider;
23 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
24 import com.tngtech.java.junit.dataprovider.UseDataProvider;
25 import java.util.Collections;
26 import java.util.Optional;
27 import javax.annotation.Nullable;
28 import org.assertj.core.api.ThrowableAssert;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.sonar.api.config.internal.ConfigurationBridge;
33 import org.sonar.api.config.internal.MapSettings;
34 import org.sonar.api.utils.System2;
35 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
36 import org.sonar.ce.task.projectanalysis.analysis.Branch;
37 import org.sonar.db.DbSession;
38 import org.sonar.db.DbTester;
39 import org.sonar.db.component.BranchDto;
40 import org.sonar.db.component.BranchType;
41 import org.sonar.db.component.ComponentDto;
42 import org.sonar.db.component.ComponentTesting;
43 import org.sonar.db.protobuf.DbProjectBranches;
44 import org.sonar.server.project.Project;
45
46 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
47 import static org.assertj.core.api.Assertions.assertThat;
48 import static org.assertj.core.api.Assertions.assertThatThrownBy;
49 import static org.mockito.Mockito.mock;
50 import static org.mockito.Mockito.when;
51 import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder;
52 import static org.sonar.core.config.PurgeConstants.BRANCHES_TO_KEEP_WHEN_INACTIVE;
53 import static org.sonar.db.component.BranchType.BRANCH;
54 import static org.sonar.db.component.BranchType.PULL_REQUEST;
55
56 @RunWith(DataProviderRunner.class)
57 public class BranchPersisterImplIT {
58   private final static Component MAIN = builder(Component.Type.PROJECT, 1, "PROJECT_KEY").setUuid("PROJECT_UUID").setName("p1").build();
59   private final static Component BRANCH1 = builder(Component.Type.PROJECT, 2, "BRANCH_KEY").setUuid("BRANCH_UUID").build();
60   private final static Component PR1 = builder(Component.Type.PROJECT, 3, "develop").setUuid("PR_UUID").build();
61   private static final Project PROJECT = new Project(MAIN.getUuid(), MAIN.getKey(), MAIN.getName(), null, Collections.emptyList());
62
63   @Rule
64   public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
65   @Rule
66   public DbTester dbTester = DbTester.create(System2.INSTANCE);
67   @Rule
68   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
69
70   private final MapSettings settings = new MapSettings();
71   private final ConfigurationRepository configurationRepository = new TestSettingsRepository(new ConfigurationBridge(settings));
72   private final BranchPersister underTest = new BranchPersisterImpl(dbTester.getDbClient(), treeRootHolder, analysisMetadataHolder, configurationRepository);
73
74   @Test
75   public void persist_fails_with_ISE_if_no_component_for_main_branches() {
76     analysisMetadataHolder.setBranch(createBranch(BRANCH, true, "master"));
77     analysisMetadataHolder.setProject(PROJECT);
78     treeRootHolder.setRoot(MAIN);
79     DbSession dbSession = dbTester.getSession();
80
81     expectMissingComponentISE(() -> underTest.persist(dbSession));
82   }
83
84   @Test
85   public void persist_fails_with_ISE_if_no_component_for_branches() {
86     analysisMetadataHolder.setBranch(createBranch(BRANCH, false, "foo"));
87     analysisMetadataHolder.setProject(PROJECT);
88
89     treeRootHolder.setRoot(BRANCH1);
90     DbSession dbSession = dbTester.getSession();
91
92     expectMissingComponentISE(() -> underTest.persist(dbSession));
93   }
94
95   @Test
96   public void persist_fails_with_ISE_if_no_component_for_pull_request() {
97     analysisMetadataHolder.setBranch(createBranch(BranchType.PULL_REQUEST, false, "12"));
98     analysisMetadataHolder.setProject(PROJECT);
99
100     treeRootHolder.setRoot(BRANCH1);
101     DbSession dbSession = dbTester.getSession();
102
103     expectMissingComponentISE(() -> underTest.persist(dbSession));
104   }
105
106   @Test
107   @UseDataProvider("nullOrNotNullString")
108   public void persist_creates_row_in_PROJECTS_BRANCHES_for_branch(@Nullable String mergeBranchUuid) {
109     String branchName = "branch";
110
111     // add project and branch in table PROJECTS
112     ComponentDto mainComponent = ComponentTesting.newPrivateProjectDto(MAIN.getUuid()).setKey(MAIN.getKey());
113     ComponentDto component = ComponentTesting.newBranchComponent(mainComponent,
114       new BranchDto().setUuid(BRANCH1.getUuid()).setKey(BRANCH1.getKey()).setBranchType(BRANCH));
115     dbTester.components().insertComponents(mainComponent, component);
116     // set project in metadata
117     treeRootHolder.setRoot(BRANCH1);
118     analysisMetadataHolder.setBranch(createBranch(BRANCH, false, branchName, mergeBranchUuid));
119     analysisMetadataHolder.setProject(Project.from(mainComponent));
120
121     underTest.persist(dbTester.getSession());
122
123     dbTester.getSession().commit();
124
125     assertThat(dbTester.countRowsOfTable("components")).isEqualTo(2);
126     Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), BRANCH1.getUuid());
127     assertThat(branchDto).isPresent();
128     assertThat(branchDto.get().getBranchType()).isEqualTo(BRANCH);
129     assertThat(branchDto.get().getKey()).isEqualTo(branchName);
130     assertThat(branchDto.get().getMergeBranchUuid()).isEqualTo(mergeBranchUuid);
131     assertThat(branchDto.get().getProjectUuid()).isEqualTo(MAIN.getUuid());
132     assertThat(branchDto.get().getPullRequestData()).isNull();
133   }
134
135   @Test
136   public void main_branch_is_excluded_from_branch_purge_by_default() {
137     analysisMetadataHolder.setBranch(createBranch(BRANCH, true, "master"));
138     analysisMetadataHolder.setProject(PROJECT);
139     treeRootHolder.setRoot(MAIN);
140     dbTester.components().insertPublicProject(p -> p.setKey(MAIN.getKey()).setUuid(MAIN.getUuid()));
141     dbTester.commit();
142
143     underTest.persist(dbTester.getSession());
144
145     Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), MAIN.getUuid());
146     assertThat(branchDto).isPresent();
147     assertThat(branchDto.get().isExcludeFromPurge()).isTrue();
148   }
149
150   @Test
151   public void non_main_branch_is_excluded_from_branch_purge_if_matches_sonar_dbcleaner_keepFromPurge_property() {
152     settings.setProperty(BRANCHES_TO_KEEP_WHEN_INACTIVE, "BRANCH.*");
153     analysisMetadataHolder.setProject(PROJECT);
154     analysisMetadataHolder.setBranch(createBranch(BRANCH, false, "BRANCH_KEY"));
155     treeRootHolder.setRoot(BRANCH1);
156     ComponentDto mainComponent = dbTester.components().insertPublicProject(p -> p.setKey(MAIN.getKey()).setUuid(MAIN.getUuid()));
157     ComponentDto component = ComponentTesting.newBranchComponent(mainComponent,
158       new BranchDto().setUuid(BRANCH1.getUuid()).setKey(BRANCH1.getKey()).setBranchType(BRANCH));
159     dbTester.getDbClient().componentDao().insert(dbTester.getSession(), component);
160     dbTester.commit();
161
162     underTest.persist(dbTester.getSession());
163
164     Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), BRANCH1.getUuid());
165     assertThat(branchDto).isPresent();
166     assertThat(branchDto.get().isExcludeFromPurge()).isTrue();
167   }
168
169   @Test
170   public void branch_is_excluded_from_purge_when_it_matches_setting() {
171     analysisMetadataHolder.setProject(PROJECT);
172     analysisMetadataHolder.setBranch(createBranch(BRANCH, false, "BRANCH_KEY"));
173     treeRootHolder.setRoot(BRANCH1);
174     ComponentDto mainComponent = dbTester.components().insertPublicProject(p -> p.setKey(MAIN.getKey()).setUuid(MAIN.getUuid()));
175     ComponentDto component = ComponentTesting.newBranchComponent(mainComponent,
176       new BranchDto().setUuid(BRANCH1.getUuid()).setKey(BRANCH1.getKey()).setBranchType(BRANCH));
177     dbTester.getDbClient().componentDao().insert(dbTester.getSession(), component);
178     settings.setProperty(BRANCHES_TO_KEEP_WHEN_INACTIVE, "BRANCH.*");
179     dbTester.commit();
180
181     underTest.persist(dbTester.getSession());
182
183     Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), BRANCH1.getUuid());
184     assertThat(branchDto).isPresent();
185     assertThat(branchDto.get().isExcludeFromPurge()).isTrue();
186   }
187
188   @Test
189   public void branch_is_not_excluded_from_purge_when_it_does_not_match_setting() {
190     analysisMetadataHolder.setProject(PROJECT);
191     analysisMetadataHolder.setBranch(createBranch(BRANCH, false, "BRANCH_KEY"));
192     treeRootHolder.setRoot(BRANCH1);
193     ComponentDto mainComponent = dbTester.components().insertPublicProject(p -> p.setKey(MAIN.getKey()).setUuid(MAIN.getUuid()));
194     ComponentDto component = ComponentTesting.newBranchComponent(mainComponent,
195       new BranchDto().setUuid(BRANCH1.getUuid()).setKey(BRANCH1.getKey()).setBranchType(BRANCH));
196     dbTester.getDbClient().componentDao().insert(dbTester.getSession(), component);
197     settings.setProperty(BRANCHES_TO_KEEP_WHEN_INACTIVE, "abc.*");
198
199     dbTester.commit();
200
201     underTest.persist(dbTester.getSession());
202
203     Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), BRANCH1.getUuid());
204     assertThat(branchDto).isPresent();
205     assertThat(branchDto.get().isExcludeFromPurge()).isFalse();
206   }
207
208   @Test
209   public void pull_request_is_never_excluded_from_branch_purge_even_if_its_source_branch_name_matches_sonar_dbcleaner_keepFromPurge_property() {
210     settings.setProperty(BRANCHES_TO_KEEP_WHEN_INACTIVE, "develop");
211     analysisMetadataHolder.setBranch(createPullRequest(PR1.getKey(), MAIN.getUuid()));
212     analysisMetadataHolder.setProject(PROJECT);
213
214     analysisMetadataHolder.setPullRequestKey(PR1.getKey());
215     treeRootHolder.setRoot(PR1);
216     ComponentDto mainComponent = dbTester.components().insertPublicProject(p -> p.setKey(MAIN.getKey()).setUuid(MAIN.getUuid()));
217     ComponentDto component = ComponentTesting.newBranchComponent(mainComponent, new BranchDto()
218       .setUuid(PR1.getUuid())
219       .setKey(PR1.getKey())
220       .setProjectUuid(MAIN.getUuid())
221       .setBranchType(PULL_REQUEST)
222       .setMergeBranchUuid(MAIN.getUuid()));
223     dbTester.getDbClient().componentDao().insert(dbTester.getSession(), component);
224     dbTester.commit();
225
226     underTest.persist(dbTester.getSession());
227
228     Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), PR1.getUuid());
229     assertThat(branchDto).isPresent();
230     assertThat(branchDto.get().isExcludeFromPurge()).isFalse();
231   }
232
233   @Test
234   public void non_main_branch_is_included_in_branch_purge_if_branch_name_does_not_match_sonar_dbcleaner_keepFromPurge_property() {
235     settings.setProperty(BRANCHES_TO_KEEP_WHEN_INACTIVE, "foobar-.*");
236     analysisMetadataHolder.setProject(PROJECT);
237     analysisMetadataHolder.setBranch(createBranch(BRANCH, false, "BRANCH_KEY"));
238     treeRootHolder.setRoot(BRANCH1);
239     ComponentDto mainComponent = dbTester.components().insertPublicProject(p -> p.setKey(MAIN.getKey()).setUuid(MAIN.getUuid()));
240     ComponentDto component = ComponentTesting.newBranchComponent(mainComponent,
241       new BranchDto().setUuid(BRANCH1.getUuid()).setKey(BRANCH1.getKey()).setBranchType(BRANCH));
242     dbTester.getDbClient().componentDao().insert(dbTester.getSession(), component);
243     dbTester.commit();
244
245     underTest.persist(dbTester.getSession());
246
247     Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), BRANCH1.getUuid());
248     assertThat(branchDto).isPresent();
249     assertThat(branchDto.get().isExcludeFromPurge()).isFalse();
250   }
251
252   @DataProvider
253   public static Object[][] nullOrNotNullString() {
254     return new Object[][] {
255       {null},
256       {randomAlphabetic(12)}
257     };
258   }
259
260   @Test
261   public void persist_creates_row_in_PROJECTS_BRANCHES_for_pull_request() {
262     String pullRequestId = "pr-123";
263
264     // add project and branch in table PROJECTS
265     ComponentDto mainComponent = ComponentTesting.newPrivateProjectDto(MAIN.getUuid()).setKey(MAIN.getKey());
266     ComponentDto component = ComponentTesting.newBranchComponent(mainComponent,
267       new BranchDto().setUuid(BRANCH1.getUuid()).setKey(BRANCH1.getKey()).setBranchType(PULL_REQUEST));
268     dbTester.components().insertComponents(mainComponent, component);
269     // set project in metadata
270     treeRootHolder.setRoot(BRANCH1);
271     analysisMetadataHolder.setBranch(createBranch(PULL_REQUEST, false, pullRequestId, "mergeBanchUuid"));
272     analysisMetadataHolder.setProject(Project.from(mainComponent));
273     analysisMetadataHolder.setPullRequestKey(pullRequestId);
274
275     underTest.persist(dbTester.getSession());
276
277     dbTester.getSession().commit();
278
279     assertThat(dbTester.countRowsOfTable("components")).isEqualTo(2);
280     Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), BRANCH1.getUuid());
281     assertThat(branchDto).isPresent();
282     assertThat(branchDto.get().getBranchType()).isEqualTo(PULL_REQUEST);
283     assertThat(branchDto.get().getKey()).isEqualTo(pullRequestId);
284     assertThat(branchDto.get().getMergeBranchUuid()).isEqualTo("mergeBanchUuid");
285     assertThat(branchDto.get().getProjectUuid()).isEqualTo(MAIN.getUuid());
286     assertThat(branchDto.get().getPullRequestData()).isEqualTo(DbProjectBranches.PullRequestData.newBuilder()
287       .setBranch(pullRequestId)
288       .setTarget("mergeBanchUuid")
289       .setTitle(pullRequestId)
290       .build());
291   }
292
293   private static Branch createBranch(BranchType type, boolean isMain, String name) {
294     return createBranch(type, isMain, name, null);
295   }
296
297   private static Branch createPullRequest(String key, String mergeBranchUuid) {
298     Branch branch = createBranch(PULL_REQUEST, false, key, mergeBranchUuid);
299     when(branch.getPullRequestKey()).thenReturn(key);
300     return branch;
301   }
302
303   private static Branch createBranch(BranchType type, boolean isMain, String name, @Nullable String mergeBranchUuid) {
304     Branch branch = mock(Branch.class);
305     when(branch.getType()).thenReturn(type);
306     when(branch.getName()).thenReturn(name);
307     when(branch.isMain()).thenReturn(isMain);
308     when(branch.getReferenceBranchUuid()).thenReturn(mergeBranchUuid);
309     when(branch.getTargetBranchName()).thenReturn(mergeBranchUuid);
310     return branch;
311   }
312
313   private void expectMissingComponentISE(ThrowableAssert.ThrowingCallable callable) {
314     assertThatThrownBy(callable)
315       .isInstanceOf(IllegalStateException.class)
316       .hasMessage("Component has been deleted by end-user during analysis");
317   }
318 }