]> source.dussan.org Git - sonarqube.git/blob
2a8549b04fba10419f01db16915cb44161a92def
[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.projectanalysis.issue;
21
22 import com.google.common.collect.ImmutableList;
23 import com.google.common.collect.ImmutableSet;
24 import java.util.Optional;
25 import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.sonar.api.rule.RuleKey;
29 import org.sonar.api.rule.RuleStatus;
30 import org.sonar.api.rules.RuleType;
31 import org.sonar.api.utils.System2;
32 import org.sonar.core.util.SequenceUuidFactory;
33 import org.sonar.db.DbClient;
34 import org.sonar.db.DbSession;
35 import org.sonar.db.DbTester;
36 import org.sonar.db.rule.DeprecatedRuleKeyDto;
37 import org.sonar.db.rule.RuleDao;
38 import org.sonar.db.rule.RuleDefinitionDto;
39 import org.sonar.db.rule.RuleDto;
40 import org.sonar.scanner.protocol.output.ScannerReport;
41 import org.sonar.server.rule.index.RuleIndexer;
42
43 import static org.assertj.core.api.Assertions.assertThat;
44 import static org.assertj.core.api.Assertions.assertThatThrownBy;
45 import static org.mockito.ArgumentMatchers.any;
46 import static org.mockito.ArgumentMatchers.anyBoolean;
47 import static org.mockito.Mockito.mock;
48 import static org.mockito.Mockito.reset;
49 import static org.mockito.Mockito.verify;
50 import static org.mockito.Mockito.verifyNoMoreInteractions;
51 import static org.mockito.Mockito.when;
52 import static org.mockito.internal.verification.VerificationModeFactory.times;
53
54 public class RuleRepositoryImplTest {
55   private static final RuleDto AB_RULE = createABRuleDto().setUuid("rule-uuid");
56   private static final RuleKey AB_RULE_DEPRECATED_KEY_1 = RuleKey.of("old_a", "old_b");
57   private static final RuleKey AB_RULE_DEPRECATED_KEY_2 = RuleKey.of(AB_RULE.getRepositoryKey(), "old_b");
58   private static final RuleKey DEPRECATED_KEY_OF_NON_EXITING_RULE = RuleKey.of("some_rep", "some_key");
59   private static final RuleKey AC_RULE_KEY = RuleKey.of("a", "c");
60   private static final String AC_RULE_UUID = "uuid-684";
61
62
63   @org.junit.Rule
64   public DbTester db = DbTester.create(System2.INSTANCE);
65
66   private DbClient dbClient = mock(DbClient.class);
67   private DbSession dbSession = mock(DbSession.class);
68   private RuleDao ruleDao = mock(RuleDao.class);
69
70   private RuleIndexer ruleIndexer = mock(RuleIndexer.class);
71   private AdHocRuleCreator adHocRuleCreator = new AdHocRuleCreator(db.getDbClient(), System2.INSTANCE, ruleIndexer, new SequenceUuidFactory());
72   private RuleRepositoryImpl underTest = new RuleRepositoryImpl(adHocRuleCreator, dbClient);
73
74   @Before
75   public void setUp() {
76     when(dbClient.openSession(anyBoolean())).thenReturn(dbSession);
77     when(dbClient.ruleDao()).thenReturn(ruleDao);
78     when(ruleDao.selectAll(any(DbSession.class))).thenReturn(ImmutableList.of(AB_RULE));
79     DeprecatedRuleKeyDto abDeprecatedRuleKey1 = deprecatedRuleKeyOf(AB_RULE, AB_RULE_DEPRECATED_KEY_1);
80     DeprecatedRuleKeyDto abDeprecatedRuleKey2 = deprecatedRuleKeyOf(AB_RULE, AB_RULE_DEPRECATED_KEY_2);
81     DeprecatedRuleKeyDto deprecatedRuleOfNonExistingRule = deprecatedRuleKeyOf("unknown-rule-uuid", DEPRECATED_KEY_OF_NON_EXITING_RULE);
82     when(ruleDao.selectAllDeprecatedRuleKeys(any(DbSession.class))).thenReturn(ImmutableSet.of(
83       abDeprecatedRuleKey1, abDeprecatedRuleKey2, deprecatedRuleOfNonExistingRule));
84   }
85
86   private static DeprecatedRuleKeyDto deprecatedRuleKeyOf(RuleDto ruleDto, RuleKey deprecatedRuleKey) {
87     return deprecatedRuleKeyOf(ruleDto.getUuid(), deprecatedRuleKey);
88   }
89
90   private static DeprecatedRuleKeyDto deprecatedRuleKeyOf(String ruleUuid, RuleKey deprecatedRuleKey) {
91     return new DeprecatedRuleKeyDto().setRuleUuid(ruleUuid)
92       .setOldRepositoryKey(deprecatedRuleKey.repository())
93       .setOldRuleKey(deprecatedRuleKey.rule());
94   }
95
96   @Test
97   public void constructor_does_not_query_DB_to_retrieve_rules() {
98     verifyNoMoreInteractions(dbClient);
99   }
100
101   @Test
102   public void first_call_to_getByKey_triggers_call_to_db_and_any_subsequent_get_or_find_call_does_not() {
103     underTest.getByKey(AB_RULE.getKey());
104
105     verify(ruleDao, times(1)).selectAll(any(DbSession.class));
106
107     verifyNoMethodCallTriggersCallToDB();
108   }
109
110   @Test
111   public void first_call_to_findByKey_triggers_call_to_db_and_any_subsequent_get_or_find_call_does_not() {
112     underTest.findByKey(AB_RULE.getKey());
113
114     verify(ruleDao, times(1)).selectAll(any(DbSession.class));
115
116     verifyNoMethodCallTriggersCallToDB();
117   }
118
119   @Test
120   public void first_call_to_getById_triggers_call_to_db_and_any_subsequent_get_or_find_call_does_not() {
121     underTest.getByUuid(AB_RULE.getUuid());
122
123     verify(ruleDao, times(1)).selectAll(any(DbSession.class));
124
125     verifyNoMethodCallTriggersCallToDB();
126   }
127
128   @Test
129   public void first_call_to_findById_triggers_call_to_db_and_any_subsequent_get_or_find_call_does_not() {
130     underTest.findByUuid(AB_RULE.getUuid());
131
132     verify(ruleDao, times(1)).selectAll(any(DbSession.class));
133
134     verifyNoMethodCallTriggersCallToDB();
135   }
136
137   @Test
138   public void getByKey_throws_NPE_if_key_argument_is_null() {
139     expectNullRuleKeyNPE(() -> underTest.getByKey(null));
140   }
141
142   @Test
143   public void getByKey_does_not_call_DB_if_key_argument_is_null() {
144     try {
145       underTest.getByKey(null);
146     } catch (NullPointerException e) {
147       assertNoCallToDb();
148     }
149   }
150
151   @Test
152   public void getByKey_returns_Rule_if_it_exists_in_DB() {
153     Rule rule = underTest.getByKey(AB_RULE.getKey());
154
155     assertIsABRule(rule);
156   }
157
158   @Test
159   public void getByKey_returns_Rule_if_argument_is_deprecated_key_in_DB_of_rule_in_DB() {
160     Rule rule = underTest.getByKey(AB_RULE_DEPRECATED_KEY_1);
161
162     assertIsABRule(rule);
163   }
164
165   @Test
166   public void getByKey_throws_IAE_if_rules_does_not_exist_in_DB() {
167     expectIAERuleNotFound(() -> underTest.getByKey(AC_RULE_KEY), AC_RULE_KEY);
168   }
169
170   @Test
171   public void getByKey_throws_IAE_if_argument_is_deprecated_key_in_DB_of_non_existing_rule() {
172     expectIAERuleNotFound(() -> underTest.getByKey(DEPRECATED_KEY_OF_NON_EXITING_RULE), DEPRECATED_KEY_OF_NON_EXITING_RULE);
173   }
174
175   private void expectIAERuleNotFound(ThrowingCallable callback, RuleKey ruleKey) {
176     assertThatThrownBy(callback)
177       .isInstanceOf(IllegalArgumentException.class)
178       .hasMessage("Can not find rule for key " + ruleKey.toString() + ". This rule does not exist in DB");
179   }
180
181   @Test
182   public void findByKey_throws_NPE_if_key_argument_is_null() {
183     expectNullRuleKeyNPE(() -> underTest.findByKey(null));
184   }
185
186   @Test
187   public void findByKey_does_not_call_DB_if_key_argument_is_null() {
188     try {
189       underTest.findByKey(null);
190     } catch (NullPointerException e) {
191       assertNoCallToDb();
192     }
193   }
194
195   @Test
196   public void findByKey_returns_absent_if_rule_does_not_exist_in_DB() {
197     Optional<Rule> rule = underTest.findByKey(AC_RULE_KEY);
198
199     assertThat(rule).isEmpty();
200   }
201
202   @Test
203   public void findByKey_returns_Rule_if_it_exists_in_DB() {
204     Optional<Rule> rule = underTest.findByKey(AB_RULE.getKey());
205
206     assertIsABRule(rule.get());
207   }
208
209   @Test
210   public void findByKey_returns_Rule_if_argument_is_deprecated_key_in_DB_of_rule_in_DB() {
211     Optional<Rule> rule = underTest.findByKey(AB_RULE_DEPRECATED_KEY_1);
212
213     assertIsABRule(rule.get());
214   }
215
216   @Test
217   public void findByKey_returns_empty_if_argument_is_deprecated_key_in_DB_of_rule_in_DB() {
218     Optional<Rule> rule = underTest.findByKey(DEPRECATED_KEY_OF_NON_EXITING_RULE);
219
220     assertThat(rule).isEmpty();
221   }
222
223   @Test
224   public void getByUuid_returns_Rule_if_it_exists_in_DB() {
225     Rule rule = underTest.getByUuid(AB_RULE.getUuid());
226
227     assertIsABRule(rule);
228   }
229
230   @Test
231   public void getByUuid_throws_IAE_if_rules_does_not_exist_in_DB() {
232     assertThatThrownBy(() -> underTest.getByUuid(AC_RULE_UUID))
233       .isInstanceOf(IllegalArgumentException.class)
234       .hasMessage("Can not find rule for uuid " + AC_RULE_UUID + ". This rule does not exist in DB");
235   }
236
237   @Test
238   public void findByUuid_returns_absent_if_rule_does_not_exist_in_DB() {
239     Optional<Rule> rule = underTest.findByUuid(AC_RULE_UUID);
240
241     assertThat(rule).isEmpty();
242   }
243
244   @Test
245   public void findByUuid_returns_Rule_if_it_exists_in_DB() {
246     Optional<Rule> rule = underTest.findByUuid(AB_RULE.getUuid());
247
248     assertIsABRule(rule.get());
249   }
250
251   @Test
252   public void accept_new_externally_defined_Rules() {
253     RuleKey ruleKey = RuleKey.of("external_eslint", "no-cond-assign");
254
255     underTest.addOrUpdateAddHocRuleIfNeeded(ruleKey, () -> new NewAdHocRule(ScannerReport.ExternalIssue.newBuilder().setEngineId("eslint").setRuleId("no-cond-assign").build()));
256
257     assertThat(underTest.getByKey(ruleKey)).isNotNull();
258     assertThat(underTest.getByKey(ruleKey).getType()).isNull();
259
260     RuleDao ruleDao = dbClient.ruleDao();
261     Optional<RuleDefinitionDto> ruleDefinitionDto = ruleDao.selectDefinitionByKey(dbClient.openSession(false), ruleKey);
262     assertThat(ruleDefinitionDto).isNotPresent();
263   }
264
265   @Test
266   public void persist_new_externally_defined_Rules() {
267     underTest = new RuleRepositoryImpl(adHocRuleCreator, db.getDbClient());
268
269     RuleKey ruleKey = RuleKey.of("external_eslint", "no-cond-assign");
270     underTest.addOrUpdateAddHocRuleIfNeeded(ruleKey, () -> new NewAdHocRule(ScannerReport.ExternalIssue.newBuilder().setEngineId("eslint").setRuleId("no-cond-assign").build()));
271
272     underTest.saveOrUpdateAddHocRules(db.getSession());
273     db.commit();
274
275     Optional<RuleDefinitionDto> ruleDefinitionDto = db.getDbClient().ruleDao().selectDefinitionByKey(db.getSession(), ruleKey);
276     assertThat(ruleDefinitionDto).isPresent();
277
278     Rule rule = underTest.getByKey(ruleKey);
279     assertThat(rule).isNotNull();
280
281     assertThat(underTest.getByUuid(ruleDefinitionDto.get().getUuid())).isNotNull();
282     verify(ruleIndexer).commitAndIndex(db.getSession(), ruleDefinitionDto.get().getUuid());
283   }
284
285   private void expectNullRuleKeyNPE(ThrowingCallable callback) {
286     assertThatThrownBy(callback)
287       .isInstanceOf(NullPointerException.class)
288       .hasMessage("RuleKey can not be null");
289   }
290
291   private void verifyNoMethodCallTriggersCallToDB() {
292     reset(ruleDao);
293     underTest.getByKey(AB_RULE.getKey());
294     assertNoCallToDb();
295     reset(ruleDao);
296     underTest.findByKey(AB_RULE.getKey());
297     assertNoCallToDb();
298     reset(ruleDao);
299     underTest.getByUuid(AB_RULE.getUuid());
300     assertNoCallToDb();
301     reset(ruleDao);
302     underTest.findByUuid(AB_RULE.getUuid());
303     assertNoCallToDb();
304   }
305
306   private void assertNoCallToDb() {
307     verifyNoMoreInteractions(ruleDao);
308   }
309
310   private void assertIsABRule(Rule rule) {
311     assertThat(rule).isNotNull();
312     assertThat(rule.getUuid()).isEqualTo(AB_RULE.getUuid());
313     assertThat(rule.getKey()).isEqualTo(AB_RULE.getKey());
314     assertThat(rule.getRemediationFunction()).isNull();
315     assertThat(rule.getStatus()).isEqualTo(RuleStatus.REMOVED);
316   }
317
318   private static RuleDto createABRuleDto() {
319     RuleKey ruleKey = RuleKey.of("a", "b");
320     return new RuleDto()
321       .setRepositoryKey(ruleKey.repository())
322       .setRuleKey(ruleKey.rule())
323       .setStatus(RuleStatus.REMOVED)
324       .setType(RuleType.CODE_SMELL);
325   }
326
327 }