Package org.sonar.server.rule.index

Source Code of org.sonar.server.rule.index.RuleIndexMediumTest

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

import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import org.apache.commons.lang.time.DateUtils;
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.core.qualityprofile.db.ActiveRuleDto;
import org.sonar.core.qualityprofile.db.QualityProfileDto;
import org.sonar.core.rule.RuleDto;
import org.sonar.core.rule.RuleParamDto;
import org.sonar.core.technicaldebt.db.CharacteristicDto;
import org.sonar.server.activity.SearchMediumTest;
import org.sonar.server.debt.DebtTesting;
import org.sonar.server.qualityprofile.ActiveRule;
import org.sonar.server.qualityprofile.QProfileTesting;
import org.sonar.server.rule.Rule;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.rule.db.RuleDao;
import org.sonar.server.search.FacetValue;
import org.sonar.server.search.QueryContext;
import org.sonar.server.search.Result;

import javax.annotation.Nullable;

import java.util.*;

import static com.google.common.collect.Lists.newArrayList;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;

public class RuleIndexMediumTest extends SearchMediumTest {

  RuleDao dao = tester.get(RuleDao.class);
  RuleIndex index = tester.get(RuleIndex.class);

  @Test
  public void getByKey() throws InterruptedException {
    RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("javascript", "S001"));
    dao.insert(dbSession, ruleDto);
    dbSession.commit();

    Rule rule = index.getByKey(RuleKey.of("javascript", "S001"));

    assertThat(rule.htmlDescription()).isEqualTo(ruleDto.getDescription());
    assertThat(rule.key()).isEqualTo(ruleDto.getKey());

    assertThat(rule.debtRemediationFunction().type().name())
      .isEqualTo(ruleDto.getRemediationFunction());

