]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6680 RuleRepository now load all rules at first call 587/head
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 19 Oct 2015 15:13:16 +0000 (17:13 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 20 Oct 2015 08:36:17 +0000 (10:36 +0200)
RuleRepository now implements a stonger contract (which is documented)
method hasKey(RuleKey) is replaced by method findByKey(RuleKey) which returns an Optional (saves using two methods in a row when Rule exists)
methods getById(int) and findById(int) added to be able to replace Views' specific RuleRepository with the one from the Compute Engine

server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java
server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleCacheLoader.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleRepository.java
server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleRepositoryImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadQualityProfilesStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/issue/DumbRule.java
server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleCacheLoaderTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleRepositoryImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleRepositoryRule.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistIssuesStepTest.java
server/sonar-server/src/test/resources/org/sonar/server/computation/issue/RuleCacheLoaderTest/shared.xml [deleted file]

index 1273a1e2d4eb409cc33064294a27a5d547a52a79..e2118173965356cf35e0ec150cb51b4ca6565b9b 100644 (file)
@@ -48,7 +48,6 @@ import org.sonar.server.computation.issue.IssueVisitors;
 import org.sonar.server.computation.issue.LoadComponentUuidsHavingOpenIssuesVisitor;
 import org.sonar.server.computation.issue.NewDebtAggregator;
 import org.sonar.server.computation.issue.NewDebtCalculator;
-import org.sonar.server.computation.issue.RuleCacheLoader;
 import org.sonar.server.computation.issue.RuleRepositoryImpl;
 import org.sonar.server.computation.issue.RuleTagsCopier;
 import org.sonar.server.computation.issue.ScmAccountToUser;
@@ -140,7 +139,6 @@ public final class ReportComputeEngineContainerPopulator implements ContainerPop
       ScmInfoRepositoryImpl.class,
 
       // issues
-      RuleCacheLoader.class,
       RuleRepositoryImpl.class,
       ScmAccountToUserLoader.class,
       ScmAccountToUser.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleCacheLoader.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleCacheLoader.java
deleted file mode 100644 (file)
index 8f2443c..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.computation.issue;
-
-import com.google.common.base.Optional;
-import java.util.Collection;
-import java.util.Map;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.MyBatis;
-import org.sonar.db.rule.RuleDto;
-import org.sonar.server.util.cache.CacheLoader;
-
-public class RuleCacheLoader implements CacheLoader<RuleKey, Rule> {
-
-  private final DbClient dbClient;
-
-  public RuleCacheLoader(DbClient dbClient) {
-    this.dbClient = dbClient;
-  }
-
-  @Override
-  public Rule load(RuleKey key) {
-    DbSession session = dbClient.openSession(false);
-    try {
-      Optional<RuleDto> dto = dbClient.ruleDao().selectByKey(session, key);
-      if (dto.isPresent()) {
-        return new RuleImpl(dto.get());
-      }
-      return null;
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
-  @Override
-  public Map<RuleKey, Rule> loadAll(Collection<? extends RuleKey> keys) {
-    throw new UnsupportedOperationException("Not implemented yet");
-  }
-}
index 57bd78c1e1960fae4c6bc4833ce471e48a728787..be6facd26405c684d7f296dc4d44b75238b438c6 100644 (file)
  */
 package org.sonar.server.computation.issue;
 
+import com.google.common.base.Optional;
 import org.sonar.api.rule.RuleKey;
 
+/**
+ * Repository of every rule in DB (including manual rules) whichever their status.
+ */
 public interface RuleRepository {
 
+  /**
+   * @throws NullPointerException if {@code key} is {@code null}
+   * @throws IllegalArgumentException when there is no Rule for the specified RuleKey in the repository
+   */
   Rule getByKey(RuleKey key);
 
-  boolean hasKey(RuleKey key);
+  /**
+   * @throws IllegalArgumentException when there is no Rule for the specified RuleKey in the repository
+   */
+  Rule getById(int id);
+
+  /**
+   * @throws NullPointerException if {@code key} is {@code null}
+   */
+  Optional<Rule> findByKey(RuleKey key);
+
+  Optional<Rule> findById(int id);
 }
index 63c96ab24b616c3e36ce009a323fda670be3e0e1..dd2935e58e5b1533dd86c52d8e6f92d508bc42ee 100644 (file)
  */
 package org.sonar.server.computation.issue;
 
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import javax.annotation.CheckForNull;
 import org.sonar.api.rule.RuleKey;
-import org.sonar.server.util.cache.MemoryCache;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.rule.RuleDto;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
 
 public class RuleRepositoryImpl implements RuleRepository {
 
-  private final MemoryCache<RuleKey, Rule> cache;
+  @CheckForNull
+  private Map<RuleKey, Rule> rulesByKey;
+  @CheckForNull
+  private Map<Integer, Rule> rulesById;
+
+  private final DbClient dbClient;
 
-  public RuleRepositoryImpl(RuleCacheLoader cacheLoader) {
-    this.cache = new MemoryCache<>(cacheLoader);
+  public RuleRepositoryImpl(DbClient dbClient) {
+    this.dbClient = dbClient;
   }
 
   @Override
   public Rule getByKey(RuleKey key) {
-    return cache.get(key);
+    verifyKeyArgument(key);
+
+    ensureInitialized();
+
+    Rule rule = rulesByKey.get(key);
+    checkArgument(rule != null, "Can not find rule for key %s. This rule does not exist in DB", key);
+    return rule;
   }
 
   @Override
-  public boolean hasKey(RuleKey key) {
-    return cache.getNullable(key) != null;
+  public Optional<Rule> findByKey(RuleKey key) {
+    verifyKeyArgument(key);
+
+    ensureInitialized();
+
+    return Optional.fromNullable(rulesByKey.get(key));
   }
+
+  @Override
+  public Rule getById(int id) {
+    ensureInitialized();
+
+    Rule rule = rulesById.get(id);
+    checkArgument(rule != null, "Can not find rule for id %s. This rule does not exist in DB", id);
+    return rule;
+  }
+
+  @Override
+  public Optional<Rule> findById(int id) {
+    ensureInitialized();
+
+    return Optional.fromNullable(rulesById.get(id));
+  }
+
+  private static void verifyKeyArgument(RuleKey key) {
+    requireNonNull(key, "RuleKey can not be null");
+  }
+
+  private void ensureInitialized() {
+    if (rulesByKey == null) {
+      DbSession dbSession = dbClient.openSession(false);
+      try {
+        loadRulesFromDb(dbSession);
+      } finally {
+        dbClient.closeSession(dbSession);
+      }
+    }
+  }
+
+  private void loadRulesFromDb(DbSession dbSession) {
+    ImmutableMap.Builder<RuleKey, Rule> rulesByKeyBuilder = ImmutableMap.builder();
+    ImmutableMap.Builder<Integer, Rule> rulesByIdBuilder = ImmutableMap.builder();
+    for (RuleDto ruleDto : dbClient.ruleDao().selectAll(dbSession)) {
+      Rule rule = new RuleImpl(ruleDto);
+      rulesByKeyBuilder.put(ruleDto.getKey(), rule);
+      rulesByIdBuilder.put(ruleDto.getId(), rule);
+    }
+    this.rulesByKey = rulesByKeyBuilder.build();
+    this.rulesById = rulesByIdBuilder.build();
+  }
+
 }
index bf19a622ddaa64ed673c9c7e715aa849dee7cd47..c7b73058510eb588224fea5941a331d7ae9b1122 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.computation.step;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -66,11 +67,8 @@ public class LoadQualityProfilesStep implements ComputationStep {
   private class IsValid implements Predicate<ActiveRule> {
     @Override
     public boolean apply(@Nonnull ActiveRule input) {
-      if (ruleRepository.hasKey(input.getRuleKey())) {
-        Rule rule = ruleRepository.getByKey(input.getRuleKey());
-        return rule.getStatus() != RuleStatus.REMOVED;
-      }
-      return false;
+      Optional<Rule> rule = ruleRepository.findByKey(input.getRuleKey());
+      return rule.isPresent() && rule.get().getStatus() != RuleStatus.REMOVED;
     }
   }
 
index 72e780b22987ebe6c1610f4d8d58d212fe1867c5..45c340ac4c9e740b41ed9d07f1f1d08c4edc28f8 100644 (file)
@@ -39,6 +39,7 @@ public class DumbRule implements Rule {
 
   public DumbRule(RuleKey key) {
     this.key = key;
+    this.id = key.hashCode();
   }
 
   @Override
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleCacheLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleCacheLoaderTest.java
deleted file mode 100644 (file)
index fc490fa..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.computation.issue;
-
-import java.util.Collections;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbTester;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-
-@Category(DbTests.class)
-public class RuleCacheLoaderTest {
-
-  @org.junit.Rule
-  public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
-  @Before
-  public void setUp() {
-    dbTester.truncateTables();
-  }
-
-  @Test
-  public void load_by_key() {
-    dbTester.prepareDbUnit(getClass(), "shared.xml");
-    RuleCacheLoader loader = new RuleCacheLoader(dbTester.getDbClient());
-
-    Rule javaRule = loader.load(RuleKey.of("java", "JAV01"));
-    assertThat(javaRule.getName()).isEqualTo("Java One");
-
-    Rule jsRule = loader.load(RuleKey.of("js", "JS01"));
-    assertThat(jsRule.getName()).isEqualTo("JS One");
-
-    assertThat(loader.load(RuleKey.of("java", "MISSING"))).isNull();
-  }
-
-  @Test
-  public void load_by_keys_is_not_supported() {
-    RuleCacheLoader loader = new RuleCacheLoader(dbTester.getDbClient());
-    try {
-      loader.loadAll(Collections.<RuleKey>emptyList());
-      fail();
-    } catch (UnsupportedOperationException e) {
-      // see RuleDao#getByKeys()
-    }
-  }
-
-}
index 1497bbce6fd39b294582365bfe674935705a3cd4..5b12101525b7452699547e097b3fb73e48f34593 100644 (file)
  */
 package org.sonar.server.computation.issue;
 
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import org.junit.Before;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.rule.RuleDao;
+import org.sonar.db.rule.RuleDto;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 import static org.mockito.internal.verification.VerificationModeFactory.times;
-import static org.sonar.db.rule.RuleTesting.XOO_X1;
-import static org.sonar.db.rule.RuleTesting.XOO_X2;
 
 public class RuleRepositoryImplTest {
 
-  RuleCacheLoader cacheLoader = mock(RuleCacheLoader.class);
-  RuleRepositoryImpl underTest = new RuleRepositoryImpl(cacheLoader);
+  private static final RuleDto AB_RULE = createABRuleDto();
+  private static final RuleKey AC_RULE_KEY = RuleKey.of("a", "c");
+  private static final int AC_RULE_ID = 684;
+
+  @org.junit.Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private DbClient dbClient = mock(DbClient.class);
+  private DbSession dbSession = mock(DbSession.class);
+  private RuleDao ruleDao = mock(RuleDao.class);
+
+  RuleRepositoryImpl underTest = new RuleRepositoryImpl(dbClient);
+
+  @Before
+  public void setUp() throws Exception {
+    when(dbClient.openSession(anyBoolean())).thenReturn(dbSession);
+    when(dbClient.ruleDao()).thenReturn(ruleDao);
+    when(ruleDao.selectAll(any(DbSession.class))).thenReturn(ImmutableList.of(AB_RULE));
+  }
+
+  @Test
+  public void constructor_does_not_query_DB_to_retrieve_rules() {
+    verifyNoMoreInteractions(dbClient);
+  }
+
+  @Test
+  public void first_call_to_getByKey_triggers_call_to_db_and_any_subsequent_get_or_find_call_does_not() {
+    underTest.getByKey(AB_RULE.getKey());
+
+    verify(ruleDao, times(1)).selectAll(any(DbSession.class));
+
+    verifyNoMethodCallTriggersCallToDB();
+  }
+
+  @Test
+  public void first_call_to_findByKey_triggers_call_to_db_and_any_subsequent_get_or_find_call_does_not() {
+    underTest.findByKey(AB_RULE.getKey());
+
+    verify(ruleDao, times(1)).selectAll(any(DbSession.class));
+
+    verifyNoMethodCallTriggersCallToDB();
+  }
+
+  @Test
+  public void first_call_to_getById_triggers_call_to_db_and_any_subsequent_get_or_find_call_does_not() {
+    underTest.getById(AB_RULE.getId());
+
+    verify(ruleDao, times(1)).selectAll(any(DbSession.class));
+
+    verifyNoMethodCallTriggersCallToDB();
+  }
+
+  @Test
+  public void first_call_to_findById_triggers_call_to_db_and_any_subsequent_get_or_find_call_does_not() {
+    underTest.findById(AB_RULE.getId());
+
+    verify(ruleDao, times(1)).selectAll(any(DbSession.class));
+
+    verifyNoMethodCallTriggersCallToDB();
+  }
+
+  @Test
+  public void getByKey_throws_NPE_if_key_argument_is_null() {
+    expectNullRuleKeyNPE();
+
+    underTest.getByKey(null);
+  }
+
+  @Test
+  public void getByKey_does_not_call_DB_if_key_argument_is_null() {
+    try {
+      underTest.getByKey(null);
+    } catch (NullPointerException e) {
+      assertNoCallToDb();
+    }
+  }
+
+  @Test
+  public void getByKey_returns_Rule_if_it_exists_in_DB() {
+    Rule rule = underTest.getByKey(AB_RULE.getKey());
+
+    assertIsABRule(rule);
+  }
+
+  @Test
+  public void getByKey_throws_IAE_if_rules_does_not_exist_in_DB() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Can not find rule for key a:c. This rule does not exist in DB");
+
+    underTest.getByKey(AC_RULE_KEY);
+  }
+
+  @Test
+  public void findByKey_throws_NPE_if_key_argument_is_null() {
+    expectNullRuleKeyNPE();
+
+    underTest.findByKey(null);
+  }
+
+  @Test
+  public void findByKey_does_not_call_DB_if_key_argument_is_null() {
+    try {
+      underTest.findByKey(null);
+    } catch (NullPointerException e) {
+      assertNoCallToDb();
+    }
+  }
+
+  @Test
+  public void findByKey_returns_absent_if_rule_does_not_exist_in_DB() {
+    Optional<Rule> rule = underTest.findByKey(AC_RULE_KEY);
+
+    assertThat(rule).isAbsent();
+  }
+
+  @Test
+  public void findByKey_returns_Rule_if_it_exists_in_DB() {
+    Optional<Rule> rule = underTest.findByKey(AB_RULE.getKey());
+
+    assertIsABRule(rule.get());
+  }
+
+  @Test
+  public void getById_returns_Rule_if_it_exists_in_DB() {
+    Rule rule = underTest.getById(AB_RULE.getId());
+
+    assertIsABRule(rule);
+  }
 
   @Test
-  public void getByKey() {
-    when(cacheLoader.load(XOO_X1)).thenReturn(new DumbRule(XOO_X1));
+  public void getById_throws_IAE_if_rules_does_not_exist_in_DB() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Can not find rule for id " + AC_RULE_ID + ". This rule does not exist in DB");
 
-    assertThat(underTest.getByKey(XOO_X1).getKey()).isEqualTo(XOO_X1);
+    underTest.getById(AC_RULE_ID);
+  }
+
+  @Test
+  public void findById_returns_absent_if_rule_does_not_exist_in_DB() {
+    Optional<Rule> rule = underTest.findById(AC_RULE_ID);
 
-    // second call -> get from cache
-    assertThat(underTest.getByKey(XOO_X1).getKey()).isEqualTo(XOO_X1);
-    verify(cacheLoader, times(1)).load(XOO_X1);
+    assertThat(rule).isAbsent();
   }
 
   @Test
-  public void hasKey() {
-    when(cacheLoader.load(XOO_X1)).thenReturn(new DumbRule(XOO_X1));
+  public void findById_returns_Rule_if_it_exists_in_DB() {
+    Optional<Rule> rule = underTest.findById(AB_RULE.getId());
+
+    assertIsABRule(rule.get());
+  }
 
-    assertThat(underTest.hasKey(XOO_X1)).isTrue();
-    assertThat(underTest.hasKey(XOO_X2)).isFalse();
+  private void expectNullRuleKeyNPE() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("RuleKey can not be null");
   }
+
+  private void verifyNoMethodCallTriggersCallToDB() {
+    reset(ruleDao);
+    underTest.getByKey(AB_RULE.getKey());
+    assertNoCallToDb();
+    reset(ruleDao);
+    underTest.findByKey(AB_RULE.getKey());
+    assertNoCallToDb();
+    reset(ruleDao);
+    underTest.getById(AB_RULE.getId());
+    assertNoCallToDb();
+    reset(ruleDao);
+    underTest.findById(AB_RULE.getId());
+    assertNoCallToDb();
+  }
+
+  private void assertNoCallToDb() {
+    verifyNoMoreInteractions(ruleDao);
+  }
+
+  private void assertIsABRule(Rule rule) {
+    assertThat(rule).isNotNull();
+    assertThat(rule.getId()).isEqualTo(AB_RULE.getId());
+    assertThat(rule.getKey()).isEqualTo(AB_RULE.getKey());
+    assertThat(rule.getRemediationFunction()).isNull();
+    assertThat(rule.getSubCharacteristicId()).isNull();
+    assertThat(rule.getStatus()).isEqualTo(RuleStatus.REMOVED);
+  }
+
+  private static RuleDto createABRuleDto() {
+    RuleKey ruleKey = RuleKey.of("a", "b");
+    RuleDto res = new RuleDto();
+    res.setId(ruleKey.hashCode());
+    res.setRepositoryKey(ruleKey.repository());
+    res.setRuleKey(ruleKey.rule());
+    res.setStatus(RuleStatus.REMOVED);
+    return res;
+  }
+
 }
index d50be77dafa6cb2341450830607c1f1289fc05ef..5cde0f10be0d5e9fdf0a1da60da48bbd9c9e461d 100644 (file)
  */
 package org.sonar.server.computation.issue;
 
+import com.google.common.base.Optional;
 import java.util.HashMap;
 import java.util.Map;
 import org.junit.rules.ExternalResource;
 import org.sonar.api.rule.RuleKey;
-import org.sonar.server.exceptions.NotFoundException;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
 
 public class RuleRepositoryRule extends ExternalResource implements RuleRepository {
 
   private final Map<RuleKey, Rule> rulesByKey = new HashMap<>();
+  private final Map<Integer, Rule> rulesById = new HashMap<>();
 
   @Override
   protected void after() {
     rulesByKey.clear();
+    rulesById.clear();
   }
 
   @Override
   public Rule getByKey(RuleKey key) {
-    Rule rule = rulesByKey.get(key);
-    if (rule == null) {
-      throw new NotFoundException();
-    }
+    Rule rule = rulesByKey.get(requireNonNull(key));
+    checkArgument(rule != null);
+    return rule;
+  }
+
+  @Override
+  public Rule getById(int id) {
+    Rule rule = rulesById.get(id);
+    checkArgument(rule != null);
     return rule;
   }
 
   @Override
-  public boolean hasKey(RuleKey key) {
-    return rulesByKey.containsKey(key);
+  public Optional<Rule> findByKey(RuleKey key) {
+    return Optional.fromNullable(rulesByKey.get(requireNonNull(key)));
+  }
+
+  @Override
+  public Optional<Rule> findById(int id) {
+    return Optional.fromNullable(rulesById.get(id));
   }
 
   public DumbRule add(RuleKey key) {
     DumbRule rule = new DumbRule(key);
+    rule.setId(key.hashCode());
     rulesByKey.put(key, rule);
+    rulesById.put(rule.getId(), rule);
     return rule;
   }
 
   public RuleRepositoryRule add(DumbRule rule) {
-    rulesByKey.put(rule.getKey(), rule);
+    rulesByKey.put(requireNonNull(rule.getKey()), rule);
+    rulesById.put(requireNonNull(rule.getId()), rule);
     return this;
   }
 
index 344e3f0769df969a1b29f66cab885a0186f9b818..53198c87543cb4f157743b89cbfec93f8a950e20 100644 (file)
@@ -38,7 +38,6 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.server.computation.batch.BatchReportReaderRule;
 import org.sonar.server.computation.issue.IssueCache;
-import org.sonar.server.computation.issue.RuleCacheLoader;
 import org.sonar.server.computation.issue.RuleRepositoryImpl;
 import org.sonar.server.computation.issue.UpdateConflictResolver;
 
@@ -81,7 +80,7 @@ public class PersistIssuesStepTest extends BaseStepTest {
     when(system2.now()).thenReturn(NOW);
     reportReader.setMetadata(BatchReport.Metadata.getDefaultInstance());
 
-    step = new PersistIssuesStep(dbClient, system2, new UpdateConflictResolver(), new RuleRepositoryImpl(new RuleCacheLoader(dbClient)), issueCache);
+    step = new PersistIssuesStep(dbClient, system2, new UpdateConflictResolver(), new RuleRepositoryImpl(dbClient), issueCache);
   }
 
   @After
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/issue/RuleCacheLoaderTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/issue/RuleCacheLoaderTest/shared.xml
deleted file mode 100644 (file)
index 075ab07..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<dataset>
-  <rules id="1" name="JS One" plugin_name="js" plugin_rule_key="JS01"
-         plugin_config_key="[null]" description="[null]" priority="4"
-         status="READY"
-         is_template="[false]" template_id="[null]"
-         tags="[null]" system_tags="[null]"/>
-
-  <rules id="2" name="Java One" plugin_name="java" plugin_rule_key="JAV01"
-         plugin_config_key="[null]" description="[null]" priority="4"
-         status="READY"
-         is_template="[false]" template_id="[null]"
-         tags="[null]" system_tags="[null]"/>
-
-</dataset>