3 * Copyright (C) 2009-2022 SonarSource SA
4 * mailto:info AT sonarsource DOT com
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.
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.
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.
20 package org.sonar.ce.task.projectanalysis.issue;
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;
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;
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";
64 public DbTester db = DbTester.create(System2.INSTANCE);
66 private DbClient dbClient = mock(DbClient.class);
67 private DbSession dbSession = mock(DbSession.class);
68 private RuleDao ruleDao = mock(RuleDao.class);
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);
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));
86 private static DeprecatedRuleKeyDto deprecatedRuleKeyOf(RuleDto ruleDto, RuleKey deprecatedRuleKey) {
87 return deprecatedRuleKeyOf(ruleDto.getUuid(), deprecatedRuleKey);
90 private static DeprecatedRuleKeyDto deprecatedRuleKeyOf(String ruleUuid, RuleKey deprecatedRuleKey) {
91 return new DeprecatedRuleKeyDto().setRuleUuid(ruleUuid)
92 .setOldRepositoryKey(deprecatedRuleKey.repository())
93 .setOldRuleKey(deprecatedRuleKey.rule());
97 public void constructor_does_not_query_DB_to_retrieve_rules() {
98 verifyNoMoreInteractions(dbClient);
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());
105 verify(ruleDao, times(1)).selectAll(any(DbSession.class));
107 verifyNoMethodCallTriggersCallToDB();
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());
114 verify(ruleDao, times(1)).selectAll(any(DbSession.class));
116 verifyNoMethodCallTriggersCallToDB();
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());
123 verify(ruleDao, times(1)).selectAll(any(DbSession.class));
125 verifyNoMethodCallTriggersCallToDB();
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());
132 verify(ruleDao, times(1)).selectAll(any(DbSession.class));
134 verifyNoMethodCallTriggersCallToDB();
138 public void getByKey_throws_NPE_if_key_argument_is_null() {
139 expectNullRuleKeyNPE(() -> underTest.getByKey(null));
143 public void getByKey_does_not_call_DB_if_key_argument_is_null() {
145 underTest.getByKey(null);
146 } catch (NullPointerException e) {
152 public void getByKey_returns_Rule_if_it_exists_in_DB() {
153 Rule rule = underTest.getByKey(AB_RULE.getKey());
155 assertIsABRule(rule);
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);
162 assertIsABRule(rule);
166 public void getByKey_throws_IAE_if_rules_does_not_exist_in_DB() {
167 expectIAERuleNotFound(() -> underTest.getByKey(AC_RULE_KEY), AC_RULE_KEY);
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);
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");
182 public void findByKey_throws_NPE_if_key_argument_is_null() {
183 expectNullRuleKeyNPE(() -> underTest.findByKey(null));
187 public void findByKey_does_not_call_DB_if_key_argument_is_null() {
189 underTest.findByKey(null);
190 } catch (NullPointerException e) {
196 public void findByKey_returns_absent_if_rule_does_not_exist_in_DB() {
197 Optional<Rule> rule = underTest.findByKey(AC_RULE_KEY);
199 assertThat(rule).isEmpty();
203 public void findByKey_returns_Rule_if_it_exists_in_DB() {
204 Optional<Rule> rule = underTest.findByKey(AB_RULE.getKey());
206 assertIsABRule(rule.get());
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);
213 assertIsABRule(rule.get());
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);
220 assertThat(rule).isEmpty();
224 public void getByUuid_returns_Rule_if_it_exists_in_DB() {
225 Rule rule = underTest.getByUuid(AB_RULE.getUuid());
227 assertIsABRule(rule);
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");
238 public void findByUuid_returns_absent_if_rule_does_not_exist_in_DB() {
239 Optional<Rule> rule = underTest.findByUuid(AC_RULE_UUID);
241 assertThat(rule).isEmpty();
245 public void findByUuid_returns_Rule_if_it_exists_in_DB() {
246 Optional<Rule> rule = underTest.findByUuid(AB_RULE.getUuid());
248 assertIsABRule(rule.get());
252 public void accept_new_externally_defined_Rules() {
253 RuleKey ruleKey = RuleKey.of("external_eslint", "no-cond-assign");
255 underTest.addOrUpdateAddHocRuleIfNeeded(ruleKey, () -> new NewAdHocRule(ScannerReport.ExternalIssue.newBuilder().setEngineId("eslint").setRuleId("no-cond-assign").build()));
257 assertThat(underTest.getByKey(ruleKey)).isNotNull();
258 assertThat(underTest.getByKey(ruleKey).getType()).isNull();
260 RuleDao ruleDao = dbClient.ruleDao();
261 Optional<RuleDefinitionDto> ruleDefinitionDto = ruleDao.selectDefinitionByKey(dbClient.openSession(false), ruleKey);
262 assertThat(ruleDefinitionDto).isNotPresent();
266 public void persist_new_externally_defined_Rules() {
267 underTest = new RuleRepositoryImpl(adHocRuleCreator, db.getDbClient());
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()));
272 underTest.saveOrUpdateAddHocRules(db.getSession());
275 Optional<RuleDefinitionDto> ruleDefinitionDto = db.getDbClient().ruleDao().selectDefinitionByKey(db.getSession(), ruleKey);
276 assertThat(ruleDefinitionDto).isPresent();
278 Rule rule = underTest.getByKey(ruleKey);
279 assertThat(rule).isNotNull();
281 assertThat(underTest.getByUuid(ruleDefinitionDto.get().getUuid())).isNotNull();
282 verify(ruleIndexer).commitAndIndex(db.getSession(), ruleDefinitionDto.get().getUuid());
285 private void expectNullRuleKeyNPE(ThrowingCallable callback) {
286 assertThatThrownBy(callback)
287 .isInstanceOf(NullPointerException.class)
288 .hasMessage("RuleKey can not be null");
291 private void verifyNoMethodCallTriggersCallToDB() {
293 underTest.getByKey(AB_RULE.getKey());
296 underTest.findByKey(AB_RULE.getKey());
299 underTest.getByUuid(AB_RULE.getUuid());
302 underTest.findByUuid(AB_RULE.getUuid());
306 private void assertNoCallToDb() {
307 verifyNoMoreInteractions(ruleDao);
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);
318 private static RuleDto createABRuleDto() {
319 RuleKey ruleKey = RuleKey.of("a", "b");
321 .setRepositoryKey(ruleKey.repository())
322 .setRuleKey(ruleKey.rule())
323 .setStatus(RuleStatus.REMOVED)
324 .setType(RuleType.CODE_SMELL);