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