    assertThat(Sets.newHashSet(rule.tags())).isEqualTo(ruleDto.getTags());
    assertThat(Sets.newHashSet(rule.systemTags())).isEqualTo(ruleDto.getSystemTags());
  }

  @Test
  public void getByKey_null_if_not_found() throws InterruptedException {
    Rule rule = index.getNullableByKey(RuleKey.of("javascript", "unknown"));

    assertThat(rule).isNull();
  }

  @Test
  public void global_facet_on_repositories_and_tags() {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("php", "S001"))
      .setSystemTags(ImmutableSet.of("sysTag")))
      .setTags(ImmutableSet.<String>of());
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("php", "S002"))
      .setSystemTags(ImmutableSet.<String>of()))
      .setTags(ImmutableSet.of("tag1"));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("javascript", "S002"))
      .setTags(ImmutableSet.of("tag1", "tag2")))
      .setSystemTags(ImmutableSet.<String>of());
    dbSession.commit();

    // should not have any facet!
    RuleQuery query = new RuleQuery();
    Result result = index.search(query, new QueryContext());
    assertThat(result.getFacets()).isEmpty();

    // should not have any facet on non matching query!
    result = index.search(new RuleQuery().setQueryText("aeiou"), new QueryContext().addFacets(Arrays.asList("repositories")));
    assertThat(result.getFacets()).isEmpty();

    // Repositories Facet is preset
    result = index.search(query, new QueryContext().addFacets(Arrays.asList("repositories", "tags")));
    assertThat(result.getFacets()).isNotNull();
    assertThat(result.getFacets()).hasSize(3);

    // Verify the value of a given facet
    Collection<FacetValue> repoFacets = result.getFacetValues("repositories");
    assertThat(repoFacets).hasSize(2);
    assertThat(Iterables.get(repoFacets, 0).getKey()).isEqualTo("php");
    assertThat(Iterables.get(repoFacets, 0).getValue()).isEqualTo(2);
    assertThat(Iterables.get(repoFacets, 1).getKey()).isEqualTo("javascript");
    assertThat(Iterables.get(repoFacets, 1).getValue()).isEqualTo(1);

    // Check that tag facet has both Tags and SystemTags values
    Collection<FacetValue> tagFacet = result.getFacetValues("tags");
    assertThat(tagFacet).hasSize(3);
    assertThat(Iterables.get(tagFacet, 0).getKey()).isEqualTo("tag1");
    assertThat(Iterables.get(tagFacet, 0).getValue()).isEqualTo(2);
  }

  @Test
  public void return_all_doc_fields_by_default() {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("javascript", "S001")));
    dbSession.commit();

    QueryContext options = new QueryContext().setFieldsToReturn(null);
    Result<Rule> results = index.search(new RuleQuery(), options);
    assertThat(results.getHits()).hasSize(1);
    Rule hit = Iterables.getFirst(results.getHits(), null);
    assertThat(hit.key()).isNotNull();
    assertThat(hit.htmlDescription()).isNotNull();
    assertThat(hit.name()).isNotNull();

    options = new QueryContext().setFieldsToReturn(Collections.<String>emptyList());
    results = index.search(new RuleQuery(), options);
    assertThat(results.getHits()).hasSize(1);
    hit = Iterables.getFirst(results.getHits(), null);
    assertThat(hit.key()).isNotNull();
    assertThat(hit.htmlDescription()).isNotNull();
    assertThat(hit.name()).isNotNull();
  }

  @Test
  public void select_doc_fields_to_return() {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("javascript", "S001")));
    dbSession.commit();

    QueryContext options = new QueryContext();
    options.addFieldsToReturn(RuleNormalizer.RuleField.LANGUAGE.field(), RuleNormalizer.RuleField.STATUS.field());
    Result<Rule> results = index.search(new RuleQuery(), options);
    assertThat(results.getHits()).hasSize(1);

    Rule hit = Iterables.getFirst(results.getHits(), null);
    assertThat(hit.language()).isEqualTo("js");
    assertThat(hit.status()).isEqualTo(RuleStatus.READY);

    try {
      hit.htmlDescription();
      fail();
    } catch (IllegalStateException e) {
      assertThat(e).hasMessage("Field htmlDesc not specified in query options");
    }
  }

  @Test
  public void search_name_by_query() {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("javascript", "S001"))
      .setName("testing the partial match and matching of rule"));
    dbSession.commit();

    // substring
    RuleQuery query = new RuleQuery().setQueryText("test");
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);

    // substring
    query = new RuleQuery().setQueryText("partial match");
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);

    // case-insensitive
    query = new RuleQuery().setQueryText("TESTING");
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);

    // not found
    query = new RuleQuery().setQueryText("not present");
    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();
  }

  @Test
  public void search_key_by_query() {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("javascript", "X001")));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("cobol", "X001")));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("php", "S002")));
    dbSession.commit();

    // key
    RuleQuery query = new RuleQuery().setQueryText("X001");
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);

    // partial key does not match
    query = new RuleQuery().setQueryText("X00");
    // TODO fix non-partial match for Key search
    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();

    // repo:key -> nice-to-have !
    query = new RuleQuery().setQueryText("javascript:X001");
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
  }

  @Test
  public void filter_by_key() {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("javascript", "X001")));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("cobol", "X001")));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("php", "S002")));
    dbSession.commit();

    // key
    RuleQuery query = new RuleQuery().setKey(RuleKey.of("javascript", "X001").toString());
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);

    // partial key does not match
    query = new RuleQuery().setKey("X001");
    // TODO fix non-partial match for Key search
    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();
  }

  @Test
  public void search_all_rules() throws InterruptedException {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("javascript", "S001")));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S002")));
    dbSession.commit();

    Result results = index.search(new RuleQuery(), new QueryContext());

    assertThat(results.getTotal()).isEqualTo(2);
    assertThat(results.getHits()).hasSize(2);
  }

  @Test
  public void scroll_all_rules() throws InterruptedException {
    int max = 100;
    for (int i = 0; i < max; i++) {
      dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "scroll_" + i)));
    }
    dbSession.commit();

    Result results = index.search(new RuleQuery(), new QueryContext().setScroll(true));

    assertThat(results.getTotal()).isEqualTo(max);
    assertThat(results.getHits()).hasSize(0);

    Iterator<Rule> it = results.scroll();
    int count = 0;
    while (it.hasNext()) {
      count++;
      it.next();
    }
    assertThat(count).isEqualTo(max);

  }

  @Test
  public void search_by_has_debt_characteristic() throws InterruptedException {
    CharacteristicDto char1 = DebtTesting.newCharacteristicDto("c1")
      .setEnabled(true)
      .setName("char1");
    db.debtCharacteristicDao().insert(char1, dbSession);
    dbSession.commit();

    CharacteristicDto char11 = DebtTesting.newCharacteristicDto("c11")
      .setEnabled(true)
      .setName("char11")
      .setParentId(char1.getId());
    db.debtCharacteristicDao().insert(char11, dbSession);

    // Rule with default characteristic
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("findbugs", "S001"))
      .setSubCharacteristicId(null)
      .setRemediationFunction(null)
      .setDefaultSubCharacteristicId(char11.getId())
      .setDefaultRemediationFunction("LINEAR").setDefaultRemediationCoefficient("2h"));
    // Rule with overridden characteristic
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("pmd", "S002"))
      .setSubCharacteristicId(char11.getId())
      .setRemediationFunction("LINEAR").setRemediationCoefficient("2h")
      .setDefaultSubCharacteristicId(null)
      .setDefaultRemediationFunction(null));
    dbSession.commit();

    // 0. assert base case
    assertThat(index.search(new RuleQuery(), new QueryContext()).getTotal()).isEqualTo(2);
    assertThat(db.debtCharacteristicDao().selectCharacteristics()).hasSize(2);

    // 1. assert hasSubChar filter
    assertThat(index.search(new RuleQuery().setHasDebtCharacteristic(true), new QueryContext()).getTotal())
      .isEqualTo(2);
  }

  @Test
  public void search_by_any_of_repositories() {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("findbugs", "S001")));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("pmd", "S002")));
    dbSession.commit();

    RuleQuery query = new RuleQuery().setRepositories(Arrays.asList("checkstyle", "pmd"));
    Result<Rule> results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(1);
    assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");

    // no results
    query = new RuleQuery().setRepositories(Arrays.asList("checkstyle"));
    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();

    // empty list => no filter
    query = new RuleQuery().setRepositories(Collections.<String>emptyList());
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
  }

  @Test
  public void search_by_any_of_languages() throws InterruptedException {
    dao.insert(dbSession,
      RuleTesting.newDto(RuleKey.of("java", "S001")).setLanguage("java"),
      RuleTesting.newDto(RuleKey.of("javascript", "S002")).setLanguage("js"));
    dbSession.commit();

    RuleQuery query = new RuleQuery().setLanguages(Arrays.asList("cobol", "js"));
    Result<Rule> results = index.search(query, new QueryContext());

    assertThat(results.getHits()).hasSize(1);
    assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");

    // no results
    query = new RuleQuery().setLanguages(Arrays.asList("cpp"));
    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();

    // empty list => no filter
    query = new RuleQuery().setLanguages(Collections.<String>emptyList());
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);

    // null list => no filter
    query = new RuleQuery().setLanguages(null);
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
  }

  @Test
  public void search_by_characteristics() throws InterruptedException {
    CharacteristicDto char1 = DebtTesting.newCharacteristicDto("RELIABILITY");
    db.debtCharacteristicDao().insert(char1, dbSession);

    CharacteristicDto char11 = DebtTesting.newCharacteristicDto("SOFT_RELIABILITY")
      .setParentId(char1.getId());
    db.debtCharacteristicDao().insert(char11, dbSession);
    dbSession.commit();

    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001"))
      .setSubCharacteristicId(char11.getId()));

    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("javascript", "S002")));

    dbSession.commit();
    dbSession.clearCache();

    RuleQuery query;
    Result<Rule> results;

    // 0. we have 2 rules in index
    results = index.search(new RuleQuery(), new QueryContext());
    assertThat(results.getHits()).hasSize(2);

    // filter by non-subChar
    query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of("toto"));
    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();

    // filter by subChar
    query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char11.getKey()));
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);

    // filter by Char
    query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char1.getKey()));
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);

    // filter by Char and SubChar
    query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char11.getKey(), char1.getKey()));
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);

    // match by Char
    query = new RuleQuery().setQueryText(char1.getKey());
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);

    // match by SubChar
    query = new RuleQuery().setQueryText(char11.getKey());
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);

    // match by SubChar & Char
    query = new RuleQuery().setQueryText(char11.getKey() + " " + char1.getKey());
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
  }

  @Test
  public void search_by_characteristics_with_default_and_overridden_char() throws InterruptedException {
    CharacteristicDto char1 = DebtTesting.newCharacteristicDto("RELIABILITY");
    db.debtCharacteristicDao().insert(char1, dbSession);

    CharacteristicDto char11 = DebtTesting.newCharacteristicDto("SOFT_RELIABILITY")
      .setParentId(char1.getId());
    db.debtCharacteristicDao().insert(char11, dbSession);
    dbSession.commit();

    CharacteristicDto char2 = DebtTesting.newCharacteristicDto("TESTABILITY");
    db.debtCharacteristicDao().insert(char2, dbSession);

    CharacteristicDto char21 = DebtTesting.newCharacteristicDto("UNIT_TESTABILITY")
      .setParentId(char2.getId());
    db.debtCharacteristicDao().insert(char21, dbSession);
    dbSession.commit();

    // Rule with only default sub characteristic -> should be find by char11 and char1
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001"))
      .setSubCharacteristicId(char11.getId())
      .setDefaultSubCharacteristicId(null));

    // Rule with only sub characteristic -> should be find by char11 and char1
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S002"))
      .setSubCharacteristicId(null)
      .setDefaultSubCharacteristicId(char11.getId()));

    // Rule with both default sub characteristic and overridden sub characteristic -> should only be find by char21 and char2
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S003"))
      .setSubCharacteristicId(char21.getId()))
      .setDefaultSubCharacteristicId(char11.getId());

    // Rule with both default sub characteristic and overridden sub characteristic and with same values -> should be find by char11 and char1
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S004"))
      .setSubCharacteristicId(char11.getId()))
      .setDefaultSubCharacteristicId(char11.getId());

    dbSession.commit();
    dbSession.clearCache();

    RuleQuery query;
    Result<Rule> results;

    // 0. we have 4 rules in index
    results = index.search(new RuleQuery(), new QueryContext());
    assertThat(results.getHits()).hasSize(4);

    // filter by subChar
    query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char11.getKey()));
    assertThat(ruleKeys(index.search(query, new QueryContext()).getHits())).containsOnly("S001", "S002", "S004");

    query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char21.getKey()));
    assertThat(ruleKeys(index.search(query, new QueryContext()).getHits())).containsOnly("S003");

    // filter by Char
    query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char1.getKey()));
    assertThat(ruleKeys(index.search(query, new QueryContext()).getHits())).containsOnly("S001", "S002", "S004");

    query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char2.getKey()));
    assertThat(ruleKeys(index.search(query, new QueryContext()).getHits())).containsOnly("S003");

    // filter by Char and SubChar
    query = new RuleQuery().setDebtCharacteristics(ImmutableSet.of(char11.getKey(), char1.getKey(), char2.getKey(), char21.getKey()));
    assertThat(ruleKeys(index.search(query, new QueryContext()).getHits())).containsOnly("S001", "S002", "S003", "S004");
  }

  @Test
  public void search_by_any_of_severities() throws InterruptedException {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001")).setSeverity(Severity.BLOCKER));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S002")).setSeverity(Severity.INFO));
    dbSession.commit();

    RuleQuery query = new RuleQuery().setSeverities(Arrays.asList(Severity.INFO, Severity.MINOR));
    Result<Rule> results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(1);
    assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");

    // no results
    query = new RuleQuery().setSeverities(Arrays.asList(Severity.MINOR));
    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();

    // empty list => no filter
    query = new RuleQuery().setSeverities(Collections.<String>emptyList());
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);

    // null list => no filter
    query = new RuleQuery().setSeverities(null);
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
  }

  @Test
  public void search_by_any_of_statuses() throws InterruptedException {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001")).setStatus(RuleStatus.BETA));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S002")).setStatus(RuleStatus.READY));
    dbSession.commit();

    RuleQuery query = new RuleQuery().setStatuses(Arrays.asList(RuleStatus.DEPRECATED, RuleStatus.READY));
    Result<Rule> results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(1);
    assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");

    // no results
    query = new RuleQuery().setStatuses(Arrays.asList(RuleStatus.DEPRECATED));
    assertThat(index.search(query, new QueryContext()).getHits()).isEmpty();

    // empty list => no filter
    query = new RuleQuery().setStatuses(Collections.<RuleStatus>emptyList());
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);

    // null list => no filter
    query = new RuleQuery().setStatuses(null);
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
  }

  @Test
  public void sort_by_name() {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001")).setName("abcd"));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S002")).setName("ABC"));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S003")).setName("FGH"));
    dbSession.commit();

    // ascending
    RuleQuery query = new RuleQuery().setSortField(RuleNormalizer.RuleField.NAME);
    Result<Rule> results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(3);
    assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");
    assertThat(Iterables.getLast(results.getHits(), null).key().rule()).isEqualTo("S003");

    // descending
    query = new RuleQuery().setSortField(RuleNormalizer.RuleField.NAME).setAscendingSort(false);
    results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(3);
    assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S003");
    assertThat(Iterables.getLast(results.getHits(), null).key().rule()).isEqualTo("S002");
  }

  @Test
  public void fail_sort_by_language() throws InterruptedException {
    try {
      // Sorting on a field not tagged as sortable
      new RuleQuery().setSortField(RuleNormalizer.RuleField.LANGUAGE);
      fail();
    } catch (IllegalStateException e) {
      assertThat(e).hasMessage("Field 'lang' is not sortable");
    }
  }

  @Test
  public void search_by_profile() throws InterruptedException {
    QualityProfileDto qualityProfileDto1 = QProfileTesting.newXooP1();
    QualityProfileDto qualityProfileDto2 = QProfileTesting.newXooP2();
    db.qualityProfileDao().insert(dbSession, qualityProfileDto1, qualityProfileDto2);

    RuleDto rule1 = RuleTesting.newXooX1();
    RuleDto rule2 = RuleTesting.newXooX2();
    RuleDto rule3 = RuleTesting.newXooX3();
    dao.insert(dbSession, rule1, rule2, rule3);

    db.activeRuleDao().insert(
      dbSession,
      ActiveRuleDto.createFor(qualityProfileDto1, rule1).setSeverity("BLOCKER"),
      ActiveRuleDto.createFor(qualityProfileDto2, rule1).setSeverity("BLOCKER"),
      ActiveRuleDto.createFor(qualityProfileDto1, rule2).setSeverity("BLOCKER"));
    dbSession.commit();
    dbSession.clearCache();

    // 1. get all active rules.
    Result<Rule> result = index.search(new RuleQuery().setActivation(true),
      new QueryContext());
    assertThat(result.getHits()).hasSize(2);

    // 2. get all inactive rules.
    result = index.search(new RuleQuery().setActivation(false),
      new QueryContext());
    assertThat(result.getHits()).hasSize(1);
    assertThat(result.getHits().get(0).name()).isEqualTo(rule3.getName());

    // 3. get all rules not active on profile
    index.search(new RuleQuery().setActivation(false).setQProfileKey(qualityProfileDto2.getKey()),
      new QueryContext());
    // TODO
    assertThat(result.getHits()).hasSize(1);

    // 4. get all active rules on profile
    result = index.search(new RuleQuery().setActivation(true)
        .setQProfileKey(qualityProfileDto2.getKey()),
      new QueryContext());
    assertThat(result.getHits()).hasSize(1);
    assertThat(result.getHits().get(0).name()).isEqualTo(rule1.getName());

  }

  @Test
  public void search_by_profile_and_inheritance() throws InterruptedException {
    QualityProfileDto qualityProfileDto1 = QProfileTesting.newXooP1();
    QualityProfileDto qualityProfileDto2 = QProfileTesting.newXooP2().setParentKee(QProfileTesting.XOO_P1_KEY);
    db.qualityProfileDao().insert(dbSession, qualityProfileDto1, qualityProfileDto2);

    RuleDto rule1 = RuleTesting.newDto(RuleKey.of("xoo", "S001"));
    RuleDto rule2 = RuleTesting.newDto(RuleKey.of("xoo", "S002"));
    RuleDto rule3 = RuleTesting.newDto(RuleKey.of("xoo", "S003"));
    RuleDto rule4 = RuleTesting.newDto(RuleKey.of("xoo", "S004"));
    dao.insert(dbSession, rule1, rule2, rule3, rule4);

    db.activeRuleDao().insert(
      dbSession,
      ActiveRuleDto.createFor(qualityProfileDto1, rule1)
        .setSeverity("BLOCKER"),
      ActiveRuleDto.createFor(qualityProfileDto1, rule2)
        .setSeverity("BLOCKER"),
      ActiveRuleDto.createFor(qualityProfileDto1, rule3)
        .setSeverity("BLOCKER"),

      ActiveRuleDto.createFor(qualityProfileDto2, rule1)
        .setSeverity("MINOR")
        .setInheritance(ActiveRule.Inheritance.INHERITED.name()),
      ActiveRuleDto.createFor(qualityProfileDto2, rule2)
        .setSeverity("BLOCKER")
        .setInheritance(ActiveRule.Inheritance.OVERRIDES.name()),
      ActiveRuleDto.createFor(qualityProfileDto2, rule3)
        .setSeverity("BLOCKER")
        .setInheritance(ActiveRule.Inheritance.INHERITED.name())
    );

    dbSession.commit();

    // 0. get all rules
    Result<Rule> result = index.search(new RuleQuery(),
      new QueryContext());
    assertThat(result.getHits()).hasSize(4);

    // 1. get all active rules
    result = index.search(new RuleQuery().setActivation(true),
      new QueryContext());
    assertThat(result.getHits()).hasSize(3);

    // 2. get all inactive rules.
    result = index.search(new RuleQuery().setActivation(false),
      new QueryContext());
    assertThat(result.getHits()).hasSize(1);
    assertThat(result.getHits().get(0).name()).isEqualTo(rule4.getName());

    // 3. get Inherited Rules on profile1
    result = index.search(new RuleQuery().setActivation(true)
        .setQProfileKey(qualityProfileDto1.getKey())
        .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.INHERITED.name())),
      new QueryContext()
    );
    assertThat(result.getHits()).hasSize(0);

    // 4. get Inherited Rules on profile2
    result = index.search(new RuleQuery().setActivation(true)
        .setQProfileKey(qualityProfileDto2.getKey())
        .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.INHERITED.name())),
      new QueryContext()
    );
    assertThat(result.getHits()).hasSize(2);

    // 5. get Overridden Rules on profile1
    result = index.search(new RuleQuery().setActivation(true)
        .setQProfileKey(qualityProfileDto1.getKey())
        .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.OVERRIDES.name())),
      new QueryContext()
    );
    assertThat(result.getHits()).hasSize(0);

    // 6. get Overridden Rules on profile2
    result = index.search(new RuleQuery().setActivation(true)
        .setQProfileKey(qualityProfileDto2.getKey())
        .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.OVERRIDES.name())),
      new QueryContext()
    );
    assertThat(result.getHits()).hasSize(1);

    // 7. get Inherited AND Overridden Rules on profile1
    result = index.search(new RuleQuery().setActivation(true)
        .setQProfileKey(qualityProfileDto1.getKey())
        .setInheritance(ImmutableSet.of(
          ActiveRule.Inheritance.INHERITED.name(), ActiveRule.Inheritance.OVERRIDES.name())),
      new QueryContext()
    );
    assertThat(result.getHits()).hasSize(0);

    // 8. get Inherited AND Overridden Rules on profile2
    result = index.search(new RuleQuery().setActivation(true)
        .setQProfileKey(qualityProfileDto2.getKey())
        .setInheritance(ImmutableSet.of(
          ActiveRule.Inheritance.INHERITED.name(), ActiveRule.Inheritance.OVERRIDES.name())),
      new QueryContext()
    );
    assertThat(result.getHits()).hasSize(3);
  }

  @Test
  public void complex_param_value() throws InterruptedException {
    String value = "//expression[primary/qualifiedIdentifier[count(IDENTIFIER) = 2]/IDENTIFIER[2]/@tokenValue = 'firstOf' and primary/identifierSuffix/arguments/expression[not(primary) or primary[not(qualifiedIdentifier) or identifierSuffix]]]";

    QualityProfileDto profile = QProfileTesting.newXooP1();
    db.qualityProfileDao().insert(dbSession, profile);

    RuleDto rule = RuleTesting.newXooX1();
    dao.insert(dbSession, rule);

    RuleParamDto param = RuleParamDto.createFor(rule)
      .setName("testing")
      .setType("STRING")
      .setDefaultValue(value);
    dao.addRuleParam(dbSession, rule, param);

    dbSession.commit();

    assertThat(index.getByKey(rule.getKey()).params()).hasSize(1);
    assertThat(index.getByKey(rule.getKey()).params().get(0).defaultValue()).isEqualTo(value);
  }

  @Test
  public void search_by_tag() throws InterruptedException {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001")).setTags(ImmutableSet.of("tag1")));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S002")).setTags(ImmutableSet.of("tag2")));
    dbSession.commit();

    // find all
    RuleQuery query = new RuleQuery();
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);

    // tag1 in query
    query = new RuleQuery().setQueryText("tag1");
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
    assertThat(Iterables.getFirst(index.search(query, new QueryContext()).getHits(), null).tags()).containsExactly("tag1");

    // tag1 and tag2 in query
    query = new RuleQuery().setQueryText("tag1 tag2");
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);

    // tag2 in filter
    query = new RuleQuery().setTags(ImmutableSet.of("tag2"));
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
    assertThat(Iterables.getFirst(index.search(query, new QueryContext()).getHits(), null).tags()).containsExactly("tag2");

    // tag2 in filter and tag1 tag2 in query
    query = new RuleQuery().setTags(ImmutableSet.of("tag2")).setQueryText("tag1");
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(0);

    // tag2 in filter and tag1 in query
    query = new RuleQuery().setTags(ImmutableSet.of("tag2")).setQueryText("tag1 tag2");
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(1);
    assertThat(Iterables.getFirst(index.search(query, new QueryContext()).getHits(), null).tags()).containsExactly("tag2");

    // null list => no filter
    query = new RuleQuery().setTags(Collections.<String>emptySet());
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);

    // null list => no filter
    query = new RuleQuery().setTags(null);
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
  }

  @Test
  public void search_by_is_template() throws InterruptedException {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001")).setIsTemplate(false));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S002")).setIsTemplate(true));
    dbSession.commit();

    // find all
    RuleQuery query = new RuleQuery();
    Result<Rule> results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(2);

    // Only template
    query = new RuleQuery().setIsTemplate(true);
    results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(1);
    assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");
    assertThat(Iterables.getFirst(results.getHits(), null).isTemplate()).isTrue();

    // Only not template
    query = new RuleQuery().setIsTemplate(false);
    results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(1);
    assertThat(Iterables.getFirst(results.getHits(), null).isTemplate()).isFalse();
    assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S001");

    // null => no filter
    query = new RuleQuery().setIsTemplate(null);
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
  }

  @Test
  public void search_by_template_key() throws InterruptedException {
    RuleDto templateRule = RuleTesting.newDto(RuleKey.of("java", "S001")).setIsTemplate(true);
    dao.insert(dbSession, templateRule);
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001_MY_CUSTOM")).setTemplateId(templateRule.getId()));
    dbSession.commit();

    // find all
    RuleQuery query = new RuleQuery();
    Result<Rule> results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(2);

    // Only custom rule
    query = new RuleQuery().setTemplateKey("java:S001");
    results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(1);
    assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S001_MY_CUSTOM");
    assertThat(Iterables.getFirst(results.getHits(), null).templateKey()).isEqualTo(RuleKey.of("java", "S001"));

    // null => no filter
    query = new RuleQuery().setTemplateKey(null);
    assertThat(index.search(query, new QueryContext()).getHits()).hasSize(2);
  }

  @Test
  public void search_by_template_key_with_params() throws InterruptedException {
    RuleDto templateRule = RuleTesting.newDto(RuleKey.of("java", "S001")).setIsTemplate(true);
    RuleParamDto ruleParamDto = RuleParamDto.createFor(templateRule).setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(".*");
    dao.insert(dbSession, templateRule);
    dao.addRuleParam(dbSession, templateRule, ruleParamDto);

    RuleDto customRule = RuleTesting.newDto(RuleKey.of("java", "S001_MY_CUSTOM")).setTemplateId(templateRule.getId());
    RuleParamDto customRuleParam = RuleParamDto.createFor(customRule).setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue("a.*");
    dao.insert(dbSession, customRule);
    dao.addRuleParam(dbSession, customRule, customRuleParam);
    dbSession.commit();

    // find all
    RuleQuery query = new RuleQuery();
    Result<Rule> results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(2);

    // get params
    assertThat(index.getByKey(templateRule.getKey()).params()).hasSize(1);
    assertThat(index.getByKey(customRule.getKey()).params()).hasSize(1);
  }

  @Test
  public void show_custom_rule() throws InterruptedException {
    RuleDto templateRule = RuleTesting.newDto(RuleKey.of("java", "S001")).setIsTemplate(true);
    dao.insert(dbSession, templateRule);
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001_MY_CUSTOM")).setTemplateId(templateRule.getId()));
    dbSession.commit();

    // find all
    RuleQuery query = new RuleQuery();
    Result<Rule> results = index.search(query, new QueryContext());
    assertThat(results.getHits()).hasSize(2);

    // find custom rule
    assertThat(index.getByKey(RuleKey.of("java", "S001_MY_CUSTOM")).templateKey()).isEqualTo(RuleKey.of("java", "S001"));
  }

  @Test
  public void paging() {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001")));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S002")));
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S003")));
    dbSession.commit();

    // from 0 to 1 included
    QueryContext options = new QueryContext();
    options.setOffset(0).setLimit(2);
    Result results = index.search(new RuleQuery(), options);
    assertThat(results.getTotal()).isEqualTo(3);
    assertThat(results.getHits()).hasSize(2);

    // from 0 to 9 included
    options.setOffset(0).setLimit(10);
    results = index.search(new RuleQuery(), options);
    assertThat(results.getTotal()).isEqualTo(3);
    assertThat(results.getHits()).hasSize(3);

    // from 2 to 11 included
    options.setOffset(2).setLimit(10);
    results = index.search(new RuleQuery(), options);
    assertThat(results.getTotal()).isEqualTo(3);
    assertThat(results.getHits()).hasSize(1);

    // from 2 to 11 included
    options.setOffset(2).setLimit(0);
    results = index.search(new RuleQuery(), options);
    assertThat(results.getTotal()).isEqualTo(3);
    assertThat(results.getHits()).hasSize(0);
  }

  @Test
  public void available_since() throws InterruptedException {
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S001")));
    dbSession.commit();
    Thread.sleep(500);
    Date since = new Date();
    dao.insert(dbSession, RuleTesting.newDto(RuleKey.of("java", "S002")));
    dbSession.commit();

    // 0. find all rules;
    assertThat(index.search(new RuleQuery(), new QueryContext()).getHits()).hasSize(2);

    // 1. find all rules available since a date;
    RuleQuery availableSinceQuery = new RuleQuery()
      .setAvailableSince(since);
    List<Rule> hits = index.search(availableSinceQuery, new QueryContext()).getHits();
    assertThat(hits).hasSize(1);
    assertThat(hits.get(0).key()).isEqualTo(RuleKey.of("java", "S002"));

    // 2. find no new rules since tomorrow.
    RuleQuery availableSinceNowQuery = new RuleQuery()
      .setAvailableSince(DateUtils.addDays(since, 1));
    assertThat(index.search(availableSinceNowQuery, new QueryContext()).getHits()).hasSize(0);
  }

  @Test
  public void scroll_byIds() throws Exception {
    Set<Integer> ids = new HashSet<Integer>();
    for (int i = 0; i < 150; i++) {
      RuleDto rule = RuleTesting.newDto(RuleKey.of("scroll", "r_" + i));
      dao.insert(dbSession, rule);
      dbSession.commit();
      ids.add(rule.getId());
    }
    List<Rule> rules = index.getByIds(ids);
    assertThat(rules).hasSize(ids.size());
  }

  @Test
  public void search_protected_chars() throws InterruptedException {
    String nameWithProtectedChars = "ja#va&sc\"r:ipt";

    RuleDto ruleDto = RuleTesting.newXooX1().setName(nameWithProtectedChars);
    dao.insert(dbSession, ruleDto);
    dbSession.commit();

    Rule rule = index.getByKey(RuleTesting.XOO_X1);
    assertThat(rule.name()).isEqualTo(nameWithProtectedChars);

    RuleQuery protectedCharsQuery = new RuleQuery().setQueryText(nameWithProtectedChars);
    List<Rule> results = index.search(protectedCharsQuery, new QueryContext()).getHits();
    assertThat(results).hasSize(1);
    assertThat(results.get(0).key()).isEqualTo(RuleTesting.XOO_X1);
  }

  @Test
  public void sticky_facets() {

    Integer numberOfSystemTags = 2;
    dao.insert(dbSession,
      RuleTesting.newDto(RuleKey.of("xoo", "S001")).setLanguage("java").setTags(ImmutableSet.<String>of()),
      RuleTesting.newDto(RuleKey.of("xoo", "S002")).setLanguage("java").setTags(ImmutableSet.<String>of()),
      RuleTesting.newDto(RuleKey.of("xoo", "S003")).setLanguage("java").setTags(ImmutableSet.<String>of("T1", "T2")),
      RuleTesting.newDto(RuleKey.of("xoo", "S011")).setLanguage("cobol").setTags(ImmutableSet.<String>of()),
      RuleTesting.newDto(RuleKey.of("xoo", "S012")).setLanguage("cobol").setTags(ImmutableSet.<String>of()),
      RuleTesting.newDto(RuleKey.of("foo", "S013")).setLanguage("cobol").setTags(ImmutableSet.<String>of("T3", "T4")),
      RuleTesting.newDto(RuleKey.of("foo", "S111")).setLanguage("cpp").setTags(ImmutableSet.<String>of()),
      RuleTesting.newDto(RuleKey.of("foo", "S112")).setLanguage("cpp").setTags(ImmutableSet.<String>of()),
      RuleTesting.newDto(RuleKey.of("foo", "S113")).setLanguage("cpp").setTags(ImmutableSet.<String>of("T2", "T3")));
    dbSession.commit();

    // 0 assert Base
    assertThat(index.countAll()).isEqualTo(9);
    assertThat(index.search(new RuleQuery(), new QueryContext()).getHits()).hasSize(9);

    // 1 Facet with no filters at all
    Map<String, Collection<FacetValue>> facets = index.search(new RuleQuery(), new QueryContext().addFacets(Arrays.asList("languages", "repositories", "tags"))).getFacets();
    assertThat(facets.keySet()).hasSize(3);
    assertThat(facets.get(RuleIndex.FACET_LANGUAGES)).onProperty("key").containsOnly("cpp", "java", "cobol");
    assertThat(facets.get(RuleIndex.FACET_REPOSITORIES)).onProperty("key").containsOnly("xoo", "foo");
    assertThat(facets.get(RuleIndex.FACET_TAGS)).onProperty("key").containsOnly("systag1", "systag2", "T1", "T2", "T3", "T4");

    // 2 Facet with a language filter
    // -- lang facet should still have all language
    Result<Rule> result = index.search(new RuleQuery()
      .setLanguages(ImmutableList.<String>of("cpp"))
      , new QueryContext().addFacets(Arrays.asList("languages", "repositories", "tags")));
    assertThat(result.getHits()).hasSize(3);
    assertThat(result.getFacets()).hasSize(3);
    assertThat(result.getFacets().get(RuleIndex.FACET_LANGUAGES)).onProperty("key").containsOnly("cpp", "java", "cobol");

    // 3 facet with 2 filters
    // -- lang facet for tag T2
    // -- tag facet for lang cpp
    // -- repository for cpp & T2
    result = index.search(new RuleQuery()
      .setLanguages(ImmutableList.<String>of("cpp"))
      .setTags(ImmutableList.<String>of("T2"))
      , new QueryContext().addFacets(Arrays.asList("languages", "repositories", "tags")));
    assertThat(result.getHits()).hasSize(1);
    assertThat(result.getFacets().keySet()).hasSize(3);
    assertThat(result.getFacets().get(RuleIndex.FACET_LANGUAGES)).onProperty("key").containsOnly("cpp", "java");
    assertThat(result.getFacets().get(RuleIndex.FACET_REPOSITORIES)).onProperty("key").containsOnly("foo");
    assertThat(result.getFacets().get(RuleIndex.FACET_TAGS)).onProperty("key").containsOnly("systag1", "systag2", "T2", "T3");

    // 4 facet with 2 filters
    // -- lang facet for tag T2
    // -- tag facet for lang cpp & java
    // -- repository for (cpp || java) & T2
    result = index.search(new RuleQuery()
      .setLanguages(ImmutableList.<String>of("cpp", "java"))
      .setTags(ImmutableList.<String>of("T2"))
      , new QueryContext().addFacets(Arrays.asList("languages", "repositories", "tags")));
    assertThat(result.getHits()).hasSize(2);
    assertThat(result.getFacets().keySet()).hasSize(3);
    assertThat(result.getFacets().get(RuleIndex.FACET_LANGUAGES)).onProperty("key").containsOnly("cpp", "java");
    assertThat(result.getFacets().get(RuleIndex.FACET_REPOSITORIES)).onProperty("key").containsOnly("foo", "xoo");
    assertThat(result.getFacets().get(RuleIndex.FACET_TAGS)).onProperty("key").containsOnly("systag1", "systag2", "T1", "T2", "T3");
  }

  private static List<String> ruleKeys(List<Rule> rules) {
    return newArrayList(Iterables.transform(rules, new Function<Rule, String>() {
      @Override
      public String apply(@Nullable Rule input) {
        return input != null ? input.key().rule() : null;
      }
    }));
  }
}
TOP

Related Classes of org.sonar.server.rule.index.RuleIndexMediumTest

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.