diff options
author | Jenkins CI <ci@sonarsource.com> | 2015-10-21 08:01:17 +0200 |
---|---|---|
committer | Jenkins CI <ci@sonarsource.com> | 2015-10-21 08:01:17 +0200 |
commit | df2b95020a82ed588d35526ff915ac2187c325da (patch) | |
tree | 965cf32dc362e2b205fd6cf7996646c332b27fa2 /server | |
parent | 187f501d31cba9ff220c44bbcd222768a4eee40e (diff) | |
parent | 5945ad454bcbac6bd7f1f6c9651daabeffe02f4f (diff) | |
download | sonarqube-df2b95020a82ed588d35526ff915ac2187c325da.tar.gz sonarqube-df2b95020a82ed588d35526ff915ac2187c325da.zip |
Automatic merge from branch-5.2
* origin/branch-5.2:
[maven-release-plugin] prepare for next development iteration
[maven-release-plugin] prepare release 5.2-RC3
Hack for IE - use mime type text/plain for api/qualityprofiles/create
fix quality profile deletion dialog on ie9
Fix some quality flaw
SONAR-6822 Rules search WS is not returning langName
SONAR-6822 Move search action tests to a dedicated test class
SONAR-6680 RuleRepository now load all rules at first call
SONAR-6680 add RuleDao.selectAll to be used by CE's RuleRepository
Fix quality flaws
fix select2 closing problem in the facet sidebar
Diffstat (limited to 'server')
39 files changed, 1063 insertions, 751 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java index 1273a1e2d4e..e2118173965 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java @@ -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 index 8f2443c5c7f..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleCacheLoader.java +++ /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"); - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleRepository.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleRepository.java index 57bd78c1e19..be6facd2640 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleRepository.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleRepository.java @@ -19,11 +19,29 @@ */ 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); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleRepositoryImpl.java index 63c96ab24b6..dd2935e58e5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleRepositoryImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleRepositoryImpl.java @@ -19,24 +19,92 @@ */ 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(); + } + } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadQualityProfilesStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadQualityProfilesStep.java index bf19a622dda..c7b73058510 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadQualityProfilesStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadQualityProfilesStep.java @@ -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; } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java index 56352214b12..706454ed545 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/es/BulkIndexer.java @@ -46,6 +46,8 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; +import static java.lang.String.format; + /** * Helper to bulk requests in an efficient way : * <ul> @@ -76,7 +78,7 @@ public class BulkIndexer implements Startable { public BulkIndexer(EsClient client, String indexName) { this.client = client; this.indexName = indexName; - this.progress = new ProgressLogger(String.format("Progress[BulkIndexer[%s]]", indexName), counter, LOGGER) + this.progress = new ProgressLogger(format("Progress[BulkIndexer[%s]]", indexName), counter, LOGGER) .setPluralLabel("requests"); this.concurrentRequests = Math.max(1, Runtime.getRuntime().availableProcessors() - 1); @@ -235,11 +237,7 @@ public class BulkIndexer implements Startable { for (BulkItemResponse item : response.getItems()) { if (item.isFailed()) { - StringBuilder sb = new StringBuilder(); - String msg = sb - .append("index [").append(item.getIndex()).append("], type [").append(item.getType()).append("], id [").append(item.getId()) - .append("], message [").append(item.getFailureMessage()).append("]").toString(); - LOGGER.error(msg); + LOGGER.error("index [{}], type [{}], id [{}], message [{}]", item.getIndex(), item.getType(), item.getId(), item.getFailureMessage()); } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java index 07b626edc24..0a40d32a3fd 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java @@ -19,6 +19,8 @@ */ package org.sonar.server.qualityprofile.ws; +import java.io.InputStream; +import java.io.OutputStreamWriter; import org.sonar.api.profiles.ProfileImporter; import org.sonar.api.resources.Languages; import org.sonar.api.server.ws.Request; @@ -27,17 +29,16 @@ import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService.NewAction; import org.sonar.api.utils.text.JsonWriter; import org.sonar.core.permission.GlobalPermissions; +import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.qualityprofile.QualityProfileDto; -import org.sonar.db.DbClient; +import org.sonar.server.plugins.MimeTypes; import org.sonar.server.qualityprofile.QProfileExporters; import org.sonar.server.qualityprofile.QProfileFactory; import org.sonar.server.qualityprofile.QProfileName; import org.sonar.server.qualityprofile.QProfileResult; import org.sonar.server.user.UserSession; -import java.io.InputStream; - public class CreateAction implements QProfileWsAction { private static final String PARAM_PROFILE_NAME = "name"; @@ -56,7 +57,7 @@ public class CreateAction implements QProfileWsAction { private final UserSession userSession; public CreateAction(DbClient dbClient, QProfileFactory profileFactory, QProfileExporters exporters, - Languages languages, ProfileImporter[] importers, UserSession userSession) { + Languages languages, ProfileImporter[] importers, UserSession userSession) { this.dbClient = dbClient; this.profileFactory = profileFactory; this.exporters = exporters; @@ -115,12 +116,29 @@ public class CreateAction implements QProfileWsAction { } } dbSession.commit(); - writeResult(response.newJsonWriter(), result); + + response.stream().setMediaType(guessMediaType(request)); + JsonWriter jsonWriter = JsonWriter.of(new OutputStreamWriter(response.stream().output())); + writeResult(jsonWriter, result); } finally { dbSession.close(); } } + private static String guessMediaType(Request request) { + if (request.getMediaType().contains("html")) { + // this is a hack for IE. + // The form which uploads files (for example PMD or Findbugs configuration files) opens a popup + // to download files if the response type header is application/json. Changing the response type to text/plain, + // even if response body is JSON, fixes the bug. + // This will be fixed in 5.3 when support of IE9/10 will be dropped in order to use + // more recent JS libs. + // We detect that caller is IE because it asks for application/html or text/html + return MimeTypes.TXT; + } + return request.getMediaType(); + } + private void writeResult(JsonWriter json, QProfileResult result) { String language = result.profile().getLanguage(); json.beginObject().name("profile").beginObject() @@ -151,7 +169,7 @@ public class CreateAction implements QProfileWsAction { json.endObject().close(); } - private String getBackupParamName(String importerKey) { + private static String getBackupParamName(String importerKey) { return String.format(PARAM_BACKUP_FORMAT, importerKey); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapping.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapping.java index 3e084ef6a27..449c52b7758 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapping.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleMapping.java @@ -21,12 +21,6 @@ package org.sonar.server.rule.ws; import com.google.common.base.Function; import com.google.common.collect.Maps; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import javax.annotation.CheckForNull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import org.sonar.api.resources.Language; import org.sonar.api.resources.Languages; import org.sonar.api.rule.RuleKey; @@ -47,6 +41,14 @@ import org.sonar.server.user.UserSession; import org.sonarqube.ws.Common; import org.sonarqube.ws.Rules; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + import static com.google.common.collect.FluentIterable.from; import static org.sonar.api.utils.DateUtils.formatDateTime; @@ -138,9 +140,11 @@ public class RuleMapping extends BaseMapping<RuleDoc, RuleMappingContext> { setParams(ruleResponse, ruleDoc, fieldsToReturn); setCreatedAt(ruleResponse, ruleDoc, fieldsToReturn); setDescriptionFields(ruleResponse, ruleDoc, fieldsToReturn); + setNotesFields(ruleResponse, ruleDoc, fieldsToReturn); setSeverity(ruleResponse, ruleDoc, fieldsToReturn); setInternalKey(ruleResponse, ruleDoc, fieldsToReturn); setLanguage(ruleResponse, ruleDoc, fieldsToReturn); + setLanguageName(ruleResponse, ruleDoc, fieldsToReturn); setIsTemplate(ruleResponse, ruleDoc, fieldsToReturn); setTemplateKey(ruleResponse, ruleDoc, fieldsToReturn); setDebtRemediationFunctionFields(ruleResponse, ruleDoc, fieldsToReturn); @@ -288,15 +292,18 @@ public class RuleMapping extends BaseMapping<RuleDoc, RuleMappingContext> { ruleResponse.setHtmlDesc(macroInterpreter.interpret(ruleDoc.htmlDescription())); } } + if (shouldReturnField(fieldsToReturn, RuleNormalizer.RuleField.MARKDOWN_DESCRIPTION) && ruleDoc.markdownDescription() != null) { + ruleResponse.setMdDesc(ruleDoc.markdownDescription()); + } + } + + private void setNotesFields(Rules.Rule.Builder ruleResponse, Rule ruleDoc, Set<String> fieldsToReturn) { if (shouldReturnField(fieldsToReturn, "htmlNote") && ruleDoc.markdownNote() != null) { ruleResponse.setHtmlNote(macroInterpreter.interpret(Markdown.convertToHtml(ruleDoc.markdownNote()))); } if (shouldReturnField(fieldsToReturn, "mdNote") && ruleDoc.markdownNote() != null) { ruleResponse.setMdNote(ruleDoc.markdownNote()); } - if (shouldReturnField(fieldsToReturn, RuleNormalizer.RuleField.MARKDOWN_DESCRIPTION) && ruleDoc.markdownDescription() != null) { - ruleResponse.setMdDesc(ruleDoc.markdownDescription()); - } if (shouldReturnField(fieldsToReturn, RuleNormalizer.RuleField.NOTE_LOGIN) && ruleDoc.noteLogin() != null) { ruleResponse.setNoteLogin(ruleDoc.noteLogin()); } @@ -314,13 +321,17 @@ public class RuleMapping extends BaseMapping<RuleDoc, RuleMappingContext> { } } - private void setLanguage(Rules.Rule.Builder ruleResponse, Rule ruleDoc, Set<String> fieldsToReturn) { + private static void setLanguage(Rules.Rule.Builder ruleResponse, Rule ruleDoc, Set<String> fieldsToReturn) { if (shouldReturnField(fieldsToReturn, RuleNormalizer.RuleField.LANGUAGE) && ruleDoc.language() != null) { ruleResponse.setLang(ruleDoc.language()); - Language language = languages.get(ruleDoc.language()); - if (language != null) { - ruleResponse.setLangName(language.getName()); - } + } + } + + private void setLanguageName(Rules.Rule.Builder ruleResponse, Rule ruleDoc, Set<String> fieldsToReturn) { + if (shouldReturnField(fieldsToReturn, "langName") && ruleDoc.language() != null) { + String languageKey = ruleDoc.language(); + Language language = languages.get(languageKey); + ruleResponse.setLangName(language == null ? languageKey : language.getName()); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/test/index/TestResultSetIterator.java b/server/sonar-server/src/main/java/org/sonar/server/test/index/TestResultSetIterator.java index e1ffd9d2e54..8c8316e5dbf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/test/index/TestResultSetIterator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/test/index/TestResultSetIterator.java @@ -55,10 +55,14 @@ import static org.sonar.server.test.index.TestIndexDefinition.TYPE; /** * Scroll over table FILE_SOURCES of test type and directly parse data required to - * populate the index sourcelines + * populate the index tests/test */ public class TestResultSetIterator extends ResultSetIterator<Row> { + private TestResultSetIterator(PreparedStatement stmt) throws SQLException { + super(stmt); + } + public static TestResultSetIterator create(DbClient dbClient, DbSession session, long afterDate, @Nullable String projectUuid) { try { return new TestResultSetIterator(FileSourcesUpdaterHelper.preparedStatementToSelectFileSources(dbClient, session, FileSourceDto.Type.TEST, afterDate, projectUuid)); @@ -67,10 +71,6 @@ public class TestResultSetIterator extends ResultSetIterator<Row> { } } - private TestResultSetIterator(PreparedStatement stmt) throws SQLException { - super(stmt); - } - @Override protected Row read(ResultSet rs) throws SQLException { String projectUuid = rs.getString(1); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/DumbRule.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/DumbRule.java index 72e780b2298..45c340ac4c9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/DumbRule.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/DumbRule.java @@ -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 index fc490fa021f..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleCacheLoaderTest.java +++ /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() - } - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleRepositoryImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleRepositoryImplTest.java index 1497bbce6fd..5b12101525b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleRepositoryImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleRepositoryImplTest.java @@ -19,37 +19,223 @@ */ 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; + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleRepositoryRule.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleRepositoryRule.java index d50be77dafa..5cde0f10be0 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleRepositoryRule.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/RuleRepositoryRule.java @@ -19,43 +19,61 @@ */ 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; } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistIssuesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistIssuesStepTest.java index 344e3f0769d..53198c87543 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistIssuesStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistIssuesStepTest.java @@ -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/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java index 84636b8ef24..eaa807efb7d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java @@ -21,16 +21,18 @@ package org.sonar.server.qualityprofile.ws; import org.junit.Rule; import org.junit.Test; -import org.sonar.api.server.ws.WebService.Action; import org.sonar.api.utils.System2; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbTester; import org.sonar.db.qualityprofile.QualityProfileDao; import org.sonar.server.db.DbClient; import org.sonar.server.language.LanguageTesting; +import org.sonar.server.plugins.MimeTypes; import org.sonar.server.qualityprofile.QProfileFactory; import org.sonar.server.tester.UserSessionRule; -import org.sonar.server.ws.WsTester; +import org.sonar.server.ws.TestResponse; +import org.sonar.server.ws.WsActionTester; +import org.sonar.test.JsonAssert; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -39,25 +41,47 @@ public class CreateActionTest { @Rule public DbTester db = DbTester.create(System2.INSTANCE); + @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone(); + QualityProfileDao profileDao = new QualityProfileDao(db.myBatis(), mock(System2.class)); + DbClient deprecatedDbClient = new DbClient(db.database(), db.myBatis(), profileDao); + @Test public void should_not_fail_on_no_importers() throws Exception { - QualityProfileDao profileDao = new QualityProfileDao(db.myBatis(), mock(System2.class)); - DbClient dbClient = new DbClient(db.database(), db.myBatis(), profileDao); + CreateAction underTest = new CreateAction(db.getDbClient(), new QProfileFactory(deprecatedDbClient), null, LanguageTesting.newLanguages("xoo"), userSessionRule); + WsActionTester wsTester = new WsActionTester(underTest); - String xooKey = "xoo"; - WsTester wsTester = new WsTester(new QProfilesWs( - mock(RuleActivationActions.class), mock(BulkRuleActivationActions.class), mock(ProjectAssociationActions.class), - new CreateAction(dbClient, new QProfileFactory(dbClient), null, LanguageTesting.newLanguages(xooKey), userSessionRule))); + userSessionRule.login("admin").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN); - Action create = wsTester.controller("api/qualityprofiles").action("create"); - assertThat(create.params()).hasSize(2); + TestResponse response = wsTester.newRequest() + .setMethod("POST") + .setMediaType(MimeTypes.JSON) + .setParam("language", "xoo") + .setParam("name", "Yeehaw!") + .execute(); + JsonAssert.assertJson(response.getInput()).isSimilarTo(getClass().getResource("CreateActionTest/create-no-importer.json")); + assertThat(response.getMediaType()).isEqualTo(MimeTypes.JSON); + } + + /** + * Do not return JSON content type header on IE. + */ + @Test + public void test_ie_hack() throws Exception { + CreateAction underTest = new CreateAction(db.getDbClient(), new QProfileFactory(deprecatedDbClient), null, LanguageTesting.newLanguages("xoo"), userSessionRule); + WsActionTester wsTester = new WsActionTester(underTest); + userSessionRule.login("admin").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN); - userSessionRule.login("anakin").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN); + TestResponse response = wsTester.newRequest() + .setMethod("POST") + // IE asks for application/html or text/html + .setMediaType("application/html") + .setParam("language", "xoo") + .setParam("name", "Yeehaw!") + .execute(); + assertThat(response.getMediaType()).isEqualTo(MimeTypes.TXT); - wsTester.newPostRequest("api/qualityprofiles", "create") - .setParam("language", xooKey).setParam("name", "Yeehaw!").execute().assertJson(getClass(), "create-no-importer.json"); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsMediumTest.java index 17ba3f9495d..5574d156a75 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsMediumTest.java @@ -20,36 +20,23 @@ package org.sonar.server.rule.ws; import com.google.common.collect.ImmutableSet; -import java.util.Calendar; import java.util.Collections; -import java.util.Date; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; 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.ws.WebService; -import org.sonar.api.utils.DateUtils; import org.sonar.db.DbSession; import org.sonar.db.qualityprofile.ActiveRuleDto; -import org.sonar.db.qualityprofile.ActiveRuleParamDto; import org.sonar.db.qualityprofile.QualityProfileDao; import org.sonar.db.qualityprofile.QualityProfileDto; import org.sonar.db.rule.RuleDto; -import org.sonar.db.rule.RuleDto.Format; -import org.sonar.db.rule.RuleParamDto; -import org.sonar.db.debt.CharacteristicDto; +import org.sonar.db.rule.RuleTesting; import org.sonar.server.db.DbClient; -import org.sonar.server.debt.DebtTesting; import org.sonar.server.qualityprofile.QProfileTesting; import org.sonar.server.qualityprofile.db.ActiveRuleDao; -import org.sonar.db.rule.RuleTesting; import org.sonar.server.rule.db.RuleDao; -import org.sonar.server.rule.index.RuleNormalizer; import org.sonar.server.tester.ServerTester; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; @@ -64,7 +51,6 @@ public class RulesWsMediumTest { public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester); private static final String API_ENDPOINT = "api/rules"; - private static final String API_SEARCH_METHOD = "search"; private static final String API_SHOW_METHOD = "show"; private static final String API_TAGS_METHOD = "tags"; @@ -72,8 +58,6 @@ public class RulesWsMediumTest { RulesWs ws; RuleDao ruleDao; DbSession session; - int softReliabilityId; - int hardReliabilityId; @Before public void setUp() { @@ -98,7 +82,7 @@ public class RulesWsMediumTest { assertThat(controller).isNotNull(); assertThat(controller.actions()).hasSize(9); - assertThat(controller.action(API_SEARCH_METHOD)).isNotNull(); + assertThat(controller.action("search")).isNotNull(); assertThat(controller.action(API_SHOW_METHOD)).isNotNull(); assertThat(controller.action(API_TAGS_METHOD)).isNotNull(); assertThat(controller.action("update")).isNotNull(); @@ -136,367 +120,6 @@ public class RulesWsMediumTest { } @Test - public void search_no_rules() throws Exception { - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, "actives"); - WsTester.Result result = request.execute(); - - result.assertJson(this.getClass(), "search_no_rules.json"); - } - - @Test - public void filter_by_key_rules() throws Exception { - ruleDao.insert(session, RuleTesting.newXooX1()); - ruleDao.insert(session, RuleTesting.newXooX2()); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(SearchAction.PARAM_KEY, RuleTesting.XOO_X1.toString()); - request.setParam(WebService.Param.FIELDS, "actives"); - WsTester.Result result = request.execute(); - result.assertJson("{\"total\":1,\"p\":1,\"ps\":100,\"rules\":[{\"key\":\"xoo:x1\"}]}"); - - request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(SearchAction.PARAM_KEY, RuleKey.of("xoo", "unknown").toString()); - request.setParam(WebService.Param.FIELDS, "actives"); - result = request.execute(); - result.assertJson("{\"total\":0,\"p\":1,\"ps\":100,\"rules\":[],\"actives\":{}}"); - - } - - @Test - public void search_2_rules() throws Exception { - ruleDao.insert(session, RuleTesting.newXooX1()); - ruleDao.insert(session, RuleTesting.newXooX2()); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - WsTester.Result result = request.execute(); - - result.assertJson(getClass(), "search_2_rules.json"); - } - - @Test - public void search_2_rules_with_field_selection() throws Exception { - ruleDao.insert(session, RuleTesting.newXooX1()); - ruleDao.insert(session, RuleTesting.newXooX2().setDescription("A *Xoo* rule").setDescriptionFormat(Format.MARKDOWN)); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD).setParam(WebService.Param.FIELDS, "name,htmlDesc,mdDesc"); - WsTester.Result result = request.execute(); - - result.assertJson(getClass(), "search_2_rules_fields.json"); - } - - @Test - public void search_debt_rules() throws Exception { - insertDebtCharacteristics(session); - - ruleDao.insert(session, RuleTesting.newXooX1() - .setDefaultSubCharacteristicId(hardReliabilityId) - .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefaultRemediationCoefficient("1h") - .setDefaultRemediationOffset("15min") - - .setSubCharacteristicId(null) - .setRemediationFunction(null) - .setRemediationCoefficient(null) - .setRemediationOffset(null) - ); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn"); - request.setParam(WebService.Param.FACETS, "debt_characteristics"); - WsTester.Result result = request.execute(); - result.assertJson(this.getClass(), "search_debt_rule.json"); - } - - @Test - public void search_debt_rules_with_default_and_overridden_debt_values() throws Exception { - insertDebtCharacteristics(session); - - ruleDao.insert(session, RuleTesting.newXooX1() - .setDefaultSubCharacteristicId(hardReliabilityId) - .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefaultRemediationCoefficient("1h") - .setDefaultRemediationOffset("15min") - - .setSubCharacteristicId(softReliabilityId) - .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setRemediationCoefficient("2h") - .setRemediationOffset("25min") - ); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn"); - WsTester.Result result = request.execute(); - result.assertJson(this.getClass(), "search_debt_rules_with_default_and_overridden_debt_values.json"); - } - - @Test - public void search_debt_rules_with_default_linear_offset_and_overridden_constant_debt() throws Exception { - insertDebtCharacteristics(session); - - ruleDao.insert(session, RuleTesting.newXooX1() - .setDefaultSubCharacteristicId(hardReliabilityId) - .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefaultRemediationCoefficient("1h") - .setDefaultRemediationOffset("15min") - - .setSubCharacteristicId(softReliabilityId) - .setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()) - .setRemediationCoefficient(null) - .setRemediationOffset("5min") - ); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn"); - WsTester.Result result = request.execute(); - result.assertJson(this.getClass(), "search_debt_rules_with_default_linear_offset_and_overridden_constant_debt.json"); - } - - @Test - public void search_debt_rules_with_default_linear_offset_and_overridden_linear_debt() throws Exception { - insertDebtCharacteristics(session); - - ruleDao.insert(session, RuleTesting.newXooX1() - .setDefaultSubCharacteristicId(hardReliabilityId) - .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefaultRemediationCoefficient("1h") - .setDefaultRemediationOffset("15min") - - .setSubCharacteristicId(softReliabilityId) - .setRemediationFunction(DebtRemediationFunction.Type.LINEAR.name()) - .setRemediationCoefficient("1h") - .setRemediationOffset(null) - ); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn"); - WsTester.Result result = request.execute(); - result.assertJson(this.getClass(), "search_debt_rules_with_default_linear_offset_and_overridden_linear_debt.json"); - } - - @Test - public void debt_characteristics_is_sticky_facet() throws Exception { - insertDebtCharacteristics(session); - - ruleDao.insert(session, RuleTesting.newXooX1() - .setDefaultSubCharacteristicId(hardReliabilityId) - .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefaultRemediationCoefficient("1h") - .setDefaultRemediationOffset("15min") - - .setSubCharacteristicId(null) - .setRemediationFunction(null) - .setRemediationCoefficient(null) - .setRemediationOffset(null) - ); - ruleDao.insert(session, RuleTesting.newXooX2() - .setDefaultSubCharacteristicId(hardReliabilityId) - .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefaultRemediationCoefficient("1h") - .setDefaultRemediationOffset("15min") - - .setSubCharacteristicId(softReliabilityId) - .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setRemediationCoefficient("30min") - .setRemediationOffset("5min") - ); - ruleDao.insert(session, RuleTesting.newXooX3() - .setDefaultSubCharacteristicId(null) - .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefaultRemediationCoefficient("2min") - .setDefaultRemediationOffset("1min") - - .setSubCharacteristicId(null) - .setRemediationFunction(null) - .setRemediationCoefficient(null) - .setRemediationOffset(null) - ); - ruleDao.insert(session, RuleTesting.newDto(RuleKey.of("xoo", "x4")).setLanguage("xoo") - .setDefaultSubCharacteristicId(softReliabilityId) - .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) - .setDefaultRemediationCoefficient("2min") - .setDefaultRemediationOffset("1min") - - .setSubCharacteristicId(-1) - .setRemediationFunction(null) - .setRemediationCoefficient(null) - .setRemediationOffset(null) - ); - session.commit(); - - WsTester.Result result = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD) - .setParam(WebService.Param.FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn") - .setParam("debt_characteristics", "SOFT_RELIABILITY") - .setParam(WebService.Param.FACETS, "debt_characteristics") - .execute(); - result.assertJson(this.getClass(), "search_debt_rules_sticky.json"); - } - - @Test - public void search_template_rules() throws Exception { - RuleDto templateRule = RuleTesting.newXooX1().setIsTemplate(true); - ruleDao.insert(session, templateRule); - ruleDao.insert(session, RuleTesting.newXooX2()).setTemplateId(templateRule.getId()); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, "isTemplate"); - request.setParam(SearchAction.PARAM_IS_TEMPLATE, "true"); - WsTester.Result result = request.execute(); - result.assertJson(this.getClass(), "search_template_rules.json"); - } - - @Test - public void search_custom_rules_from_template_key() throws Exception { - RuleDto templateRule = RuleTesting.newXooX1().setIsTemplate(true); - ruleDao.insert(session, templateRule); - ruleDao.insert(session, RuleTesting.newXooX2()).setTemplateId(templateRule.getId()); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, "templateKey"); - request.setParam(SearchAction.PARAM_TEMPLATE_KEY, "xoo:x1"); - WsTester.Result result = request.execute(); - result.assertJson(this.getClass(), "search_rules_from_template_key.json"); - } - - @Test - public void search_all_active_rules() throws Exception { - QualityProfileDto profile = QProfileTesting.newXooP1(); - tester.get(QualityProfileDao.class).insert(session, profile); - - RuleDto rule = RuleTesting.newXooX1(); - ruleDao.insert(session, rule); - - ActiveRuleDto activeRule = newActiveRule(profile, rule); - tester.get(ActiveRuleDao.class).insert(session, activeRule); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.TEXT_QUERY, "x1"); - request.setParam(SearchAction.PARAM_ACTIVATION, "true"); - request.setParam(WebService.Param.FIELDS, ""); - WsTester.Result result = request.execute(); - - result.assertJson(this.getClass(), "search_active_rules.json"); - } - - @Test - public void search_profile_active_rules() throws Exception { - QualityProfileDto profile = QProfileTesting.newXooP1(); - tester.get(QualityProfileDao.class).insert(session, profile); - - QualityProfileDto profile2 = QProfileTesting.newXooP2(); - tester.get(QualityProfileDao.class).insert(session, profile2); - - session.commit(); - - RuleDto rule = RuleTesting.newXooX1(); - ruleDao.insert(session, rule); - - ActiveRuleDto activeRule = newActiveRule(profile, rule); - tester.get(ActiveRuleDao.class).insert(session, activeRule); - ActiveRuleDto activeRule2 = newActiveRule(profile2, rule); - tester.get(ActiveRuleDao.class).insert(session, activeRule2); - - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.TEXT_QUERY, "x1"); - request.setParam(SearchAction.PARAM_ACTIVATION, "true"); - request.setParam(SearchAction.PARAM_QPROFILE, profile2.getKey()); - request.setParam(WebService.Param.FIELDS, "actives"); - WsTester.Result result = request.execute(); - result.assertJson(this.getClass(), "search_profile_active_rules.json"); - - tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD) - .setParam(SearchAction.PARAM_ACTIVATION, "true") - .setParam(SearchAction.PARAM_QPROFILE, "unknown_profile") - .setParam(WebService.Param.FIELDS, "actives") - .execute() - .assertJson(this.getClass(), "search_no_rules.json"); - } - - @Test - public void search_profile_active_rules_with_inheritance() throws Exception { - QualityProfileDto profile = QProfileTesting.newXooP1(); - tester.get(QualityProfileDao.class).insert(session, profile); - - QualityProfileDto profile2 = QProfileTesting.newXooP2().setParentKee(profile.getKee()); - tester.get(QualityProfileDao.class).insert(session, profile2); - - session.commit(); - - RuleDto rule = RuleTesting.newXooX1(); - ruleDao.insert(session, rule); - - ActiveRuleDto activeRule = newActiveRule(profile, rule); - tester.get(ActiveRuleDao.class).insert(session, activeRule); - ActiveRuleDto activeRule2 = newActiveRule(profile2, rule).setInheritance(ActiveRuleDto.OVERRIDES).setSeverity(Severity.CRITICAL); - tester.get(ActiveRuleDao.class).insert(session, activeRule2); - - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.TEXT_QUERY, "x1"); - request.setParam(SearchAction.PARAM_ACTIVATION, "true"); - request.setParam(SearchAction.PARAM_QPROFILE, profile2.getKey()); - request.setParam(WebService.Param.FIELDS, "actives"); - WsTester.Result result = request.execute(); - result.assertJson(this.getClass(), "search_profile_active_rules_inheritance.json"); - } - - @Test - public void search_all_active_rules_params() throws Exception { - QualityProfileDto profile = QProfileTesting.newXooP1(); - tester.get(QualityProfileDao.class).insert(session, profile); - RuleDto rule = RuleTesting.newXooX1(); - ruleDao.insert(session, rule); - session.commit(); - - RuleParamDto param = RuleParamDto.createFor(rule) - .setDefaultValue("some value") - .setType("string") - .setDescription("My small description") - .setName("my_var"); - ruleDao.insertRuleParam(session, rule, param); - - RuleParamDto param2 = RuleParamDto.createFor(rule) - .setDefaultValue("other value") - .setType("integer") - .setDescription("My small description") - .setName("the_var"); - ruleDao.insertRuleParam(session, rule, param2); - - ActiveRuleDto activeRule = newActiveRule(profile, rule); - tester.get(ActiveRuleDao.class).insert(session, activeRule); - - ActiveRuleParamDto activeRuleParam = ActiveRuleParamDto.createFor(param) - .setValue("The VALUE"); - tester.get(ActiveRuleDao.class).insertParam(session, activeRule, activeRuleParam); - - ActiveRuleParamDto activeRuleParam2 = ActiveRuleParamDto.createFor(param2) - .setValue("The Other Value"); - tester.get(ActiveRuleDao.class).insertParam(session, activeRule, activeRuleParam2); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.TEXT_QUERY, "x1"); - request.setParam(SearchAction.PARAM_ACTIVATION, "true"); - request.setParam(WebService.Param.FIELDS, "params"); - WsTester.Result result = request.execute(); - - result.assertJson(this.getClass(), "search_active_rules_params.json"); - } - - @Test public void get_tags() throws Exception { QualityProfileDto profile = QProfileTesting.newXooP1(); tester.get(QualityProfileDao.class).insert(session, profile); @@ -519,139 +142,4 @@ public class RulesWsMediumTest { .setParam("q", "ll").execute().assertJson(this.getClass(), "get_tags_filtered.json"); } - @Test - public void get_note_as_markdown_and_html() throws Exception { - QualityProfileDto profile = QProfileTesting.newXooP1(); - tester.get(QualityProfileDao.class).insert(session, profile); - RuleDto rule = RuleTesting.newXooX1().setNoteData("this is *bold*"); - ruleDao.insert(session, rule); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, "htmlNote, mdNote"); - WsTester.Result result = request.execute(); - result.assertJson(this.getClass(), "get_note_as_markdown_and_html.json"); - } - - @Test - public void filter_by_tags() throws Exception { - ruleDao.insert(session, RuleTesting.newXooX1() - .setTags(Collections.<String>emptySet()) - .setSystemTags(ImmutableSet.of("tag1"))); - ruleDao.insert(session, RuleTesting.newXooX2() - .setTags(Collections.<String>emptySet()) - .setSystemTags(ImmutableSet.of("tag2"))); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(SearchAction.PARAM_TAGS, "tag1"); - request.setParam(WebService.Param.FIELDS, "sysTags, tags"); - request.setParam(WebService.Param.FACETS, "tags"); - WsTester.Result result = request.execute(); - result.assertJson(this.getClass(), "filter_by_tags.json"); - } - - @Test - public void severities_facet_should_have_all_severities() throws Exception { - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FACETS, "severities"); - request.execute().assertJson(this.getClass(), "severities_facet.json"); - } - - @Test - public void statuses_facet_should_have_all_statuses_except_removed() throws Exception { - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FACETS, "statuses"); - request.execute().assertJson(this.getClass(), "statuses_facet.json"); - } - - @Test - public void statuses_facet_should_be_sticky() throws Exception { - ruleDao.insert(session, RuleTesting.newXooX1()); - ruleDao.insert(session, RuleTesting.newXooX2().setStatus(RuleStatus.BETA)); - ruleDao.insert(session, RuleTesting.newXooX3().setStatus(RuleStatus.DEPRECATED)); - session.commit(); - - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(SearchAction.PARAM_STATUSES, "DEPRECATED"); - request.setParam(WebService.Param.FACETS, "statuses"); - request.execute().assertJson(this.getClass(), "statuses_facet_sticky.json"); - } - - @Test - public void sort_by_name() throws Exception { - ruleDao.insert(session, RuleTesting.newXooX1().setName("Dodgy - Consider returning a zero length array rather than null ")); - ruleDao.insert(session, RuleTesting.newXooX2().setName("Bad practice - Creates an empty zip file entry")); - ruleDao.insert(session, RuleTesting.newXooX3().setName("XPath rule")); - session.commit(); - - // 1. Sort Name Asc - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, ""); - request.setParam(WebService.Param.SORT, "name"); - request.setParam(WebService.Param.ASCENDING, "true"); - - WsTester.Result result = request.execute(); - result.assertJson("{\"total\":3,\"p\":1,\"ps\":100,\"rules\":[{\"key\":\"xoo:x2\"},{\"key\":\"xoo:x1\"},{\"key\":\"xoo:x3\"}]}"); - - // 2. Sort Name DESC - request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, ""); - request.setParam(WebService.Param.SORT, RuleNormalizer.RuleField.NAME.field()); - request.setParam(WebService.Param.ASCENDING, "false"); - - result = request.execute(); - result.assertJson("{\"total\":3,\"p\":1,\"ps\":100,\"rules\":[{\"key\":\"xoo:x3\"},{\"key\":\"xoo:x1\"},{\"key\":\"xoo:x2\"}]}"); - - } - - @Test - public void available_since() throws Exception { - ruleDao.insert(session, RuleTesting.newXooX1()); - ruleDao.insert(session, RuleTesting.newXooX2()); - session.commit(); - session.clearCache(); - - Date since = new Date(); - - // 1. find today's rules - WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, ""); - request.setParam(SearchAction.PARAM_AVAILABLE_SINCE, DateUtils.formatDate(since)); - request.setParam(WebService.Param.SORT, RuleNormalizer.RuleField.KEY.field()); - WsTester.Result result = request.execute(); - result.assertJson("{\"total\":2,\"p\":1,\"ps\":100,\"rules\":[{\"key\":\"xoo:x1\"},{\"key\":\"xoo:x2\"}]}"); - - Calendar c = Calendar.getInstance(); - c.setTime(since); - c.add(Calendar.DATE, 1); // number of days to add - - // 2. no rules since tomorrow - request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); - request.setParam(WebService.Param.FIELDS, ""); - request.setParam(SearchAction.PARAM_AVAILABLE_SINCE, DateUtils.formatDate(c.getTime())); - result = request.execute(); - result.assertJson("{\"total\":0,\"p\":1,\"ps\":100,\"rules\":[]}"); - } - - private ActiveRuleDto newActiveRule(QualityProfileDto profile, RuleDto rule) { - return ActiveRuleDto.createFor(profile, rule) - .setInheritance(null) - .setSeverity("BLOCKER"); - } - - private void insertDebtCharacteristics(DbSession dbSession) { - CharacteristicDto reliability = DebtTesting.newCharacteristicDto("RELIABILITY").setName("Reliability"); - db.debtCharacteristicDao().insert(dbSession, reliability); - - CharacteristicDto softReliability = DebtTesting.newCharacteristicDto("SOFT_RELIABILITY").setName("Soft Reliability") - .setParentId(reliability.getId()); - db.debtCharacteristicDao().insert(dbSession, softReliability); - softReliabilityId = softReliability.getId(); - - CharacteristicDto hardReliability = DebtTesting.newCharacteristicDto("HARD_RELIABILITY").setName("Hard Reliability") - .setParentId(reliability.getId()); - db.debtCharacteristicDao().insert(dbSession, hardReliability); - hardReliabilityId = hardReliability.getId(); - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionMediumTest.java new file mode 100644 index 00000000000..bc2fe0be698 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionMediumTest.java @@ -0,0 +1,627 @@ +/* + * 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.ws; + +import com.google.common.collect.ImmutableSet; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +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.ws.WebService; +import org.sonar.api.utils.DateUtils; +import org.sonar.db.DbSession; +import org.sonar.db.debt.CharacteristicDto; +import org.sonar.db.qualityprofile.ActiveRuleDto; +import org.sonar.db.qualityprofile.ActiveRuleParamDto; +import org.sonar.db.qualityprofile.QualityProfileDao; +import org.sonar.db.qualityprofile.QualityProfileDto; +import org.sonar.db.rule.RuleDto; +import org.sonar.db.rule.RuleParamDto; +import org.sonar.db.rule.RuleTesting; +import org.sonar.server.db.DbClient; +import org.sonar.server.debt.DebtTesting; +import org.sonar.server.qualityprofile.QProfileTesting; +import org.sonar.server.qualityprofile.db.ActiveRuleDao; +import org.sonar.server.rule.db.RuleDao; +import org.sonar.server.rule.index.RuleNormalizer; +import org.sonar.server.tester.ServerTester; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.ws.WsTester; + +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SearchActionMediumTest { + + @ClassRule + public static ServerTester tester = new ServerTester().addXoo(); + @Rule + public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester); + + private static final String API_ENDPOINT = "api/rules"; + private static final String API_SEARCH_METHOD = "search"; + + DbClient db; + RulesWs ws; + RuleDao ruleDao; + DbSession session; + int softReliabilityId; + int hardReliabilityId; + + @Before + public void setUp() { + tester.clearDbAndIndexes(); + db = tester.get(DbClient.class); + ruleDao = tester.get(RuleDao.class); + ws = tester.get(RulesWs.class); + session = tester.get(DbClient.class).openSession(false); + } + + @After + public void after() { + session.close(); + } + + @Test + public void search_no_rules() throws Exception { + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, "actives"); + WsTester.Result result = request.execute(); + + result.assertJson(this.getClass(), "search_no_rules.json"); + } + + @Test + public void filter_by_key_rules() throws Exception { + ruleDao.insert(session, RuleTesting.newXooX1()); + ruleDao.insert(session, RuleTesting.newXooX2()); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(SearchAction.PARAM_KEY, RuleTesting.XOO_X1.toString()); + request.setParam(WebService.Param.FIELDS, "actives"); + WsTester.Result result = request.execute(); + result.assertJson("{\"total\":1,\"p\":1,\"ps\":100,\"rules\":[{\"key\":\"xoo:x1\"}]}"); + + request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(SearchAction.PARAM_KEY, RuleKey.of("xoo", "unknown").toString()); + request.setParam(WebService.Param.FIELDS, "actives"); + result = request.execute(); + result.assertJson("{\"total\":0,\"p\":1,\"ps\":100,\"rules\":[],\"actives\":{}}"); + + } + + @Test + public void search_2_rules() throws Exception { + ruleDao.insert(session, RuleTesting.newXooX1()); + ruleDao.insert(session, RuleTesting.newXooX2()); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + WsTester.Result result = request.execute(); + + result.assertJson(getClass(), "search_2_rules.json"); + } + + @Test + public void search_2_rules_with_field_selection() throws Exception { + ruleDao.insert(session, RuleTesting.newXooX1()); + ruleDao.insert(session, RuleTesting.newXooX2().setDescription("A *Xoo* rule").setDescriptionFormat(RuleDto.Format.MARKDOWN)); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD).setParam(WebService.Param.FIELDS, "name,htmlDesc,mdDesc"); + WsTester.Result result = request.execute(); + + result.assertJson(getClass(), "search_2_rules_fields.json"); + } + + @Test + public void return_lang_field() throws Exception { + ruleDao.insert(session, RuleTesting.newXooX1()); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD).setParam(WebService.Param.FIELDS, "lang"); + WsTester.Result result = request.execute(); + + result.assertJson("{\"total\":1,\"p\":1,\"ps\":100," + + "\"rules\":[{\"key\":\"xoo:x1\",\"lang\":\"xoo\"}]}"); + assertThat(result.outputAsString()).doesNotContain("\"langName\""); + assertThat(result.outputAsString()).doesNotContain("\"name\""); + } + + @Test + public void return_lang_name_field() throws Exception { + ruleDao.insert(session, RuleTesting.newXooX1()); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD).setParam(WebService.Param.FIELDS, "langName"); + WsTester.Result result = request.execute(); + + result.assertJson("{\"total\":1,\"p\":1,\"ps\":100," + + "\"rules\":[{\"key\":\"xoo:x1\",\"langName\":\"Xoo\"}]}"); + assertThat(result.outputAsString()).doesNotContain("\"lang\""); + assertThat(result.outputAsString()).doesNotContain("\"name\""); + } + + @Test + public void return_lang_key_field_when_language_name_is_not_available() throws Exception { + ruleDao.insert(session, RuleTesting.newDto(RuleKey.of("other", "rule"))).setLanguage("unknown"); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD).setParam(WebService.Param.FIELDS, "langName"); + WsTester.Result result = request.execute(); + + result.assertJson("{\"total\":1,\"p\":1,\"ps\":100," + + "\"rules\":[{\"key\":\"other:rule\",\"langName\":\"unknown\"}]}"); + } + + @Test + public void search_debt_rules() throws Exception { + insertDebtCharacteristics(session); + + ruleDao.insert(session, RuleTesting.newXooX1() + .setDefaultSubCharacteristicId(hardReliabilityId) + .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefaultRemediationCoefficient("1h") + .setDefaultRemediationOffset("15min") + + .setSubCharacteristicId(null) + .setRemediationFunction(null) + .setRemediationCoefficient(null) + .setRemediationOffset(null) + ); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn"); + request.setParam(WebService.Param.FACETS, "debt_characteristics"); + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "search_debt_rule.json"); + } + + @Test + public void search_debt_rules_with_default_and_overridden_debt_values() throws Exception { + insertDebtCharacteristics(session); + + ruleDao.insert(session, RuleTesting.newXooX1() + .setDefaultSubCharacteristicId(hardReliabilityId) + .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefaultRemediationCoefficient("1h") + .setDefaultRemediationOffset("15min") + + .setSubCharacteristicId(softReliabilityId) + .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setRemediationCoefficient("2h") + .setRemediationOffset("25min") + ); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn"); + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "search_debt_rules_with_default_and_overridden_debt_values.json"); + } + + @Test + public void search_debt_rules_with_default_linear_offset_and_overridden_constant_debt() throws Exception { + insertDebtCharacteristics(session); + + ruleDao.insert(session, RuleTesting.newXooX1() + .setDefaultSubCharacteristicId(hardReliabilityId) + .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefaultRemediationCoefficient("1h") + .setDefaultRemediationOffset("15min") + + .setSubCharacteristicId(softReliabilityId) + .setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.name()) + .setRemediationCoefficient(null) + .setRemediationOffset("5min") + ); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn"); + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "search_debt_rules_with_default_linear_offset_and_overridden_constant_debt.json"); + } + + @Test + public void search_debt_rules_with_default_linear_offset_and_overridden_linear_debt() throws Exception { + insertDebtCharacteristics(session); + + ruleDao.insert(session, RuleTesting.newXooX1() + .setDefaultSubCharacteristicId(hardReliabilityId) + .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefaultRemediationCoefficient("1h") + .setDefaultRemediationOffset("15min") + + .setSubCharacteristicId(softReliabilityId) + .setRemediationFunction(DebtRemediationFunction.Type.LINEAR.name()) + .setRemediationCoefficient("1h") + .setRemediationOffset(null) + ); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn"); + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "search_debt_rules_with_default_linear_offset_and_overridden_linear_debt.json"); + } + + @Test + public void debt_characteristics_is_sticky_facet() throws Exception { + insertDebtCharacteristics(session); + + ruleDao.insert(session, RuleTesting.newXooX1() + .setDefaultSubCharacteristicId(hardReliabilityId) + .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefaultRemediationCoefficient("1h") + .setDefaultRemediationOffset("15min") + + .setSubCharacteristicId(null) + .setRemediationFunction(null) + .setRemediationCoefficient(null) + .setRemediationOffset(null) + ); + ruleDao.insert(session, RuleTesting.newXooX2() + .setDefaultSubCharacteristicId(hardReliabilityId) + .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefaultRemediationCoefficient("1h") + .setDefaultRemediationOffset("15min") + + .setSubCharacteristicId(softReliabilityId) + .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setRemediationCoefficient("30min") + .setRemediationOffset("5min") + ); + ruleDao.insert(session, RuleTesting.newXooX3() + .setDefaultSubCharacteristicId(null) + .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefaultRemediationCoefficient("2min") + .setDefaultRemediationOffset("1min") + + .setSubCharacteristicId(null) + .setRemediationFunction(null) + .setRemediationCoefficient(null) + .setRemediationOffset(null) + ); + ruleDao.insert(session, RuleTesting.newDto(RuleKey.of("xoo", "x4")).setLanguage("xoo") + .setDefaultSubCharacteristicId(softReliabilityId) + .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.name()) + .setDefaultRemediationCoefficient("2min") + .setDefaultRemediationOffset("1min") + + .setSubCharacteristicId(-1) + .setRemediationFunction(null) + .setRemediationCoefficient(null) + .setRemediationOffset(null) + ); + session.commit(); + + WsTester.Result result = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD) + .setParam(WebService.Param.FIELDS, "debtChar,debtCharName,debtSubChar,debtSubCharName,debtRemFn,debtOverloaded,defaultDebtChar,defaultDebtSubChar,defaultDebtRemFn") + .setParam("debt_characteristics", "SOFT_RELIABILITY") + .setParam(WebService.Param.FACETS, "debt_characteristics") + .execute(); + result.assertJson(this.getClass(), "search_debt_rules_sticky.json"); + } + + @Test + public void search_template_rules() throws Exception { + RuleDto templateRule = RuleTesting.newXooX1().setIsTemplate(true); + ruleDao.insert(session, templateRule); + ruleDao.insert(session, RuleTesting.newXooX2()).setTemplateId(templateRule.getId()); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, "isTemplate"); + request.setParam(SearchAction.PARAM_IS_TEMPLATE, "true"); + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "search_template_rules.json"); + } + + @Test + public void search_custom_rules_from_template_key() throws Exception { + RuleDto templateRule = RuleTesting.newXooX1().setIsTemplate(true); + ruleDao.insert(session, templateRule); + ruleDao.insert(session, RuleTesting.newXooX2()).setTemplateId(templateRule.getId()); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, "templateKey"); + request.setParam(SearchAction.PARAM_TEMPLATE_KEY, "xoo:x1"); + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "search_rules_from_template_key.json"); + } + + @Test + public void search_all_active_rules() throws Exception { + QualityProfileDto profile = QProfileTesting.newXooP1(); + tester.get(QualityProfileDao.class).insert(session, profile); + + RuleDto rule = RuleTesting.newXooX1(); + ruleDao.insert(session, rule); + + ActiveRuleDto activeRule = newActiveRule(profile, rule); + tester.get(ActiveRuleDao.class).insert(session, activeRule); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.TEXT_QUERY, "x1"); + request.setParam(SearchAction.PARAM_ACTIVATION, "true"); + request.setParam(WebService.Param.FIELDS, ""); + WsTester.Result result = request.execute(); + + result.assertJson(this.getClass(), "search_active_rules.json"); + } + + @Test + public void search_profile_active_rules() throws Exception { + QualityProfileDto profile = QProfileTesting.newXooP1(); + tester.get(QualityProfileDao.class).insert(session, profile); + + QualityProfileDto profile2 = QProfileTesting.newXooP2(); + tester.get(QualityProfileDao.class).insert(session, profile2); + + session.commit(); + + RuleDto rule = RuleTesting.newXooX1(); + ruleDao.insert(session, rule); + + ActiveRuleDto activeRule = newActiveRule(profile, rule); + tester.get(ActiveRuleDao.class).insert(session, activeRule); + ActiveRuleDto activeRule2 = newActiveRule(profile2, rule); + tester.get(ActiveRuleDao.class).insert(session, activeRule2); + + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.TEXT_QUERY, "x1"); + request.setParam(SearchAction.PARAM_ACTIVATION, "true"); + request.setParam(SearchAction.PARAM_QPROFILE, profile2.getKey()); + request.setParam(WebService.Param.FIELDS, "actives"); + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "search_profile_active_rules.json"); + + tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD) + .setParam(SearchAction.PARAM_ACTIVATION, "true") + .setParam(SearchAction.PARAM_QPROFILE, "unknown_profile") + .setParam(WebService.Param.FIELDS, "actives") + .execute() + .assertJson(this.getClass(), "search_no_rules.json"); + } + + @Test + public void search_profile_active_rules_with_inheritance() throws Exception { + QualityProfileDto profile = QProfileTesting.newXooP1(); + tester.get(QualityProfileDao.class).insert(session, profile); + + QualityProfileDto profile2 = QProfileTesting.newXooP2().setParentKee(profile.getKee()); + tester.get(QualityProfileDao.class).insert(session, profile2); + + session.commit(); + + RuleDto rule = RuleTesting.newXooX1(); + ruleDao.insert(session, rule); + + ActiveRuleDto activeRule = newActiveRule(profile, rule); + tester.get(ActiveRuleDao.class).insert(session, activeRule); + ActiveRuleDto activeRule2 = newActiveRule(profile2, rule).setInheritance(ActiveRuleDto.OVERRIDES).setSeverity(Severity.CRITICAL); + tester.get(ActiveRuleDao.class).insert(session, activeRule2); + + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.TEXT_QUERY, "x1"); + request.setParam(SearchAction.PARAM_ACTIVATION, "true"); + request.setParam(SearchAction.PARAM_QPROFILE, profile2.getKey()); + request.setParam(WebService.Param.FIELDS, "actives"); + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "search_profile_active_rules_inheritance.json"); + } + + @Test + public void search_all_active_rules_params() throws Exception { + QualityProfileDto profile = QProfileTesting.newXooP1(); + tester.get(QualityProfileDao.class).insert(session, profile); + RuleDto rule = RuleTesting.newXooX1(); + ruleDao.insert(session, rule); + session.commit(); + + RuleParamDto param = RuleParamDto.createFor(rule) + .setDefaultValue("some value") + .setType("string") + .setDescription("My small description") + .setName("my_var"); + ruleDao.insertRuleParam(session, rule, param); + + RuleParamDto param2 = RuleParamDto.createFor(rule) + .setDefaultValue("other value") + .setType("integer") + .setDescription("My small description") + .setName("the_var"); + ruleDao.insertRuleParam(session, rule, param2); + + ActiveRuleDto activeRule = newActiveRule(profile, rule); + tester.get(ActiveRuleDao.class).insert(session, activeRule); + + ActiveRuleParamDto activeRuleParam = ActiveRuleParamDto.createFor(param) + .setValue("The VALUE"); + tester.get(ActiveRuleDao.class).insertParam(session, activeRule, activeRuleParam); + + ActiveRuleParamDto activeRuleParam2 = ActiveRuleParamDto.createFor(param2) + .setValue("The Other Value"); + tester.get(ActiveRuleDao.class).insertParam(session, activeRule, activeRuleParam2); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.TEXT_QUERY, "x1"); + request.setParam(SearchAction.PARAM_ACTIVATION, "true"); + request.setParam(WebService.Param.FIELDS, "params"); + WsTester.Result result = request.execute(); + + result.assertJson(this.getClass(), "search_active_rules_params.json"); + } + + @Test + public void get_note_as_markdown_and_html() throws Exception { + QualityProfileDto profile = QProfileTesting.newXooP1(); + tester.get(QualityProfileDao.class).insert(session, profile); + RuleDto rule = RuleTesting.newXooX1().setNoteData("this is *bold*"); + ruleDao.insert(session, rule); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, "htmlNote, mdNote"); + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "get_note_as_markdown_and_html.json"); + } + + @Test + public void filter_by_tags() throws Exception { + ruleDao.insert(session, RuleTesting.newXooX1() + .setTags(Collections.<String>emptySet()) + .setSystemTags(ImmutableSet.of("tag1"))); + ruleDao.insert(session, RuleTesting.newXooX2() + .setTags(Collections.<String>emptySet()) + .setSystemTags(ImmutableSet.of("tag2"))); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(SearchAction.PARAM_TAGS, "tag1"); + request.setParam(WebService.Param.FIELDS, "sysTags, tags"); + request.setParam(WebService.Param.FACETS, "tags"); + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "filter_by_tags.json"); + } + + @Test + public void severities_facet_should_have_all_severities() throws Exception { + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FACETS, "severities"); + request.execute().assertJson(this.getClass(), "severities_facet.json"); + } + + @Test + public void statuses_facet_should_have_all_statuses_except_removed() throws Exception { + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FACETS, "statuses"); + request.execute().assertJson(this.getClass(), "statuses_facet.json"); + } + + @Test + public void statuses_facet_should_be_sticky() throws Exception { + ruleDao.insert(session, RuleTesting.newXooX1()); + ruleDao.insert(session, RuleTesting.newXooX2().setStatus(RuleStatus.BETA)); + ruleDao.insert(session, RuleTesting.newXooX3().setStatus(RuleStatus.DEPRECATED)); + session.commit(); + + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(SearchAction.PARAM_STATUSES, "DEPRECATED"); + request.setParam(WebService.Param.FACETS, "statuses"); + request.execute().assertJson(this.getClass(), "statuses_facet_sticky.json"); + } + + @Test + public void sort_by_name() throws Exception { + ruleDao.insert(session, RuleTesting.newXooX1().setName("Dodgy - Consider returning a zero length array rather than null ")); + ruleDao.insert(session, RuleTesting.newXooX2().setName("Bad practice - Creates an empty zip file entry")); + ruleDao.insert(session, RuleTesting.newXooX3().setName("XPath rule")); + session.commit(); + + // 1. Sort Name Asc + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, ""); + request.setParam(WebService.Param.SORT, "name"); + request.setParam(WebService.Param.ASCENDING, "true"); + + WsTester.Result result = request.execute(); + result.assertJson("{\"total\":3,\"p\":1,\"ps\":100,\"rules\":[{\"key\":\"xoo:x2\"},{\"key\":\"xoo:x1\"},{\"key\":\"xoo:x3\"}]}"); + + // 2. Sort Name DESC + request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, ""); + request.setParam(WebService.Param.SORT, RuleNormalizer.RuleField.NAME.field()); + request.setParam(WebService.Param.ASCENDING, "false"); + + result = request.execute(); + result.assertJson("{\"total\":3,\"p\":1,\"ps\":100,\"rules\":[{\"key\":\"xoo:x3\"},{\"key\":\"xoo:x1\"},{\"key\":\"xoo:x2\"}]}"); + + } + + @Test + public void available_since() throws Exception { + ruleDao.insert(session, RuleTesting.newXooX1()); + ruleDao.insert(session, RuleTesting.newXooX2()); + session.commit(); + session.clearCache(); + + Date since = new Date(); + + // 1. find today's rules + WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, ""); + request.setParam(SearchAction.PARAM_AVAILABLE_SINCE, DateUtils.formatDate(since)); + request.setParam(WebService.Param.SORT, RuleNormalizer.RuleField.KEY.field()); + WsTester.Result result = request.execute(); + result.assertJson("{\"total\":2,\"p\":1,\"ps\":100,\"rules\":[{\"key\":\"xoo:x1\"},{\"key\":\"xoo:x2\"}]}"); + + Calendar c = Calendar.getInstance(); + c.setTime(since); + c.add(Calendar.DATE, 1); // number of days to add + + // 2. no rules since tomorrow + request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD); + request.setParam(WebService.Param.FIELDS, ""); + request.setParam(SearchAction.PARAM_AVAILABLE_SINCE, DateUtils.formatDate(c.getTime())); + result = request.execute(); + result.assertJson("{\"total\":0,\"p\":1,\"ps\":100,\"rules\":[]}"); + } + + private ActiveRuleDto newActiveRule(QualityProfileDto profile, RuleDto rule) { + return ActiveRuleDto.createFor(profile, rule) + .setInheritance(null) + .setSeverity("BLOCKER"); + } + + private void insertDebtCharacteristics(DbSession dbSession) { + CharacteristicDto reliability = DebtTesting.newCharacteristicDto("RELIABILITY").setName("Reliability"); + db.debtCharacteristicDao().insert(dbSession, reliability); + + CharacteristicDto softReliability = DebtTesting.newCharacteristicDto("SOFT_RELIABILITY").setName("Soft Reliability") + .setParentId(reliability.getId()); + db.debtCharacteristicDao().insert(dbSession, softReliability); + softReliabilityId = softReliability.getId(); + + CharacteristicDto hardReliability = DebtTesting.newCharacteristicDto("HARD_RELIABILITY").setName("Hard Reliability") + .setParentId(reliability.getId()); + db.debtCharacteristicDao().insert(dbSession, hardReliability); + hardReliabilityId = hardReliability.getId(); + } + +} 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 index 075ab07d14f..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/computation/issue/RuleCacheLoaderTest/shared.xml +++ /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> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/filter_by_tags.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/filter_by_tags.json index e109ed28cc8..e109ed28cc8 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/filter_by_tags.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/filter_by_tags.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/get_note_as_markdown_and_html.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/get_note_as_markdown_and_html.json index b4a4ecd5153..b4a4ecd5153 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/get_note_as_markdown_and_html.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/get_note_as_markdown_and_html.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_2_rules.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_2_rules.json index a3da4d33ff2..a3da4d33ff2 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_2_rules.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_2_rules.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_2_rules_fields.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_2_rules_fields.json index 0dcbe93c49f..0dcbe93c49f 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_2_rules_fields.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_2_rules_fields.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_active_rules.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_active_rules.json index 76e721d0b85..76e721d0b85 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_active_rules.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_active_rules.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_active_rules_params.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_active_rules_params.json index c8edf1ad34a..c8edf1ad34a 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_active_rules_params.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_active_rules_params.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_debt_rule.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_debt_rule.json index 0a2211290ec..0a2211290ec 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_debt_rule.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_debt_rule.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_debt_rules_sticky.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_debt_rules_sticky.json index 59441d3015d..59441d3015d 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_debt_rules_sticky.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_debt_rules_sticky.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_debt_rules_with_default_and_overridden_debt_values.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_debt_rules_with_default_and_overridden_debt_values.json index a3d107c3fc4..a3d107c3fc4 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_debt_rules_with_default_and_overridden_debt_values.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_debt_rules_with_default_and_overridden_debt_values.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_debt_rules_with_default_linear_offset_and_overridden_constant_debt.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_debt_rules_with_default_linear_offset_and_overridden_constant_debt.json index 0a1632920f0..0a1632920f0 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_debt_rules_with_default_linear_offset_and_overridden_constant_debt.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_debt_rules_with_default_linear_offset_and_overridden_constant_debt.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_debt_rules_with_default_linear_offset_and_overridden_linear_debt.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_debt_rules_with_default_linear_offset_and_overridden_linear_debt.json index d778dc77969..d778dc77969 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_debt_rules_with_default_linear_offset_and_overridden_linear_debt.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_debt_rules_with_default_linear_offset_and_overridden_linear_debt.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_no_rules.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_no_rules.json index 0e7286cf282..0e7286cf282 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_no_rules.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_no_rules.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_profile_active_rules.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_profile_active_rules.json index 1b7d587e7b0..ec6439cb0a7 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_profile_active_rules.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_profile_active_rules.json @@ -21,7 +21,7 @@ "XOO_P2": { "name": "P2", "lang": "xoo", - "langName": "xoo" + "langName": "Xoo" } } } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_profile_active_rules_inheritance.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_profile_active_rules_inheritance.json index adc48218f3e..016101f2a44 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_profile_active_rules_inheritance.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_profile_active_rules_inheritance.json @@ -21,13 +21,13 @@ "XOO_P2": { "name": "P2", "lang": "xoo", - "langName": "xoo", + "langName": "Xoo", "parent": "XOO_P1" }, "XOO_P1": { "name": "P1", "lang": "xoo", - "langName": "xoo" + "langName": "Xoo" } } } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_rules_from_template_key.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_rules_from_template_key.json index f9668593f71..f9668593f71 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_rules_from_template_key.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_rules_from_template_key.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_template_rules.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_template_rules.json index c7a449843da..c7a449843da 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/search_template_rules.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/search_template_rules.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/severities_facet.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/severities_facet.json index f2d9754809b..f2d9754809b 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/severities_facet.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/severities_facet.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/statuses_facet.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/statuses_facet.json index 4692be87efe..4692be87efe 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/statuses_facet.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/statuses_facet.json diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/statuses_facet_sticky.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/statuses_facet_sticky.json index a5b7a796655..a5b7a796655 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWsMediumTest/statuses_facet_sticky.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/SearchActionMediumTest/statuses_facet_sticky.json diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/templates/quality-profiles-delete-profile.hbs b/server/sonar-web/src/main/js/apps/quality-profiles/templates/quality-profiles-delete-profile.hbs index a2635e55124..99ee29ce611 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/templates/quality-profiles-delete-profile.hbs +++ b/server/sonar-web/src/main/js/apps/quality-profiles/templates/quality-profiles-delete-profile.hbs @@ -1,4 +1,3 @@ -{{log this}} <form id="delete-profile-form"> <div class="modal-head"> <h2>{{t 'quality_profiles.delete_confirm_title'}}</h2> diff --git a/server/sonar-web/src/main/js/libs/third-party/select2.js b/server/sonar-web/src/main/js/libs/third-party/select2.js index 213f4cf930a..8975c0ea4c2 100644 --- a/server/sonar-web/src/main/js/libs/third-party/select2.js +++ b/server/sonar-web/src/main/js/libs/third-party/select2.js @@ -962,15 +962,17 @@ var cid = this.containerId, selector = this.containerSelector, scroll = "scroll." + cid, resize = "resize." + cid; - this.container.parents().each(function() { - $(this).bind(scroll, function() { - var s2 = $(selector); - if (s2.length == 0) { - $(this).unbind(scroll); - } - s2.select2("close"); + setTimeout(function () { + this.container.parents().each(function() { + $(this).bind(scroll, function() { + var s2 = $(selector); + if (s2.length == 0) { + $(this).unbind(scroll); + } + s2.select2("close"); + }); }); - }); + }.bind(this), 100); $(window).bind(resize, function() { var s2 = $(selector); @@ -1401,6 +1403,7 @@ // single close: function () { if (!this.opened()) return; + console.log('closing...'); this.parent.close.apply(this, arguments); this.dropdown.removeAttr("style").addClass("select2-offscreen").insertAfter(this.selection).show(); }, |