]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10544 Fix handling of external rules in CE
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Tue, 10 Apr 2018 14:08:50 +0000 (16:08 +0200)
committerSonarTech <sonartech@sonarsource.com>
Thu, 26 Apr 2018 18:20:50 +0000 (20:20 +0200)
14 files changed:
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/ComponentIssuesLoader.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculator.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistExternalRulesStep.java
server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/rule/RuleCreator.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculatorTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RuleRepositoryImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistExternalRulesStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistIssuesStepTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java [new file with mode: 0644]

index 86afcb2bed12073fa491fa4beb6c4427c7549fe9..38075e93fc5bb35bfb67d32a67c373e7485e6e9d 100644 (file)
@@ -33,9 +33,9 @@ public class RuleDto {
   public enum Format {
     HTML, MARKDOWN
   }
-  
+
   public enum Scope {
-    MAIN, TEST, ALL;
+    MAIN, TEST, ALL
   }
 
   private final RuleDefinitionDto definition;
@@ -142,16 +142,16 @@ public class RuleDto {
   public String getConfigKey() {
     return definition.getConfigKey();
   }
-  
+
   public RuleDto setConfigKey(@Nullable String configKey) {
     definition.setConfigKey(configKey);
     return this;
   }
-  
+
   public Scope getScope() {
     return definition.getScope();
   }
-  
+
   public RuleDto setScope(Scope scope) {
     definition.setScope(scope);
     return this;
@@ -177,6 +177,10 @@ public class RuleDto {
     return this;
   }
 
+  public boolean isExternal() {
+    return definition.isExternal();
+  }
+
   public boolean isTemplate() {
     return definition.isTemplate();
   }
index f40d4dece13806e9afecc54d7c4bd2b49268a180..b7692f5cb56a48755e6f9c1309e6504ec1d501ee 100644 (file)
@@ -122,6 +122,7 @@ import org.sonar.server.computation.task.projectanalysis.webhook.WebhookPostTask
 import org.sonar.server.computation.task.step.ComputationStepExecutor;
 import org.sonar.server.computation.task.step.ComputationSteps;
 import org.sonar.server.computation.taskprocessor.MutableTaskResultHolderImpl;
+import org.sonar.server.rule.ExternalRuleCreator;
 import org.sonar.server.view.index.ViewIndex;
 
 public final class ProjectAnalysisTaskContainerPopulator implements ContainerPopulator<TaskContainer> {
@@ -196,6 +197,7 @@ public final class ProjectAnalysisTaskContainerPopulator implements ContainerPop
       DuplicationRepositoryImpl.class,
 
       // issues
+      ExternalRuleCreator.class,
       RuleRepositoryImpl.class,
       ScmAccountToUserLoader.class,
       ScmAccountToUser.class,
index fad321457847b1686edfea1e4a27a769b0726e49..3dd91d851a04d20e001548ce53c1a3437d3af8b1 100644 (file)
@@ -72,9 +72,10 @@ public class ComponentIssuesLoader {
     List<DefaultIssue> result = new ArrayList<>();
     dbSession.getMapper(IssueMapper.class).scrollNonClosedByComponentUuid(componentUuid, resultContext -> {
       DefaultIssue issue = (resultContext.getResultObject()).toDefaultIssue();
+      Rule rule = ruleRepository.getByKey(issue.ruleKey());
 
       // TODO this field should be set outside this class
-      if (!isActive(issue.ruleKey()) || ruleRepository.getByKey(issue.ruleKey()).getStatus() == RuleStatus.REMOVED) {
+      if ((!rule.isExternal() && !isActive(issue.ruleKey())) || rule.getStatus() == RuleStatus.REMOVED) {
         issue.setOnDisabledRule(true);
         // TODO to be improved, why setOnDisabledRule(true) is not enough ?
         issue.setBeingClosed(true);
index 473fe7054f9e2bb6655d7cde059768a3473c533e..70a8a66633a41ee8246b3b14418061fa7c6a8e25 100644 (file)
@@ -28,6 +28,8 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.function.Supplier;
 import java.util.stream.IntStream;
+import javax.annotation.Nullable;
+import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
@@ -63,12 +65,14 @@ public class IssueCreationDateCalculator extends IssueVisitor {
   private final AnalysisMetadataHolder analysisMetadataHolder;
   private final IssueChangeContext changeContext;
   private final ActiveRulesHolder activeRulesHolder;
+  private final RuleRepository ruleRepository;
 
   public IssueCreationDateCalculator(AnalysisMetadataHolder analysisMetadataHolder, ScmInfoRepository scmInfoRepository,
-    IssueFieldsSetter issueUpdater, ActiveRulesHolder activeRulesHolder) {
+    IssueFieldsSetter issueUpdater, ActiveRulesHolder activeRulesHolder, RuleRepository ruleRepository) {
     this.scmInfoRepository = scmInfoRepository;
     this.issueUpdater = issueUpdater;
     this.analysisMetadataHolder = analysisMetadataHolder;
+    this.ruleRepository = ruleRepository;
     this.changeContext = createScan(new Date(analysisMetadataHolder.getAnalysisDate()));
     this.activeRulesHolder = activeRulesHolder;
   }
@@ -80,24 +84,28 @@ public class IssueCreationDateCalculator extends IssueVisitor {
     }
     Optional<Long> lastAnalysisOptional = lastAnalysis();
     boolean firstAnalysis = !lastAnalysisOptional.isPresent();
-    ActiveRule activeRule = toJavaUtilOptional(activeRulesHolder.get(issue.getRuleKey()))
-      .orElseThrow(illegalStateException("The rule %s raised an issue, but is not one of the active rules.", issue.getRuleKey()));
-    if (firstAnalysis
-      || activeRuleIsNew(activeRule, lastAnalysisOptional.get())
-      || ruleImplementationChanged(activeRule, lastAnalysisOptional.get())) {
-      getScmChangeDate(component, issue)
-        .ifPresent(changeDate -> updateDate(issue, changeDate));
+    Rule rule = ruleRepository.findByKey(issue.getRuleKey())
+      .orElseThrow(illegalStateException("The rule with key '%s' raised an issue, but no rule with that key was found", issue.getRuleKey()));
+
+    if (rule.isExternal()) {
+      getScmChangeDate(component, issue).ifPresent(changeDate -> updateDate(issue, changeDate));
+    } else {
+      ActiveRule activeRule = toJavaUtilOptional(activeRulesHolder.get(issue.getRuleKey()))
+        .orElseThrow(illegalStateException("The rule %s raised an issue, but is not one of the active rules.", issue.getRuleKey()));
+      if (firstAnalysis || activeRuleIsNew(activeRule, lastAnalysisOptional.get())
+        || ruleImplementationChanged(activeRule.getRuleKey(), activeRule.getPluginKey(), lastAnalysisOptional.get())) {
+        getScmChangeDate(component, issue).ifPresent(changeDate -> updateDate(issue, changeDate));
+      }
     }
   }
 
-  private boolean ruleImplementationChanged(ActiveRule activeRule, long lastAnalysisDate) {
-    String pluginKey = activeRule.getPluginKey();
+  private boolean ruleImplementationChanged(RuleKey ruleKey, @Nullable String pluginKey, long lastAnalysisDate) {
     if (pluginKey == null) {
       return false;
     }
 
     ScannerPlugin scannerPlugin = Optional.ofNullable(analysisMetadataHolder.getScannerPluginsByKey().get(pluginKey))
-      .orElseThrow(illegalStateException("The rule %s is declared to come from plugin %s, but this plugin was not used by scanner.", activeRule.getRuleKey(), pluginKey));
+      .orElseThrow(illegalStateException("The rule %s is declared to come from plugin %s, but this plugin was not used by scanner.", ruleKey, pluginKey));
     return pluginIsNew(scannerPlugin, lastAnalysisDate)
       || basePluginIsNew(scannerPlugin, lastAnalysisDate);
   }
index 4762cef06292e4b8ccd823def805656b3fb790cd..0119b4d640ceeb7b74fd36b5a0ed6f66103f7d22 100644 (file)
@@ -55,8 +55,7 @@ public class RuleImpl implements Rule {
     this.remediationFunction = effectiveRemediationFunction(dto);
     this.type = RuleType.valueOf(dto.getType());
     this.pluginKey = dto.getPluginKey();
-    // TODO
-    this.external = false;
+    this.external = dto.isExternal();
   }
 
   @Override
index 32fbac077f614e816ec0062c255ba7996176cf2e..10eb88f7e09f093fc8d288c5401cf1c18ff18320 100644 (file)
 package org.sonar.server.computation.task.projectanalysis.issue;
 
 import com.google.common.collect.Multimap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Supplier;
+import javax.annotation.CheckForNull;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
@@ -27,13 +32,7 @@ import org.sonar.db.DbSession;
 import org.sonar.db.rule.DeprecatedRuleKeyDto;
 import org.sonar.db.rule.RuleDto;
 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
-import org.sonar.server.rule.RuleCreator;
-
-import javax.annotation.CheckForNull;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Supplier;
+import org.sonar.server.rule.ExternalRuleCreator;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Objects.requireNonNull;
@@ -45,11 +44,11 @@ public class RuleRepositoryImpl implements RuleRepository {
   @CheckForNull
   private Map<Integer, Rule> rulesById;
 
-  private final RuleCreator creator;
+  private final ExternalRuleCreator creator;
   private final DbClient dbClient;
   private final AnalysisMetadataHolder analysisMetadataHolder;
 
-  public RuleRepositoryImpl(RuleCreator creator, DbClient dbClient, AnalysisMetadataHolder analysisMetadataHolder) {
+  public RuleRepositoryImpl(ExternalRuleCreator creator, DbClient dbClient, AnalysisMetadataHolder analysisMetadataHolder) {
     this.creator = creator;
     this.dbClient = dbClient;
     this.analysisMetadataHolder = analysisMetadataHolder;
@@ -63,7 +62,8 @@ public class RuleRepositoryImpl implements RuleRepository {
     }
   }
 
-  @Override public void persistNewExternalRules(DbSession dbSession) {
+  @Override
+  public void persistNewExternalRules(DbSession dbSession) {
     ensureInitialized();
 
     rulesByKey.values().stream()
index aac5e714eebfd5dcf99c19c46b156b781ff19a0a..e51c1c895de81d96805b01736ec5a249003bc864 100644 (file)
@@ -37,7 +37,7 @@ public class PersistExternalRulesStep implements ComputationStep {
   @Override
   public void execute() {
 
-    try (DbSession dbSession = dbClient.openSession(true)) {
+    try (DbSession dbSession = dbClient.openSession(false)) {
       ruleRepository.persistNewExternalRules(dbSession);
       dbSession.flushStatements();
       dbSession.commit();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ExternalRuleCreator.java
new file mode 100644 (file)
index 0000000..2cbef97
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.rule;
+
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.rule.RuleDao;
+import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.server.computation.task.projectanalysis.issue.NewExternalRule;
+import org.sonar.server.computation.task.projectanalysis.issue.Rule;
+import org.sonar.server.computation.task.projectanalysis.issue.RuleImpl;
+
+import static org.sonar.db.rule.RuleDto.Scope.ALL;
+
+@ServerSide
+public class ExternalRuleCreator {
+
+  private final DbClient dbClient;
+  private final System2 system2;
+
+  public ExternalRuleCreator(DbClient dbClient, System2 system2) {
+    this.dbClient = dbClient;
+    this.system2 = system2;
+  }
+
+  public Rule create(DbSession dbSession, NewExternalRule external) {
+    RuleDao dao = dbClient.ruleDao();
+    dao.insert(dbSession, new RuleDefinitionDto()
+      .setRuleKey(external.getKey())
+      .setPluginKey(external.getPluginKey())
+      .setIsExternal(true)
+      .setName(external.getName())
+      .setDescriptionURL(external.getDescriptionUrl())
+      .setType(external.getType())
+      .setScope(ALL)
+      .setSeverity(external.getSeverity())
+      .setCreatedAt(system2.now())
+      .setUpdatedAt(system2.now()));
+    return new RuleImpl(dao.selectOrFailByKey(dbSession, external.getKey()));
+  }
+
+}
index 73ab988cadee202715e813c37041e3a770238d53..b6823f0e3ef6d00d7ef20ca9ef8af9c161e9da00 100644 (file)
@@ -36,14 +36,11 @@ import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.rule.RuleDao;
 import org.sonar.db.rule.RuleDefinitionDto;
 import org.sonar.db.rule.RuleDto;
 import org.sonar.db.rule.RuleDto.Format;
 import org.sonar.db.rule.RuleMetadataDto;
 import org.sonar.db.rule.RuleParamDto;
-import org.sonar.server.computation.task.projectanalysis.issue.NewExternalRule;
-import org.sonar.server.computation.task.projectanalysis.issue.RuleImpl;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.organization.DefaultOrganizationProvider;
 import org.sonar.server.rule.index.RuleIndexer;
@@ -52,7 +49,6 @@ import org.sonar.server.util.TypeValidations;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.collect.Lists.newArrayList;
 import static java.lang.String.format;
-import static org.sonar.db.rule.RuleDto.Scope.ALL;
 import static org.sonar.server.ws.WsUtils.checkRequest;
 
 @ServerSide
@@ -93,20 +89,6 @@ public class RuleCreator {
     return customRuleKey;
   }
 
-  public org.sonar.server.computation.task.projectanalysis.issue.Rule create(DbSession dbSession, NewExternalRule external) {
-    RuleDao dao = dbClient.ruleDao();
-    dao.insert(dbSession, new RuleDefinitionDto()
-      .setRuleKey(external.getKey())
-      .setPluginKey(external.getPluginKey())
-      .setIsExternal(true)
-      .setName(external.getName())
-      .setDescriptionURL(external.getDescriptionUrl())
-      .setType(external.getType())
-      .setScope(ALL)
-      .setSeverity(external.getSeverity()));
-    return new RuleImpl(dao.selectOrFailByKey(dbSession, external.getKey()));
-  }
-
   private void validateCustomRule(NewCustomRule newRule, DbSession dbSession, RuleKey templateKey) {
     List<String> errors = new ArrayList<>();
 
index b8ebe63fdb54a9d28fd351e19264595c251dad82..8024f1b121f6abf49563bef92407a7baa25cbe83 100644 (file)
@@ -59,33 +59,25 @@ public class IssueCreationDateCalculatorTest {
   @Rule
   public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
 
-  private ScmInfoRepository scmInfoRepository;
-  private IssueFieldsSetter issueUpdater;
-  private ActiveRulesHolder activeRulesHolder;
-  private Component component;
-  private RuleKey ruleKey;
-  private DefaultIssue issue;
-  private ActiveRule activeRule;
+  private ScmInfoRepository scmInfoRepository = mock(ScmInfoRepository.class);
+  private IssueFieldsSetter issueUpdater = mock(IssueFieldsSetter.class);
+  private ActiveRulesHolder activeRulesHolder = mock(ActiveRulesHolder.class);
+  private Component component = mock(Component.class);
+  private RuleKey ruleKey = RuleKey.of("reop", "rule");
+  private DefaultIssue issue = mock(DefaultIssue.class);
+  private ActiveRule activeRule = mock(ActiveRule.class);
   private IssueCreationDateCalculator calculator;
-  private Analysis baseAnalysis;
-  private Map<String, ScannerPlugin> scannerPlugins;
+  private Analysis baseAnalysis = mock(Analysis.class);
+  private Map<String, ScannerPlugin> scannerPlugins = new HashMap<>();
+  private RuleRepository ruleRepository = mock(RuleRepository.class);
   private ScmInfo scmInfo;
 
   @Before
   public void before() {
-    scannerPlugins = new HashMap<>();
     analysisMetadataHolder.setScannerPluginsByKey(scannerPlugins);
     analysisMetadataHolder.setAnalysisDate(new Date());
-    scmInfoRepository = mock(ScmInfoRepository.class);
-    issueUpdater = mock(IssueFieldsSetter.class);
-    activeRulesHolder = mock(ActiveRulesHolder.class);
-    component = mock(Component.class);
     when(component.getUuid()).thenReturn(COMPONENT_UUID);
-    ruleKey = RuleKey.of("reop", "rule");
-    issue = mock(DefaultIssue.class);
-    activeRule = mock(ActiveRule.class);
-    baseAnalysis = mock(Analysis.class);
-    calculator = new IssueCreationDateCalculator(analysisMetadataHolder, scmInfoRepository, issueUpdater, activeRulesHolder);
+    calculator = new IssueCreationDateCalculator(analysisMetadataHolder, scmInfoRepository, issueUpdater, activeRulesHolder, ruleRepository);
 
     when(activeRulesHolder.get(any(RuleKey.class)))
       .thenReturn(Optional.absent());
index 24400902b3d9f5f1214b18e37fbea1c4c56b0cc5..318f4e4ca7baec43505a19a1842d325cf9f68ef6 100644 (file)
@@ -21,16 +21,13 @@ package org.sonar.server.computation.task.projectanalysis.issue;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-
 import java.util.Optional;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.RuleType;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
@@ -42,14 +39,10 @@ import org.sonar.db.rule.RuleDefinitionDto;
 import org.sonar.db.rule.RuleDto;
 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
 import org.sonar.server.es.EsTester;
-import org.sonar.server.organization.TestDefaultOrganizationProvider;
-import org.sonar.server.rule.RuleCreator;
+import org.sonar.server.rule.ExternalRuleCreator;
 import org.sonar.server.rule.index.RuleIndexDefinition;
-import org.sonar.server.rule.index.RuleIndexer;
-import org.sonar.server.util.TypeValidationsTesting;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.eq;
@@ -61,8 +54,6 @@ import static org.mockito.Mockito.when;
 import static org.mockito.internal.verification.VerificationModeFactory.times;
 import static org.sonar.api.rule.Severity.BLOCKER;
 import static org.sonar.api.rules.RuleType.BUG;
-import static org.sonar.server.organization.TestDefaultOrganizationProvider.from;
-import static org.sonar.server.util.TypeValidationsTesting.newFullTypeValidations;
 
 public class RuleRepositoryImplTest {
 
@@ -87,14 +78,12 @@ public class RuleRepositoryImplTest {
   @org.junit.Rule
   public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
 
-  private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient());
-  private RuleCreator creator = new RuleCreator(System2.INSTANCE, ruleIndexer, db.getDbClient(), newFullTypeValidations(), from(db));
-
   private DbClient dbClient = mock(DbClient.class);
   private DbSession dbSession = mock(DbSession.class);
   private RuleDao ruleDao = mock(RuleDao.class);
 
-  private RuleRepositoryImpl underTest = new RuleRepositoryImpl(creator, dbClient, analysisMetadataHolder);
+  private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
+  private RuleRepositoryImpl underTest = new RuleRepositoryImpl(externalRuleCreator, dbClient, analysisMetadataHolder);
 
   @Before
   public void setUp() throws Exception {
@@ -284,7 +273,8 @@ public class RuleRepositoryImplTest {
   @Test
   public void accept_new_externally_defined_Rules() {
     DbClient dbClient = db.getDbClient();
-    underTest = new RuleRepositoryImpl(creator, dbClient, analysisMetadataHolder);
+    externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
+    underTest = new RuleRepositoryImpl(externalRuleCreator, dbClient, analysisMetadataHolder);
 
     RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
 
@@ -297,7 +287,6 @@ public class RuleRepositoryImplTest {
       .setType(BUG)
       .build());
 
-
     assertThat(underTest.getByKey(ruleKey)).isNotNull();
     assertThat(underTest.getByKey(ruleKey).getPluginKey()).isEqualTo("eslint");
     assertThat(underTest.getByKey(ruleKey).getName()).isEqualTo("disallow assignment operators in conditional statements (no-cond-assign)");
@@ -312,7 +301,8 @@ public class RuleRepositoryImplTest {
   public void persist_new_externally_defined_Rules() {
     DbClient dbClient = db.getDbClient();
     DbSession dbSession = dbClient.openSession(false);
-    underTest = new RuleRepositoryImpl(creator, dbClient, analysisMetadataHolder);
+    externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
+    underTest = new RuleRepositoryImpl(externalRuleCreator, dbClient, analysisMetadataHolder);
 
     RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
     underTest.insertNewExternalRuleIfAbsent(ruleKey, () -> new NewExternalRule.Builder()
@@ -324,7 +314,6 @@ public class RuleRepositoryImplTest {
       .setType(BUG)
       .build());
 
-
     underTest.persistNewExternalRules(dbSession);
 
     dbSession.commit();
index a9f0fdaf553407e826c18aa51e31d3ca61139a80..d3f2a9d33dbba96110f84d62bc13daf0f4f51c2d 100644 (file)
@@ -34,17 +34,14 @@ import org.sonar.server.computation.task.projectanalysis.issue.NewExternalRule;
 import org.sonar.server.computation.task.projectanalysis.issue.RuleRepositoryImpl;
 import org.sonar.server.computation.task.step.ComputationStep;
 import org.sonar.server.es.EsTester;
-import org.sonar.server.rule.RuleCreator;
+import org.sonar.server.rule.ExternalRuleCreator;
 import org.sonar.server.rule.index.RuleIndexDefinition;
-import org.sonar.server.rule.index.RuleIndexer;
 
 import java.util.Optional;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.api.rule.Severity.BLOCKER;
 import static org.sonar.api.rules.RuleType.BUG;
-import static org.sonar.server.organization.TestDefaultOrganizationProvider.from;
-import static org.sonar.server.util.TypeValidationsTesting.newFullTypeValidations;
 
 public class PersistExternalRulesStepTest extends BaseStepTest {
 
@@ -56,7 +53,6 @@ public class PersistExternalRulesStepTest extends BaseStepTest {
     .setOrganizationUuid("org-1", "qg-uuid-1");
 
   private DbClient dbClient = db.getDbClient();
-  private System2 system2 = System2.INSTANCE;
 
   private ComputationStep underTest;
   private RuleRepositoryImpl ruleRepository;
@@ -64,9 +60,7 @@ public class PersistExternalRulesStepTest extends BaseStepTest {
   @org.junit.Rule
   public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
 
-  private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient());
-  private RuleCreator creator = new RuleCreator(System2.INSTANCE, ruleIndexer, db.getDbClient(), newFullTypeValidations(), from(db));
-
+  private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
 
   @Override
   protected ComputationStep step() {
@@ -75,7 +69,7 @@ public class PersistExternalRulesStepTest extends BaseStepTest {
 
   @Before
   public void setup() {
-    ruleRepository = new RuleRepositoryImpl(creator, dbClient, analysisMetadataHolder);
+    ruleRepository = new RuleRepositoryImpl(externalRuleCreator, dbClient, analysisMetadataHolder);
     underTest = new PersistExternalRulesStep(dbClient, ruleRepository);
   }
 
index 2d3590b42fb38e71c1c570a62e0946933111a3e8..e57c3dd6729560ef8182a39b19ff7dcb72b913a0 100644 (file)
@@ -52,9 +52,8 @@ import org.sonar.server.computation.task.projectanalysis.issue.RuleRepositoryImp
 import org.sonar.server.computation.task.projectanalysis.issue.UpdateConflictResolver;
 import org.sonar.server.computation.task.step.ComputationStep;
 import org.sonar.server.es.EsTester;
-import org.sonar.server.rule.RuleCreator;
+import org.sonar.server.rule.ExternalRuleCreator;
 import org.sonar.server.rule.index.RuleIndexDefinition;
-import org.sonar.server.rule.index.RuleIndexer;
 import org.sonar.server.util.cache.DiskCache;
 
 import static java.util.Collections.singletonList;
@@ -66,8 +65,6 @@ import static org.sonar.api.issue.Issue.STATUS_CLOSED;
 import static org.sonar.api.issue.Issue.STATUS_OPEN;
 import static org.sonar.api.rule.Severity.BLOCKER;
 import static org.sonar.db.component.ComponentTesting.newFileDto;
-import static org.sonar.server.organization.TestDefaultOrganizationProvider.from;
-import static org.sonar.server.util.TypeValidationsTesting.newFullTypeValidations;
 
 public class PersistIssuesStepTest extends BaseStepTest {
 
@@ -92,8 +89,7 @@ public class PersistIssuesStepTest extends BaseStepTest {
   @org.junit.Rule
   public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
 
-  private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient());
-  private RuleCreator creator = new RuleCreator(System2.INSTANCE, ruleIndexer, db.getDbClient(), newFullTypeValidations(), from(db));
+  private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
 
   @Override
   protected ComputationStep step() {
@@ -107,7 +103,7 @@ public class PersistIssuesStepTest extends BaseStepTest {
     when(system2.now()).thenReturn(NOW);
     reportReader.setMetadata(ScannerReport.Metadata.getDefaultInstance());
 
-    step = new PersistIssuesStep(dbClient, system2, new UpdateConflictResolver(), new RuleRepositoryImpl(creator, dbClient, analysisMetadataHolder), issueCache);
+    step = new PersistIssuesStep(dbClient, system2, new UpdateConflictResolver(), new RuleRepositoryImpl(externalRuleCreator, dbClient, analysisMetadataHolder), issueCache);
   }
 
   @After
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ExternalRuleCreatorTest.java
new file mode 100644 (file)
index 0000000..2beeddf
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.rule;
+
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.server.computation.task.projectanalysis.issue.NewExternalRule;
+import org.sonar.server.computation.task.projectanalysis.issue.Rule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.rule.Severity.BLOCKER;
+import static org.sonar.api.rules.RuleType.BUG;
+
+public class ExternalRuleCreatorTest {
+
+  @org.junit.Rule
+  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+  private ExternalRuleCreator underTest = new ExternalRuleCreator(dbTester.getDbClient(), System2.INSTANCE);
+  private DbSession dbSession = dbTester.getSession();
+
+  @Test
+  public void create_external_rule() {
+
+    RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
+    NewExternalRule externalRule = new NewExternalRule.Builder()
+      .setKey(ruleKey)
+      .setPluginKey("eslint")
+      .setName("disallow assignment operators in conditional statements (no-cond-assign)")
+      .setDescriptionUrl("https://eslint.org/docs/rules/no-cond-assign")
+      .setSeverity(BLOCKER)
+      .setType(BUG)
+      .build();
+
+    Rule rule1 = underTest.create(dbSession, externalRule);
+
+    assertThat(rule1).isNotNull();
+    assertThat(rule1.isExternal()).isTrue();
+    assertThat(rule1.getId()).isGreaterThan(0);
+    assertThat(rule1.getKey()).isEqualTo(ruleKey);
+    assertThat(rule1.getPluginKey()).isEqualTo("eslint");
+    assertThat(rule1.getName()).isEqualTo("disallow assignment operators in conditional statements (no-cond-assign)");
+    assertThat(rule1.getType()).isEqualTo(BUG);
+
+  }
+
+}