]> source.dussan.org Git - sonarqube.git/blob
3bc395f22c0bdd55f77a8e4c936895837da293bd
[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.server.pushapi.qualityprofile;
21
22 import java.nio.charset.StandardCharsets;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.Deque;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.function.Consumer;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.sonar.api.rule.RuleKey;
32 import org.sonar.db.DbTester;
33 import org.sonar.db.component.ComponentDto;
34 import org.sonar.db.measure.LiveMeasureDto;
35 import org.sonar.db.metric.MetricDto;
36 import org.sonar.db.project.ProjectDto;
37 import org.sonar.db.pushevent.PushEventDto;
38 import org.sonar.db.qualityprofile.ActiveRuleDto;
39 import org.sonar.db.qualityprofile.ActiveRuleParamDto;
40 import org.sonar.db.qualityprofile.QProfileDto;
41 import org.sonar.db.qualityprofile.QualityProfileTesting;
42 import org.sonar.db.rule.RuleDto;
43 import org.sonar.db.rule.RuleParamDto;
44 import org.sonar.server.qualityprofile.ActiveRuleChange;
45 import org.sonarqube.ws.Common;
46
47 import static java.util.List.of;
48 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
49 import static org.apache.commons.lang.math.RandomUtils.nextInt;
50 import static org.assertj.core.api.Assertions.assertThat;
51 import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY;
52 import static org.sonar.api.measures.Metric.ValueType.STRING;
53 import static org.sonar.db.rule.RuleTesting.newCustomRule;
54 import static org.sonar.db.rule.RuleTesting.newTemplateRule;
55 import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
56
57 public class QualityProfileChangeEventServiceImplTest {
58
59   @Rule
60   public DbTester db = DbTester.create();
61
62   public final QualityProfileChangeEventServiceImpl underTest = new QualityProfileChangeEventServiceImpl(db.getDbClient());
63
64   @Test
65   public void distributeRuleChangeEvent() {
66     QProfileDto qualityProfileDto = QualityProfileTesting.newQualityProfileDto();
67
68     RuleDto templateRule = newTemplateRule(RuleKey.of("xoo", "template-key"));
69     db.rules().insert(templateRule);
70
71     RuleDto rule1 = newCustomRule(templateRule, "<div>line1\nline2</div>")
72       .setLanguage("xoo")
73       .setRepositoryKey("repo")
74       .setRuleKey("ruleKey")
75       .setDescriptionFormat(RuleDto.Format.MARKDOWN);
76     db.rules().insert(rule1);
77
78     ActiveRuleChange activeRuleChange = changeActiveRule(qualityProfileDto, rule1, "paramChangeKey", "paramChangeValue");
79
80     Collection<QProfileDto> profiles = Collections.singleton(qualityProfileDto);
81
82     ProjectDto project = db.components().insertPrivateProjectDto();
83     db.qualityProfiles().associateWithProject(project, qualityProfileDto);
84
85     underTest.distributeRuleChangeEvent(profiles, of(activeRuleChange), "xoo");
86
87     Deque<PushEventDto> events = getProjectEvents(project.getUuid());
88
89     assertThat(events).isNotEmpty().hasSize(1);
90     assertThat(events.getFirst())
91       .extracting(PushEventDto::getName, PushEventDto::getLanguage)
92       .contains("RuleSetChanged", "xoo");
93
94     String ruleSetChangedEvent = new String(events.getFirst().getPayload(), StandardCharsets.UTF_8);
95
96     assertThat(ruleSetChangedEvent)
97       .contains("\"activatedRules\":[{\"key\":\"repo:ruleKey\"," +
98         "\"language\":\"xoo\"," +
99         "\"templateKey\":\"xoo:template-key\"," +
100         "\"params\":[{\"key\":\"paramChangeKey\",\"value\":\"paramChangeValue\"}]}]," +
101         "\"deactivatedRules\":[]");
102   }
103
104   @Test
105   public void distributeRuleChangeEvent_when_project_has_only_default_quality_profiles() {
106     String language = "xoo";
107     ComponentDto project = db.components().insertPrivateProject();
108     RuleDto templateRule = insertTemplateRule();
109     QProfileDto defaultQualityProfile = insertDefaultQualityProfile(language);
110     RuleDto rule = insertCustomRule(templateRule, language, "<div>line1\nline2</div>");
111     ActiveRuleChange activeRuleChange = changeActiveRule(defaultQualityProfile, rule, "paramChangeKey", "paramChangeValue");
112     insertQualityProfileLiveMeasure(project, language, NCLOC_LANGUAGE_DISTRIBUTION_KEY);
113
114     db.getSession().commit();
115
116     underTest.distributeRuleChangeEvent(List.of(defaultQualityProfile), of(activeRuleChange), language);
117
118     Deque<PushEventDto> events = getProjectEvents(project.projectUuid());
119
120     assertThat(events)
121       .hasSize(1);
122
123     assertThat(events.getFirst())
124       .extracting(PushEventDto::getName, PushEventDto::getLanguage)
125       .contains("RuleSetChanged", "xoo");
126
127     String ruleSetChangedEvent = new String(events.getFirst().getPayload(), StandardCharsets.UTF_8);
128
129     assertThat(ruleSetChangedEvent)
130       .contains("\"activatedRules\":[{\"key\":\"repo:ruleKey\"," +
131         "\"language\":\"xoo\"," +
132         "\"templateKey\":\"xoo:template-key\"," +
133         "\"params\":[{\"key\":\"paramChangeKey\",\"value\":\"paramChangeValue\"}]}]," +
134         "\"deactivatedRules\":[]");
135   }
136
137   private Deque<PushEventDto> getProjectEvents(String projectUuid) {
138     return db.getDbClient()
139       .pushEventDao()
140       .selectChunkByProjectUuids(db.getSession(), Set.of(projectUuid), 1L, null, 1);
141   }
142
143   private ActiveRuleChange changeActiveRule(QProfileDto defaultQualityProfile, RuleDto rule, String changeKey, String changeValue) {
144     ActiveRuleDto activeRuleDto = ActiveRuleDto.createFor(defaultQualityProfile, rule);
145     ActiveRuleChange activeRuleChange = new ActiveRuleChange(ACTIVATED, activeRuleDto, rule);
146     return activeRuleChange.setParameter(changeKey, changeValue);
147   }
148
149   private RuleDto insertCustomRule(RuleDto templateRule, String language, String description) {
150     RuleDto rule = newCustomRule(templateRule, description)
151       .setLanguage(language)
152       .setRepositoryKey("repo")
153       .setRuleKey("ruleKey")
154       .setDescriptionFormat(RuleDto.Format.MARKDOWN);
155
156     db.rules().insert(rule);
157     return rule;
158   }
159
160   private QProfileDto insertDefaultQualityProfile(String language) {
161     Consumer<QProfileDto> configureQualityProfile = profile -> profile
162       .setIsBuiltIn(true)
163       .setLanguage(language);
164
165     QProfileDto defaultQualityProfile = db.qualityProfiles().insert(configureQualityProfile);
166     db.qualityProfiles().setAsDefault(defaultQualityProfile);
167
168     return defaultQualityProfile;
169   }
170
171   private RuleDto insertTemplateRule() {
172     RuleKey key = RuleKey.of("xoo", "template-key");
173     RuleDto templateRule = newTemplateRule(key);
174     db.rules().insert(templateRule);
175     return templateRule;
176   }
177
178   @Test
179   public void publishRuleActivationToSonarLintClients() {
180     ProjectDto projectDao = new ProjectDto().setUuid("project-uuid");
181     QProfileDto activatedQualityProfile = QualityProfileTesting.newQualityProfileDto();
182     activatedQualityProfile.setLanguage("xoo");
183     db.qualityProfiles().insert(activatedQualityProfile);
184     RuleDto rule1 = db.rules().insert(r -> r.setLanguage("xoo").setRepositoryKey("repo").setRuleKey("ruleKey"));
185     RuleParamDto rule1Param = db.rules().insertRuleParam(rule1);
186
187     ActiveRuleDto activeRule1 = db.qualityProfiles().activateRule(activatedQualityProfile, rule1);
188     ActiveRuleParamDto activeRuleParam1 = ActiveRuleParamDto.createFor(rule1Param).setValue(randomAlphanumeric(20));
189     db.getDbClient().activeRuleDao().insertParam(db.getSession(), activeRule1, activeRuleParam1);
190     db.getSession().commit();
191
192     QProfileDto deactivatedQualityProfile = QualityProfileTesting.newQualityProfileDto();
193     db.qualityProfiles().insert(deactivatedQualityProfile);
194     RuleDto rule2 = db.rules().insert(r -> r.setLanguage("xoo").setRepositoryKey("repo2").setRuleKey("ruleKey2"));
195     RuleParamDto rule2Param = db.rules().insertRuleParam(rule2);
196
197     ActiveRuleDto activeRule2 = db.qualityProfiles().activateRule(deactivatedQualityProfile, rule2);
198     ActiveRuleParamDto activeRuleParam2 = ActiveRuleParamDto.createFor(rule2Param).setValue(randomAlphanumeric(20));
199     db.getDbClient().activeRuleDao().insertParam(db.getSession(), activeRule2, activeRuleParam2);
200     db.getSession().commit();
201
202     underTest.publishRuleActivationToSonarLintClients(projectDao, activatedQualityProfile, deactivatedQualityProfile);
203
204     Deque<PushEventDto> events = getProjectEvents(projectDao.getUuid());
205
206     assertThat(events).isNotEmpty().hasSize(1);
207     assertThat(events.getFirst())
208       .extracting(PushEventDto::getName, PushEventDto::getLanguage)
209       .contains("RuleSetChanged", "xoo");
210
211     String ruleSetChangedEvent = new String(events.getFirst().getPayload(), StandardCharsets.UTF_8);
212
213     assertThat(ruleSetChangedEvent)
214       .contains("\"activatedRules\":[{\"key\":\"repo:ruleKey\"," +
215         "\"language\":\"xoo\",\"severity\":\"" + Common.Severity.forNumber(rule1.getSeverity()).name() + "\"," +
216         "\"params\":[{\"key\":\"" + activeRuleParam1.getKey() + "\",\"value\":\"" + activeRuleParam1.getValue() + "\"}]}]," +
217         "\"deactivatedRules\":[\"repo2:ruleKey2\"]");
218   }
219
220   private void insertQualityProfileLiveMeasure(ComponentDto project, String language, String metricKey) {
221     MetricDto metric = insertMetric(metricKey);
222
223     Consumer<LiveMeasureDto> configureLiveMeasure = liveMeasure -> liveMeasure
224       .setMetricUuid(metric.getUuid())
225       .setComponentUuid(project.uuid())
226       .setProjectUuid(project.uuid())
227       .setData(language + "=" + nextInt(10));
228
229     db.measures().insertLiveMeasure(project, metric, configureLiveMeasure);
230   }
231
232   private MetricDto insertMetric(String metricKey) {
233     Consumer<MetricDto> configureMetric = metric -> metric
234       .setUuid("uuid")
235       .setValueType(STRING.name())
236       .setKey(metricKey);
237
238     return db.measures().insertMetric(configureMetric);
239   }
240 }