Package org.sonar.server.rule

Source Code of org.sonar.server.rule.RegisterRulesMediumTest

/*
* 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.rule;

import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang.time.DateUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rule.Severity;
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.server.rule.RuleParamType;
import org.sonar.api.server.rule.RulesDefinition;
import org.sonar.api.utils.MessageException;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.qualityprofile.db.ActiveRuleKey;
import org.sonar.core.rule.RuleDto;
import org.sonar.core.rule.RuleParamDto;
import org.sonar.server.db.DbClient;
import org.sonar.server.platform.Platform;
import org.sonar.server.qualityprofile.ActiveRule;
import org.sonar.server.qualityprofile.QProfileService;
import org.sonar.server.qualityprofile.QProfileTesting;
import org.sonar.server.qualityprofile.RuleActivation;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.rule.index.RuleQuery;
import org.sonar.server.search.QueryContext;
import org.sonar.server.search.Result;
import org.sonar.server.tester.ServerTester;
import org.sonar.server.user.MockUserSession;
import org.sonar.server.user.UserSession;

import javax.annotation.Nullable;

import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.google.common.collect.Sets.newHashSet;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;

public class RegisterRulesMediumTest {

  static final XooRulesDefinition RULE_DEFS = new XooRulesDefinition();

  @ClassRule
  public static final ServerTester TESTER = new ServerTester().addXoo().addComponents(RULE_DEFS);

  RuleIndex ruleIndex;
  ActiveRuleIndex activeRuleIndex;
  DbClient db;
  DbSession dbSession;

  @Before
  public void before() {
    TESTER.clearDbAndIndexes();
    db = TESTER.get(DbClient.class);
    dbSession = TESTER.get(DbClient.class).openSession(false);
    dbSession.clearCache();
    ruleIndex = TESTER.get(RuleIndex.class);
    activeRuleIndex = TESTER.get(ActiveRuleIndex.class);
  }

  @After
  public void after() {
    if (dbSession != null) {
      dbSession.close();
    }
  }

  private void register(@Nullable Rules rules) {
    if (dbSession != null) {
      dbSession.close();
    }
    RULE_DEFS.set(rules);
    TESTER.get(Platform.class).executeStartupTasks();
    db = TESTER.get(DbClient.class);
    dbSession = TESTER.get(DbClient.class).openSession(false);
    dbSession.clearCache();
    ruleIndex = TESTER.get(RuleIndex.class);
  }

  @Test
  public void register_rules_at_startup() throws Exception {
    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        RulesDefinition.NewRule x1Rule = repository.createRule("x1")
          .setName("x1 name")
          .setMarkdownDescription("x1 desc")
          .setSeverity(Severity.MINOR)
          .setEffortToFixDescription("x1 effort to fix")
          .setTags("tag1");
        x1Rule.createParam("acceptWhitespace")
          .setType(RuleParamType.BOOLEAN)
          .setDefaultValue("false")
          .setDescription("Accept whitespaces on the line");
        x1Rule.createParam("min")
          .setType(RuleParamType.INTEGER);
        x1Rule
          .setDebtSubCharacteristic(RulesDefinition.SubCharacteristics.INTEGRATION_TESTABILITY)
          .setDebtRemediationFunction(x1Rule.debtRemediationFunctions().linearWithOffset("1h", "30min"));
      }
    });

    // verify db
    List<RuleDto> rules = db.ruleDao().findAll(dbSession);
    assertThat(rules).hasSize(1);
    assertThat(rules.get(0).getKey()).isEqualTo(RuleKey.of("xoo", "x1"));
    List<RuleParamDto> ruleParams = db.ruleDao().findAllRuleParams(dbSession);
    assertThat(ruleParams).hasSize(2);

    // verify es
    Result<Rule> searchResult = ruleIndex.search(new RuleQuery(), new QueryContext());
    assertThat(searchResult.getTotal()).isEqualTo(1);
    assertThat(searchResult.getHits()).hasSize(1);
    Rule rule = ruleIndex.getByKey(RuleKey.of("xoo", "x1"));
    assertThat(rule.severity()).isEqualTo(Severity.MINOR);
    assertThat(rule.name()).isEqualTo("x1 name");
    assertThat(rule.htmlDescription()).isEqualTo("x1 desc");
    assertThat(rule.systemTags()).contains("tag1");
    assertThat(rule.language()).contains("xoo");
    assertThat(rule.params()).hasSize(2);
    assertThat(rule.param("acceptWhitespace").type()).isEqualTo(RuleParamType.BOOLEAN);
    assertThat(rule.param("acceptWhitespace").defaultValue()).isEqualTo("false");
    assertThat(rule.param("acceptWhitespace").description()).isEqualTo("Accept whitespaces on the line");
    assertThat(rule.param("min").type()).isEqualTo(RuleParamType.INTEGER);
    assertThat(rule.param("min").defaultValue()).isNull();
    assertThat(rule.param("min").description()).isNull();
    assertThat(rule.debtSubCharacteristicKey()).isEqualTo(RulesDefinition.SubCharacteristics.INTEGRATION_TESTABILITY);
    assertThat(rule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
    assertThat(rule.debtRemediationFunction().coefficient()).isEqualTo("1h");
    assertThat(rule.debtRemediationFunction().offset()).isEqualTo("30min");
    assertThat(rule.effortToFixDescription()).isEqualTo("x1 effort to fix");
  }

  /**
   * Use-case:
   * 1. start server
   * 2. stop server
   * 3. drop elasticsearch index: rm -rf data/es
   * 4. start server -> db is up-to-date (no changes) but rules must be re-indexed
   */
  @Test
  public void index_rules_even_if_no_changes() throws Exception {
    Rules rules = new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("x1")
          .setName("x1 name")
          .setHtmlDescription("x1 desc");
      }
    };
    register(rules);

    // clear ES but keep db
    TESTER.clearIndexes();
    register(rules);

    // verify that rules are indexed
    Result<Rule> searchResult = ruleIndex.search(new RuleQuery(), new QueryContext());
    searchResult = ruleIndex.search(new RuleQuery().setKey("xoo:x1"), new QueryContext());
    assertThat(searchResult.getTotal()).isEqualTo(1);
    assertThat(searchResult.getHits()).hasSize(1);
    assertThat(searchResult.getHits().get(0).key()).isEqualTo(RuleKey.of("xoo", "x1"));
  }

  @Test
  public void update_existing_rules() {
    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        RulesDefinition.NewRule x1Rule = repository.createRule("x1")
          .setName("Name1")
          .setHtmlDescription("Desc1")
          .setSeverity(Severity.MINOR)
          .setEffortToFixDescription("Effort1")
          .setTags("tag1", "tag2");
        x1Rule.createParam("max")
          .setType(RuleParamType.INTEGER)
          .setDefaultValue("10")
          .setDescription("Maximum1");
        x1Rule.createParam("min")
          .setType(RuleParamType.INTEGER);
        x1Rule
          .setDebtSubCharacteristic(RulesDefinition.SubCharacteristics.INTEGRATION_TESTABILITY)
          .setDebtRemediationFunction(x1Rule.debtRemediationFunctions().linearWithOffset("1h", "30min"));
      }
    });

    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        RulesDefinition.NewRule x1Rule = repository.createRule(RuleTesting.XOO_X1.rule())
          .setName("Name2")
          .setHtmlDescription("Desc2")
          .setSeverity(Severity.INFO)
          .setEffortToFixDescription("Effort2")
          .setTags("tag2", "tag3");
        // Param "max" is updated, "min" is removed, "format" is added
        x1Rule.createParam("max")
          .setType(RuleParamType.INTEGER)
          .setDefaultValue("15")
          .setDescription("Maximum2");
        x1Rule.createParam("format").setType(RuleParamType.TEXT);
        x1Rule
          .setDebtSubCharacteristic(RulesDefinition.SubCharacteristics.INSTRUCTION_RELIABILITY)
          .setDebtRemediationFunction(x1Rule.debtRemediationFunctions().linear("2h"));
      }
    });

    Rule rule = ruleIndex.getByKey(RuleTesting.XOO_X1);
    assertThat(rule.severity()).isEqualTo(Severity.INFO);
    assertThat(rule.name()).isEqualTo("Name2");
    assertThat(rule.htmlDescription()).isEqualTo("Desc2");
    assertThat(rule.systemTags()).contains("tag2", "tag3");
    assertThat(rule.params()).hasSize(2);
    assertThat(rule.param("max").type()).isEqualTo(RuleParamType.INTEGER);
    assertThat(rule.param("max").defaultValue()).isEqualTo("15");
    assertThat(rule.param("max").description()).isEqualTo("Maximum2");
    assertThat(rule.param("format").type()).isEqualTo(RuleParamType.TEXT);
    assertThat(rule.param("format").defaultValue()).isNull();
    assertThat(rule.param("format").description()).isNull();
    assertThat(rule.debtSubCharacteristicKey()).isEqualTo(RulesDefinition.SubCharacteristics.INSTRUCTION_RELIABILITY);
    assertThat(rule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR);
    assertThat(rule.debtRemediationFunction().coefficient()).isEqualTo("2h");
    assertThat(rule.debtRemediationFunction().offset()).isNull();
    assertThat(rule.effortToFixDescription()).isEqualTo("Effort2");
  }

  @Test
  public void do_not_update_rules_if_no_changes() throws Exception {
    Rules rules = new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("x1").setName("x1 name").setHtmlDescription("x1 desc");
      }
    };
    register(rules);

    // Store updated at date
    Date updatedAt = ruleIndex.getByKey(RuleTesting.XOO_X1).updatedAt();

    // Re-execute startup tasks
    register(rules);

    // Verify rule has not been updated
    Rule customRuleReloaded = ruleIndex.getByKey(RuleTesting.XOO_X1);
    assertThat(DateUtils.isSameInstant(customRuleReloaded.updatedAt(), updatedAt));
  }

  @Test
  public void disable_then_enable_rules() {
    Rules rules = new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("x1").setName("x1 name").setHtmlDescription("x1 desc");
      }
    };
    register(rules);

    // Uninstall plugin
    register(null);
    RuleDto rule = db.ruleDao().getByKey(dbSession, RuleTesting.XOO_X1);
    assertThat(rule.getStatus()).isEqualTo(RuleStatus.REMOVED);
    Rule indexedRule = ruleIndex.getByKey(RuleTesting.XOO_X1);
    assertThat(indexedRule.status()).isEqualTo(RuleStatus.REMOVED);

    // Re-install plugin
    register(rules);
    rule = db.ruleDao().getByKey(dbSession, RuleTesting.XOO_X1);
    assertThat(rule.getStatus()).isEqualTo(RuleStatus.READY);
    indexedRule = ruleIndex.getByKey(RuleTesting.XOO_X1);
    assertThat(indexedRule.status()).isEqualTo(RuleStatus.READY);
  }

  @Test
  public void deactivate_removed_rules_only_if_repository_still_exists() throws Exception {
    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("x1").setName("x1 name").setHtmlDescription("x1 desc");
      }
    });

    // Create a profile and activate rule
    MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN).setLogin("me");
    db.qualityProfileDao().insert(dbSession, QProfileTesting.newXooP1());
    dbSession.commit();
    dbSession.clearCache();
    RuleActivation activation = new RuleActivation(RuleTesting.XOO_X1);
    TESTER.get(QProfileService.class).activate(QProfileTesting.XOO_P1_KEY, activation);

    // Restart, repo xoo still exists -> deactivate x1
    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("x2").setName("x2 name").setHtmlDescription("x2 desc");
      }
    });
    assertThat(ruleIndex.getByKey(RuleKey.of("xoo", "x1")).status()).isEqualTo(RuleStatus.REMOVED);
    assertThat(ruleIndex.getByKey(RuleKey.of("xoo", "x2")).status()).isEqualTo(RuleStatus.READY);
    assertThat(activeRuleIndex.findByProfile(QProfileTesting.XOO_P1_KEY)).hasSize(0);
  }

  @Test
  public void do_not_deactivate_removed_rules_if_repository_accidentally_uninstalled() throws Exception {
    Rules rules = new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("x1").setName("x1 name").setHtmlDescription("x1 desc");
      }
    };
    register(rules);

    // create a profile and activate rule
    MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN).setLogin("me");
    db.qualityProfileDao().insert(dbSession, QProfileTesting.newXooP1());
    dbSession.commit();
    dbSession.clearCache();
    RuleActivation activation = new RuleActivation(RuleTesting.XOO_X1);
    TESTER.get(QProfileService.class).activate(QProfileTesting.XOO_P1_KEY, activation);

    // Restart without xoo
    register(null);
    assertThat(ruleIndex.getByKey(RuleTesting.XOO_X1).status()).isEqualTo(RuleStatus.REMOVED);
    assertThat(activeRuleIndex.findByProfile(QProfileTesting.XOO_P1_KEY)).isEmpty();

    // Re-install
    register(rules);
    assertThat(ruleIndex.getByKey(RuleTesting.XOO_X1).status()).isEqualTo(RuleStatus.READY);
    assertThat(activeRuleIndex.findByProfile(QProfileTesting.XOO_P1_KEY)).hasSize(1);
  }

  @Test
  public void update_active_rules_on_param_changes() throws Exception {
    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        RulesDefinition.NewRule x1Rule = repository.createRule("x1").setName("x1 name").setHtmlDescription("x1 desc");
        // has default value
        x1Rule.createParam("min").setType(RuleParamType.INTEGER).setDefaultValue("5");
        // no default value
        x1Rule.createParam("format").setType(RuleParamType.STRING);
      }
    });

    // Create profile and activate rule
    MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN).setLogin("me");
    db.qualityProfileDao().insert(dbSession, QProfileTesting.newXooP1());
    dbSession.commit();
    dbSession.clearCache();
    RuleActivation activation = new RuleActivation(RuleTesting.XOO_X1);
    activation.setParameter("format", "txt");
    TESTER.get(QProfileService.class).activate(QProfileTesting.XOO_P1_KEY, activation);

    // Default value of "min" is changed, "format" is removed, "format2" is added, "max" is added with a default value
    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        RulesDefinition.NewRule x1Rule = repository.createRule("x1").setName("x1 name").setHtmlDescription("x1 desc");
        x1Rule.createParam("min").setType(RuleParamType.INTEGER).setDefaultValue("6");
        x1Rule.createParam("format2").setType(RuleParamType.STRING);
        x1Rule.createParam("max").setType(RuleParamType.INTEGER).setDefaultValue("10");
      }
    });

    ActiveRule activeRule = activeRuleIndex.getByKey(ActiveRuleKey.of(QProfileTesting.XOO_P1_KEY, RuleTesting.XOO_X1));
    Map<String, String> params = activeRule.params();
    assertThat(params).hasSize(2);

    // do not change default value on existing active rules -> keep min=5
    assertThat(params.get("min")).isEqualTo("5");

    // new param with default value
    assertThat(params.get("max")).isEqualTo("10");
  }

  @Test
  public void remove_user_tags_that_are_newly_declared_as_system() {
    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("x1").setName("x1 name").setHtmlDescription("x1 desc").setTags("tag1");
      }
    });
    Rule rule = ruleIndex.getByKey(RuleTesting.XOO_X1);
    assertThat(rule.systemTags()).containsOnly("tag1");
    assertThat(rule.tags()).isEmpty();

    // User adds tag
    TESTER.get(RuleUpdater.class).update(RuleUpdate.createForPluginRule(RuleTesting.XOO_X1).setTags(newHashSet("tag2")), UserSession.get());
    dbSession.clearCache();
    rule = ruleIndex.getByKey(RuleTesting.XOO_X1);
    assertThat(rule.systemTags()).containsOnly("tag1");
    assertThat(rule.tags()).containsOnly("tag2");

    // Definition updated -> user tag "tag2" becomes a system tag
    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("x1").setName("x1 name").setHtmlDescription("x1 desc").setTags("tag1", "tag2");
      }
    });
    rule = ruleIndex.getByKey(RuleTesting.XOO_X1);
    assertThat(rule.systemTags()).containsOnly("tag1", "tag2");
    assertThat(rule.tags()).isEmpty();
  }

  @Test
  public void fail_if_debt_characteristic_is_root() throws Exception {
    try {
      register(new Rules() {
        @Override
        public void init(RulesDefinition.NewRepository repository) {
          RulesDefinition.NewRule rule = repository.createRule("x1").setName("x1 name").setHtmlDescription("x1 desc");
          rule
            .setDebtSubCharacteristic("REUSABILITY")
            .setDebtRemediationFunction(rule.debtRemediationFunctions().linearWithOffset("1h", "30min"));
        }
      });
      fail();
    } catch (MessageException e) {
      assertThat(e).hasMessage("Rule 'xoo:x1' cannot be linked on the root characteristic 'REUSABILITY'");
    }
  }

  @Test
  public void update_custom_rule_on_template_change() throws Exception {
    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("T1")
          .setName("template1 name")
          .setHtmlDescription("template1 desc")
          .setSeverity(Severity.MAJOR)
          .setTemplate(true)
          .createParam("format")
          .setDefaultValue("csv")
          .setType(RuleParamType.STRING)
          .setDescription("format parameter");
      }
    });
    Rule template = ruleIndex.getByKey(RuleKey.of("xoo", "T1"));

    // Create custom rule
    RuleKey customRuleKey = TESTER.get(RuleCreator.class).create(NewRule.createForCustomRule("CUSTOM_RULE", template.key())
      .setName("My custom")
      .setHtmlDescription("Some description")
      .setSeverity(Severity.MAJOR)
      .setStatus(RuleStatus.READY)
      .setParameters(ImmutableMap.of("format", "txt")));

    // Update template and restart
    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        RulesDefinition.NewRule rule = repository.createRule("T1")
          .setName("template1 name")
          .setHtmlDescription("template1 desc")
          .setSeverity(Severity.BLOCKER)
          .setStatus(RuleStatus.BETA)
          .setTemplate(true)
          .setInternalKey("new_internal");
        rule
          .setDebtSubCharacteristic(RulesDefinition.SubCharacteristics.INTEGRATION_TESTABILITY)
          .setDebtRemediationFunction(rule.debtRemediationFunctions().linearWithOffset("1h", "30min"))
          .setEffortToFixDescription("Effort");
      }
    });

    // Verify custom rule has been restore from the template
    Rule customRule = ruleIndex.getByKey(customRuleKey);
    assertThat(customRule.language()).isEqualTo("xoo");
    assertThat(customRule.internalKey()).isEqualTo("new_internal");
    assertThat(customRule.severity()).isEqualTo(Severity.BLOCKER);
    assertThat(customRule.status()).isEqualTo(RuleStatus.BETA);
    assertThat(customRule.debtSubCharacteristicKey()).isEqualTo(RulesDefinition.SubCharacteristics.INTEGRATION_TESTABILITY);
    assertThat(customRule.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
    assertThat(customRule.effortToFixDescription()).isEqualTo("Effort");
  }

  @Test
  public void do_not_update_custom_rule_if_no_template_change() throws Exception {
    Rules rules = new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("T1")
          .setName("template1 name")
          .setHtmlDescription("template1 desc")
          .setSeverity(Severity.MAJOR)
          .setTemplate(true)
          .createParam("format")
          .setDefaultValue("csv")
          .setType(RuleParamType.STRING)
          .setDescription("format parameter");
      }
    };
    register(rules);
    Rule template = ruleIndex.getByKey(RuleKey.of("xoo", "T1"));

    // Create custom rule
    RuleKey customRuleKey = TESTER.get(RuleCreator.class).create(NewRule.createForCustomRule("CUSTOM_RULE", template.key())
      .setName("My custom")
      .setHtmlDescription("Some description")
      .setSeverity(Severity.MAJOR)
      .setStatus(RuleStatus.READY)
      .setParameters(ImmutableMap.of("format", "txt")));

    Date updatedAt = ruleIndex.getByKey(customRuleKey).updatedAt();

    register(rules);

    // Verify custom rule has been restore from the template
    Rule customRuleReloaded = ruleIndex.getByKey(customRuleKey);
    assertThat(customRuleReloaded.updatedAt()).isEqualTo(updatedAt);
  }

  @Test
  public void do_not_update_custom_rule_params_from_template() throws Exception {
    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("T1")
          .setName("template1 name")
          .setHtmlDescription("template1 desc")
          .setSeverity(Severity.MAJOR)
          .setTemplate(true)
          .createParam("format")
          .setDefaultValue("csv")
          .setType(RuleParamType.STRING)
          .setDescription("format parameter");
      }
    });
    Rule templateRule = ruleIndex.getByKey(RuleKey.of("xoo", "T1"));

    // Create custom rule
    RuleKey customRuleKey = TESTER.get(RuleCreator.class).create(NewRule.createForCustomRule("CUSTOM_RULE", templateRule.key())
      .setName("My custom")
      .setHtmlDescription("Some description")
      .setSeverity(Severity.MAJOR)
      .setStatus(RuleStatus.READY)
      .setParameters(ImmutableMap.of("format", "txt")));

    register(new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("T1")
          .setName("template1 name")
          .setHtmlDescription("template1 desc")
          .setSeverity(Severity.MAJOR)
          .setTemplate(true)
          // "format" removed, "format2" added
          .createParam("format2")
          .setDefaultValue("csv")
          .setType(RuleParamType.STRING)
          .setDescription("format parameter");
      }
    });

    // Verify custom rule param has not been changed!
    Rule customRuleReloaded = ruleIndex.getByKey(customRuleKey);
    assertThat(customRuleReloaded.params().get(0).key()).isEqualTo("format");
  }

  @Test
  public void disable_custom_rules_if_template_disabled() {
    Rules rules = new Rules() {
      @Override
      public void init(RulesDefinition.NewRepository repository) {
        repository.createRule("T1")
          .setName("template1 name")
          .setHtmlDescription("template1 desc")
          .setSeverity(Severity.MAJOR)
          .setTemplate(true)
          .createParam("format")
          .setDefaultValue("csv")
          .setType(RuleParamType.STRING)
          .setDescription("format parameter");
      }
    };
    register(rules);
    Rule templateRule = ruleIndex.getByKey(RuleKey.of("xoo", "T1"));

    // Create custom rule
    RuleKey customRuleKey = TESTER.get(RuleCreator.class).create(NewRule.createForCustomRule("CUSTOM_RULE", templateRule.key())
      .setName("My custom")
      .setHtmlDescription("Some description")
      .setSeverity(Severity.MAJOR)
      .setStatus(RuleStatus.READY)
      .setParameters(ImmutableMap.of("format", "txt")));
    assertThat(ruleIndex.getByKey(customRuleKey).status()).isEqualTo(RuleStatus.READY);

    // Restart without template
    register(null);

    // Verify custom rule is removed
    assertThat(ruleIndex.getByKey(templateRule.key()).status()).isEqualTo(RuleStatus.REMOVED);
    assertThat(ruleIndex.getByKey(customRuleKey).status()).isEqualTo(RuleStatus.REMOVED);

    // Re-install template
    register(rules);
    assertThat(ruleIndex.getByKey(templateRule.key()).status()).isEqualTo(RuleStatus.READY);
    assertThat(ruleIndex.getByKey(customRuleKey).status()).isEqualTo(RuleStatus.READY);
  }

  @Test
  public void do_not_disable_manual_rules() {
    // Create manual rule
    RuleKey manualRuleKey = TESTER.get(RuleCreator.class).create(NewRule.createForManualRule("MANUAL_RULE")
      .setName("My manual")
      .setHtmlDescription("Some description"));
    dbSession.commit();
    dbSession.clearCache();
    assertThat(ruleIndex.getByKey(manualRuleKey).status()).isEqualTo(RuleStatus.READY);

    // Restart
    register(null);

    // Verify manual rule is still ready
    assertThat(ruleIndex.getByKey(manualRuleKey).status()).isEqualTo(RuleStatus.READY);
  }

  interface Rules {
    void init(RulesDefinition.NewRepository repository);
  }

  public static class XooRulesDefinition implements RulesDefinition {
    private Rules rules = null;

    void set(@Nullable Rules rules) {
      this.rules = rules;
    }

    @Override
    public void define(Context context) {
      if (rules != null) {
        NewRepository repository = context.createRepository("xoo", ServerTester.Xoo.KEY).setName("Xoo Repo");
        rules.init(repository);
        repository.done();
      }
    }
  }

}
TOP

Related Classes of org.sonar.server.rule.RegisterRulesMediumTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.