]> source.dussan.org Git - sonarqube.git/blob
8507f576880b9ea8e492ab1587fd0b0a3e98adc7
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 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.projectexport.rule;
21
22 import com.google.common.collect.ImmutableList;
23 import com.sonarsource.governance.projectdump.protobuf.ProjectDump;
24 import java.util.Date;
25 import java.util.List;
26 import org.junit.Before;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.sonar.api.resources.Qualifiers;
30 import org.sonar.api.resources.Scopes;
31 import org.sonar.api.rule.RuleKey;
32 import org.sonar.api.rule.RuleStatus;
33 import org.sonar.api.utils.System2;
34 import org.sonar.api.utils.log.LogTester;
35 import org.sonar.api.utils.log.LoggerLevel;
36 import org.sonar.ce.task.projectexport.steps.DumpElement;
37 import org.sonar.ce.task.projectexport.steps.FakeDumpWriter;
38 import org.sonar.ce.task.projectexport.steps.ProjectHolder;
39 import org.sonar.ce.task.step.TestComputationStepContext;
40 import org.sonar.db.DbTester;
41 import org.sonar.db.component.BranchDto;
42 import org.sonar.db.component.BranchType;
43 import org.sonar.db.component.ComponentDto;
44 import org.sonar.db.issue.IssueDto;
45 import org.sonar.db.project.ProjectDto;
46 import org.sonar.db.rule.RuleDefinitionDto;
47 import org.sonar.db.rule.RuleDto;
48 import org.sonar.db.rule.RuleMetadataDto;
49
50 import static org.assertj.core.api.Assertions.assertThat;
51 import static org.assertj.core.api.Assertions.assertThatThrownBy;
52 import static org.assertj.core.api.Assertions.tuple;
53 import static org.mockito.Mockito.mock;
54 import static org.mockito.Mockito.when;
55 import static org.sonar.db.component.ComponentDto.UUID_PATH_OF_ROOT;
56
57 public class ExportAdHocRulesStepTest {
58   private static final String PROJECT_UUID = "some-uuid";
59
60   private static final ComponentDto PROJECT = new ComponentDto()
61     // no id yet
62     .setScope(Scopes.PROJECT)
63     .setQualifier(Qualifiers.PROJECT)
64     .setDbKey("the_project")
65     .setName("The Project")
66     .setDescription("The project description")
67     .setEnabled(true)
68     .setUuid(PROJECT_UUID)
69     .setUuidPath(UUID_PATH_OF_ROOT)
70     .setRootUuid(PROJECT_UUID)
71     .setModuleUuid(null)
72     .setModuleUuidPath("." + PROJECT_UUID + ".")
73     .setProjectUuid(PROJECT_UUID);
74
75   private static final List<BranchDto> BRANCHES = ImmutableList.of(
76     new BranchDto().setBranchType(BranchType.PULL_REQUEST).setProjectUuid(PROJECT_UUID).setKey("pr-1").setUuid("pr-1-uuid").setMergeBranchUuid("master"),
77     new BranchDto().setBranchType(BranchType.BRANCH).setProjectUuid(PROJECT_UUID).setKey("branch-2").setUuid("branch-2-uuid").setMergeBranchUuid("master")
78       .setExcludeFromPurge(true),
79     new BranchDto().setBranchType(BranchType.BRANCH).setProjectUuid(PROJECT_UUID).setKey("branch-3").setUuid("branch-3-uuid").setMergeBranchUuid("master")
80       .setExcludeFromPurge(false));
81
82
83   @Rule
84   public LogTester logTester = new LogTester();
85
86   @Rule
87   public DbTester dbTester = DbTester.create(System2.INSTANCE);
88
89   private int issueUuidGenerator = 1;
90   private FakeDumpWriter dumpWriter = new FakeDumpWriter();
91   private ProjectHolder projectHolder = mock(ProjectHolder.class);
92   private ExportAdHocRulesStep underTest = new ExportAdHocRulesStep(dbTester.getDbClient(), projectHolder, dumpWriter);
93
94   @Before
95   public void setup() {
96     ProjectDto project = createProject();
97     when(projectHolder.projectDto()).thenReturn(project);
98   }
99
100   @Test
101   public void export_zero_ad_hoc_rules() {
102     underTest.execute(new TestComputationStepContext());
103
104     List<ProjectDump.AdHocRule> exportedRules = dumpWriter.getWrittenMessagesOf(DumpElement.AD_HOC_RULES);
105     assertThat(exportedRules).isEmpty();
106     assertThat(logTester.logs(LoggerLevel.DEBUG)).contains("0 ad-hoc rules exported");
107   }
108
109   @Test
110   public void execute_only_exports_ad_hoc_rules_that_reference_project_issue() {
111     String differentProject = "diff-proj-uuid";
112     RuleDto rule1 = insertRule(RuleKey.of("plugin-1", "rule-1"), true, true);
113     RuleDto rule2 = insertRule(RuleKey.of("plugin-1", "rule-2"), true, true);
114     insertRule(RuleKey.of("plugin-1", "rule-3"), true, true);
115     insertIssue(rule1, differentProject, differentProject);
116     insertIssue(rule2, PROJECT_UUID, PROJECT_UUID);
117
118     underTest.execute(new TestComputationStepContext());
119
120     List<ProjectDump.AdHocRule> exportedRules = dumpWriter.getWrittenMessagesOf(DumpElement.AD_HOC_RULES);
121     assertThat(exportedRules).hasSize(1);
122     assertThat(exportedRules).extracting(ProjectDump.AdHocRule::getPluginName, ProjectDump.AdHocRule::getPluginRuleKey)
123       .containsOnly(tuple("plugin-1", "rule-2"));
124     assertThat(logTester.logs(LoggerLevel.DEBUG)).contains("1 ad-hoc rules exported");
125   }
126
127   @Test
128   public void execute_only_exports_rules_that_are_ad_hoc() {
129     RuleDto rule1 = insertRule(RuleKey.of("plugin-1", "rule-1"), false, false);
130     RuleDto rule2 = insertRule(RuleKey.of("plugin-1", "rule-2"), true, false);
131     RuleDto rule3 = insertRule(RuleKey.of("plugin-1", "rule-3"), true, true);
132     insertIssue(rule1, PROJECT_UUID, PROJECT_UUID);
133     insertIssue(rule2, PROJECT_UUID, PROJECT_UUID);
134     insertIssue(rule3, PROJECT_UUID, PROJECT_UUID);
135
136     underTest.execute(new TestComputationStepContext());
137
138     List<ProjectDump.AdHocRule> exportedRules = dumpWriter.getWrittenMessagesOf(DumpElement.AD_HOC_RULES);
139     assertThat(exportedRules).hasSize(1);
140     assertThat(exportedRules).extracting(ProjectDump.AdHocRule::getPluginName, ProjectDump.AdHocRule::getPluginRuleKey)
141       .containsOnly(tuple("plugin-1", "rule-3"));
142     assertThat(logTester.logs(LoggerLevel.DEBUG)).contains("1 ad-hoc rules exported");
143   }
144
145   @Test
146   public void execute_exports_ad_hoc_rules_that_are_referenced_by_issues_on_branches_excluded_from_purge() {
147     when(projectHolder.branches()).thenReturn(BRANCHES);
148     RuleDto rule1 = insertRule(RuleKey.of("plugin-1", "rule-1"), true, true);
149     RuleDto rule2 = insertRule(RuleKey.of("plugin-1", "rule-2"), true, true);
150     RuleDto rule3 = insertRule(RuleKey.of("plugin-1", "rule-3"), true, true);
151     insertIssue(rule1, "branch-1-uuid", "branch-1-uuid");
152     insertIssue(rule2, "branch-2-uuid", "branch-2-uuid");
153     insertIssue(rule3, "branch-3-uuid", "branch-3-uuid");
154
155     underTest.execute(new TestComputationStepContext());
156
157     List<ProjectDump.AdHocRule> exportedRules = dumpWriter.getWrittenMessagesOf(DumpElement.AD_HOC_RULES);
158     assertThat(exportedRules).hasSize(1);
159     assertThat(exportedRules).extracting(ProjectDump.AdHocRule::getPluginName, ProjectDump.AdHocRule::getPluginRuleKey)
160       .containsOnly(tuple("plugin-1", "rule-2"));
161     assertThat(logTester.logs(LoggerLevel.DEBUG)).contains("1 ad-hoc rules exported");
162   }
163
164   @Test
165   public void execute_throws_ISE_with_number_of_successful_exports_before_failure() {
166     RuleDto rule1 = insertRule(RuleKey.of("plugin-1", "rule-1"), true, true);
167     RuleDto rule2 = insertRule(RuleKey.of("plugin-1", "rule-2"), true, true);
168     RuleDto rule3 = insertRule(RuleKey.of("plugin-1", "rule-3"), true, true);
169     insertIssue(rule1, PROJECT_UUID, PROJECT_UUID);
170     insertIssue(rule2, PROJECT_UUID, PROJECT_UUID);
171     insertIssue(rule3, PROJECT_UUID, PROJECT_UUID);
172     dumpWriter.failIfMoreThan(2, DumpElement.AD_HOC_RULES);
173
174     assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
175       .isInstanceOf(IllegalStateException.class)
176       .hasMessage("Ad-hoc rules export failed after processing 2 rules successfully");
177   }
178
179   @Test
180   public void getDescription() {
181     assertThat(underTest.getDescription()).isEqualTo("Export ad-hoc rules");
182   }
183
184   private ProjectDto createProject() {
185     Date createdAt = new Date();
186     ComponentDto projectDto = dbTester.components().insertPublicProject(PROJECT);
187     BRANCHES.forEach(branch -> dbTester.components().insertProjectBranch(projectDto, branch).setCreatedAt(createdAt));
188     dbTester.commit();
189     return dbTester.components().getProjectDto(projectDto);
190   }
191
192   private void insertIssue(RuleDto ruleDto, String projectUuid, String componentUuid) {
193     IssueDto dto = createBaseIssueDto(ruleDto, projectUuid, componentUuid);
194     insertIssue(dto);
195   }
196
197   private void insertIssue(IssueDto dto) {
198     dbTester.getDbClient().issueDao().insert(dbTester.getSession(), dto);
199     dbTester.commit();
200   }
201
202   private IssueDto createBaseIssueDto(RuleDto ruleDto, String projectUuid, String componentUuid) {
203     return new IssueDto()
204       .setKee("issue_uuid_" + issueUuidGenerator++)
205       .setComponentUuid(componentUuid)
206       .setProjectUuid(projectUuid)
207       .setRuleUuid(ruleDto.getUuid())
208       .setStatus("OPEN");
209   }
210
211   private RuleDto insertRule(RuleKey ruleKey, boolean isExternal, boolean isAdHoc) {
212     dbTester.rules().insert(
213       new RuleDefinitionDto()
214         .setRuleKey(ruleKey)
215         .setIsExternal(isExternal)
216         .setIsAdHoc(isAdHoc)
217         .setStatus(RuleStatus.READY)
218         .setScope(RuleDto.Scope.ALL));
219     dbTester.commit();
220     return dbTester.getDbClient().ruleDao().selectByKey(dbTester.getSession(), ruleKey)
221       .orElseThrow(() -> new RuntimeException("insertAdHocRule failed"));
222   }
223
224   private void insertRuleMetadata(String ruleUuid, String adHocName) {
225     dbTester.rules().insertOrUpdateMetadata(new RuleMetadataDto()
226       .setRuleUuid(ruleUuid)
227       .setAdHocName(adHocName));
228     dbTester.commit();
229   }
230 }