From 03084baafbc2ee034309143ee71e866b98e322b4 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lievremont Date: Fri, 10 Apr 2015 18:03:35 +0200 Subject: [PATCH] SONAR-6303 WS to compare quality profiles --- .../server/platform/ServerComponents.java | 2 + .../qualityprofile/QProfileComparator.java | 181 ++++++++++++++++ .../ws/QProfileCompareAction.java | 205 ++++++++++++++++++ .../qualityprofile/ws/example-compare.json | 65 ++++++ .../ws/QProfileCompareActionMediumTest.java | 197 +++++++++++++++++ .../compare_nominal.json | 79 +++++++ 6 files changed, 729 insertions(+) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileComparator.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCompareAction.java create mode 100644 server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/example-compare.json create mode 100644 server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest.java create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_nominal.json diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index f3b490d007b..95bad79553e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -377,6 +377,7 @@ class ServerComponents { pico.addSingleton(QProfileLookup.class); pico.addSingleton(QProfileProjectOperations.class); pico.addSingleton(QProfileProjectLookup.class); + pico.addSingleton(QProfileComparator.class); pico.addSingleton(BuiltInProfiles.class); pico.addSingleton(QProfileRestoreBuiltInAction.class); pico.addSingleton(QProfileSearchAction.class); @@ -392,6 +393,7 @@ class ServerComponents { pico.addSingleton(QProfileInheritanceAction.class); pico.addSingleton(QProfileChangeParentAction.class); pico.addSingleton(QProfileChangelogAction.class); + pico.addSingleton(QProfileCompareAction.class); pico.addSingleton(QProfilesWs.class); pico.addSingleton(ProfilesWs.class); pico.addSingleton(RuleActivationActions.class); diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileComparator.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileComparator.java new file mode 100644 index 00000000000..767dfaa5c17 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileComparator.java @@ -0,0 +1,181 @@ +/* + * 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.qualityprofile; + +import com.google.common.base.Preconditions; +import com.google.common.collect.MapDifference; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.sonar.api.ServerComponent; +import org.sonar.api.rule.RuleKey; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.qualityprofile.db.QualityProfileDto; +import org.sonar.core.util.NonNullInputFunction; +import org.sonar.server.db.DbClient; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +public class QProfileComparator implements ServerComponent { + + private final DbClient dbClient; + + private final QProfileLoader profileLoader; + + public QProfileComparator(DbClient dbClient, QProfileLoader profileLoader) { + this.dbClient = dbClient; + this.profileLoader = profileLoader; + } + + public QProfileComparisonResult compare(String leftKey, String rightKey) { + QProfileComparisonResult result = new QProfileComparisonResult(); + + DbSession dbSession = dbClient.openSession(false); + + try { + compare(leftKey, rightKey, dbSession, result); + } finally { + dbSession.close(); + } + + return result; + } + + private void compare(String leftKey, String rightKey, DbSession session, QProfileComparisonResult result) { + result.left = dbClient.qualityProfileDao().getByKey(session, leftKey); + Preconditions.checkArgument(result.left != null, String.format("Could not find left profile '%s'", leftKey)); + result.right = dbClient.qualityProfileDao().getByKey(session, rightKey); + Preconditions.checkArgument(result.right != null, String.format("Could not find right profile '%s'", leftKey)); + + Map leftActiveRulesByRuleKey = loadActiveRules(leftKey); + Map rightActiveRulesByRuleKey = loadActiveRules(rightKey); + + Set allRules = Sets.newHashSet(); + allRules.addAll(leftActiveRulesByRuleKey.keySet()); + allRules.addAll(rightActiveRulesByRuleKey.keySet()); + + for (RuleKey ruleKey : allRules) { + if (!leftActiveRulesByRuleKey.containsKey(ruleKey)) { + result.inRight.put(ruleKey, rightActiveRulesByRuleKey.get(ruleKey)); + } else if (!rightActiveRulesByRuleKey.containsKey(ruleKey)) { + result.inLeft.put(ruleKey, leftActiveRulesByRuleKey.get(ruleKey)); + } else { + compare(leftActiveRulesByRuleKey.get(ruleKey), rightActiveRulesByRuleKey.get(ruleKey), result); + } + } + } + + private void compare(ActiveRule leftRule, ActiveRule rightRule, QProfileComparisonResult result) { + RuleKey key = leftRule.key().ruleKey(); + if (leftRule.params().equals(rightRule.params()) && leftRule.severity().equals(rightRule.severity())) { + result.same.put(key, leftRule); + } else { + ActiveRuleDiff diff = new ActiveRuleDiff(); + diff.key = key; + + if (leftRule.severity().equals(rightRule.severity())) { + diff.leftSeverity = diff.rightSeverity = leftRule.severity(); + } else { + diff.leftSeverity = leftRule.severity(); + diff.rightSeverity = rightRule.severity(); + } + + diff.paramDifference = Maps.difference(leftRule.params(), rightRule.params()); + result.modified.put(key, diff); + } + } + + private Map loadActiveRules(String profileKey) { + return Maps.uniqueIndex(profileLoader.findActiveRulesByProfile(profileKey), new NonNullInputFunction() { + @Override + protected RuleKey doApply(ActiveRule input) { + return input.key().ruleKey(); + } + }); + } + + public static class QProfileComparisonResult { + + private QualityProfileDto left; + private QualityProfileDto right; + private Map inLeft = Maps.newHashMap(); + private Map inRight = Maps.newHashMap(); + private Map modified = Maps.newHashMap(); + private Map same = Maps.newHashMap(); + + public QualityProfileDto left() { + return left; + } + + public QualityProfileDto right() { + return right; + } + + public Map inLeft() { + return inLeft; + } + + public Map inRight() { + return inRight; + } + + public Map modified() { + return modified; + } + + public Map same() { + return same; + } + + public Collection collectRuleKeys() { + Set keys = Sets.newHashSet(); + keys.addAll(inLeft.keySet()); + keys.addAll(inRight.keySet()); + keys.addAll(modified.keySet()); + keys.addAll(same.keySet()); + return keys; + } + } + + public static class ActiveRuleDiff { + private RuleKey key; + private String leftSeverity; + private String rightSeverity; + private MapDifference paramDifference; + + public RuleKey key() { + return key; + } + + public String leftSeverity() { + return leftSeverity; + } + + public String rightSeverity() { + return rightSeverity; + } + + public MapDifference paramDifference() { + return paramDifference; + } + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCompareAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCompareAction.java new file mode 100644 index 00000000000..754095e8512 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileCompareAction.java @@ -0,0 +1,205 @@ +/* + * 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.qualityprofile.ws; + +import com.google.common.collect.MapDifference.ValueDifference; +import com.google.common.collect.Maps; +import org.sonar.api.resources.Language; +import org.sonar.api.resources.Languages; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService.NewAction; +import org.sonar.api.server.ws.WebService.NewController; +import org.sonar.api.utils.text.JsonWriter; +import org.sonar.core.qualityprofile.db.QualityProfileDto; +import org.sonar.core.util.NonNullInputFunction; +import org.sonar.server.qualityprofile.ActiveRule; +import org.sonar.server.qualityprofile.QProfileComparator; +import org.sonar.server.qualityprofile.QProfileComparator.ActiveRuleDiff; +import org.sonar.server.qualityprofile.QProfileComparator.QProfileComparisonResult; +import org.sonar.server.rule.Rule; +import org.sonar.server.rule.RuleRepositories; +import org.sonar.server.rule.RuleRepositories.Repository; +import org.sonar.server.rule.RuleService; + +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public class QProfileCompareAction implements BaseQProfileWsAction { + + private static final String PARAM_LEFT_KEY = "leftKey"; + private static final String PARAM_RIGHT_KEY = "rightKey"; + + private final QProfileComparator comparator; + private final RuleService ruleService; + private final RuleRepositories ruleRepositories; + private final Languages languages; + + public QProfileCompareAction(QProfileComparator comparator, RuleService ruleService, RuleRepositories ruleRepositories, Languages languages) { + this.comparator = comparator; + this.ruleService = ruleService; + this.ruleRepositories = ruleRepositories; + this.languages = languages; + } + + @Override + public void define(NewController context) { + NewAction compare = context.createAction("compare") + .setDescription("Compare two quality profiles.") + .setHandler(this) + .setResponseExample(getClass().getResource("example-compare.json")) + .setSince("5.2"); + + compare.createParam(PARAM_LEFT_KEY) + .setDescription("A profile key.") + .setExampleValue("java-sonar-way-12345") + .setRequired(true); + + compare.createParam(PARAM_RIGHT_KEY) + .setDescription("Another profile key.") + .setExampleValue("java-sonar-way-with-findbugs-23456") + .setRequired(true); + } + + @Override + public void handle(Request request, Response response) throws Exception { + String leftKey = request.mandatoryParam(PARAM_LEFT_KEY); + String rightKey = request.mandatoryParam(PARAM_RIGHT_KEY); + + QProfileComparisonResult result = comparator.compare(leftKey, rightKey); + + List referencedRules = ruleService.getByKeys(result.collectRuleKeys()); + Map rulesByKey = Maps.uniqueIndex(referencedRules, new NonNullInputFunction() { + @Override + protected RuleKey doApply(Rule input) { + return input.key(); + } + }); + + writeResult(response.newJsonWriter(), result, rulesByKey); + } + + private void writeResult(JsonWriter json, QProfileComparisonResult result, Map rulesByKey) { + json.beginObject(); + + json.name("left").beginObject(); + writeProfile(json, result.left()); + json.endObject(); + + json.name("right").beginObject(); + writeProfile(json, result.right()); + json.endObject(); + + json.name("inLeft"); + writeRules(json, result.inLeft(), rulesByKey); + + json.name("inRight"); + writeRules(json, result.inRight(), rulesByKey); + + json.name("modified"); + writeDifferences(json, result.modified(), rulesByKey); + + json.name("same"); + writeRules(json, result.same(), rulesByKey); + + json.endObject().close(); + } + + private void writeProfile(JsonWriter json, QualityProfileDto profile) { + json.prop("key", profile.getKey()) + .prop("name", profile.getName()); + } + + private void writeRules(JsonWriter json, Map activeRules, Map rulesByKey) { + json.beginArray(); + for (Entry activeRule : activeRules.entrySet()) { + RuleKey key = activeRule.getKey(); + ActiveRule value = activeRule.getValue(); + + json.beginObject(); + writeRule(json, key, rulesByKey); + json.prop("severity", value.severity()); + json.endObject(); + } + json.endArray(); + } + + private void writeRule(JsonWriter json, RuleKey key, Map rulesByKey) { + String repositoryKey = key.repository(); + json.prop("key", key.toString()) + .prop("name", rulesByKey.get(key).name()) + .prop("pluginKey", repositoryKey); + + Repository repo = ruleRepositories.repository(repositoryKey); + if (repo != null) { + String languageKey = repo.getLanguage(); + Language language = languages.get(languageKey); + + json.prop("pluginName", repo.getName()); + json.prop("languageKey", languageKey); + json.prop("languageName", language == null ? null : language.getName()); + } + } + + private void writeDifferences(JsonWriter json, Map modified, Map rulesByKey) { + json.beginArray(); + for (Entry diffEntry : modified.entrySet()) { + RuleKey key = diffEntry.getKey(); + ActiveRuleDiff value = diffEntry.getValue(); + json.beginObject(); + writeRule(json, key, rulesByKey); + + json.name("left").beginObject(); + json.prop("severity", value.leftSeverity()); + json.name("params").beginObject(); + for (Entry> valueDiff : value.paramDifference().entriesDiffering().entrySet()) { + json.prop(valueDiff.getKey(), valueDiff.getValue().leftValue()); + } + for (Entry valueDiff : value.paramDifference().entriesOnlyOnLeft().entrySet()) { + json.prop(valueDiff.getKey(), valueDiff.getValue()); + } + // params + json.endObject(); + // left + json.endObject(); + + json.name("right").beginObject(); + json.prop("severity", value.rightSeverity()); + json.name("params").beginObject(); + for (Entry> valueDiff : value.paramDifference().entriesDiffering().entrySet()) { + json.prop(valueDiff.getKey(), valueDiff.getValue().rightValue()); + } + for (Entry valueDiff : value.paramDifference().entriesOnlyOnRight().entrySet()) { + json.prop(valueDiff.getKey(), valueDiff.getValue()); + } + // params + json.endObject(); + // right + json.endObject(); + + // rule + json.endObject(); + } + json.endArray(); + } + +} diff --git a/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/example-compare.json b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/example-compare.json new file mode 100644 index 00000000000..396a06c8918 --- /dev/null +++ b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/example-compare.json @@ -0,0 +1,65 @@ +{ + "left" : { + "key" : "js-my-profile-19170", + "name" : "My Profile" + }, + "right" : { + "key" : "js-my-other-profile-12367", + "name" : "My Other Profile" + }, + "same" : [ + { + "key" : "javascript:EqEqEq", + "pluginKey" : "javascript", + "pluginName" : "SonarQube", + "languageKey": "js", + "languageName": "JavaScript", + "name" : "\"===\" and \"!==\" should be used instead of \"==\" and \"!=\"", + "severity" : "MAJOR" + } + ], + "inLeft" : [ + { + "key" : "javascript:TrailingWhitespace", + "pluginKey" : "javascript", + "pluginName" : "SonarQube", + "languageKey": "js", + "languageName": "JavaScript", + "name" : "Avoid trailing whitespaces", + "severity" : "MAJOR" + } + ], + "inRight" : [ + { + "key" : "javascript:TabCharacter", + "pluginKey" : "javascript", + "pluginName" : "SonarQube", + "languageKey": "js", + "languageName": "JavaScript", + "name" : "Avoid use of tabulation character", + "severity" : "MINOR" + } + ], + "modified" : [ + { + "key" : "javascript:ExcessiveParameterList", + "pluginKey" : "javascript", + "pluginName" : "SonarQube", + "languageKey": "js", + "languageName": "JavaScript", + "name" : "Avoid function with too many parameters", + "right" : { + "severity" : "MAJOR", + "params" : { + "maximumFunctionParameters" : "7" + } + }, + "left" : { + "severity" : "MAJOR", + "params" : { + "maximumFunctionParameters" : "10" + } + } + } + ] +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest.java new file mode 100644 index 00000000000..9abcb7a6a10 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest.java @@ -0,0 +1,197 @@ +/* + * 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.qualityprofile.ws; + +import org.apache.commons.lang.StringUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rule.Severity; +import org.sonar.api.server.rule.RuleParamType; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.qualityprofile.db.ActiveRuleDto; +import org.sonar.core.qualityprofile.db.ActiveRuleParamDto; +import org.sonar.core.qualityprofile.db.QualityProfileDto; +import org.sonar.core.rule.RuleDto; +import org.sonar.core.rule.RuleParamDto; +import org.sonar.server.db.DbClient; +import org.sonar.server.qualityprofile.QProfileName; +import org.sonar.server.qualityprofile.QProfileTesting; +import org.sonar.server.tester.ServerTester; +import org.sonar.server.ws.WsTester; + +public class QProfileCompareActionMediumTest { + + @ClassRule + public static ServerTester tester = new ServerTester().addXoo() + .addComponents(new RulesDefinition() { + @Override + public void define(Context context) { + context.createRepository("blah", "xoo") + .setName("Blah") + .done(); + } + }); + + private DbClient db; + + private WsTester wsTester; + + private DbSession session; + + @Before + public void setUp() throws Exception { + tester.clearDbAndIndexes(); + db = tester.get(DbClient.class); + session = db.openSession(false); + + wsTester = new WsTester(tester.get(QProfilesWs.class)); + } + + @After + public void tearDown() { + session.close(); + } + + @Test + public void compare_nominal() throws Exception { + RuleDto rule1 = createRule("xoo", "rule1"); + RuleDto rule2 = createRule("xoo", "rule2"); + RuleDto rule3 = createRule("xoo", "rule3"); + RuleDto rule4 = createRuleWithParam("xoo", "rule4"); + RuleDto rule5 = createRule("xoo", "rule5"); + + /* + * Profile 1: + * - rule 1 active (on both profiles) => "same" + * - rule 2 active (only in this profile) => "inLeft" + * - rule 4 active with different parameters => "modified" + * - rule 5 active with different severity => "modified" + */ + QualityProfileDto profile1 = createProfile("xoo", "Profile 1", "xoo-profile-1-01234"); + createActiveRule(rule1, profile1); + createActiveRule(rule2, profile1); + createActiveRuleWithParam(rule4, profile1, "polop"); + createActiveRuleWithSeverity(rule5, profile1, Severity.MINOR); + session.commit(); + + /* + * Profile 1: + * - rule 1 active (on both profiles) => "same" + * - rule 3 active (only in this profile) => "inRight" + * - rule 4 active with different parameters => "modified" + */ + QualityProfileDto profile2 = createProfile("xoo", "Profile 2", "xoo-profile-2-12345"); + createActiveRule(rule1, profile2); + createActiveRule(rule3, profile2); + createActiveRuleWithParam(rule4, profile2, "palap"); + createActiveRuleWithSeverity(rule5, profile2, Severity.MAJOR); + session.commit(); + + wsTester.newGetRequest("api/qualityprofiles", "compare") + .setParam("leftKey", profile1.getKey()) + .setParam("rightKey", profile2.getKey()) + .execute().assertJson(this.getClass(), "compare_nominal.json"); + } + + @Test(expected = IllegalArgumentException.class) + public void fail_on_missing_left_param() throws Exception { + wsTester.newGetRequest("api/qualityprofiles", "compare") + .setParam("rightKey", "polop") + .execute(); + } + + @Test(expected = IllegalArgumentException.class) + public void fail_on_missing_right_param() throws Exception { + wsTester.newGetRequest("api/qualityprofiles", "compare") + .setParam("leftKey", "polop") + .execute(); + } + + @Test(expected = IllegalArgumentException.class) + public void fail_on_left_profile_not_found() throws Exception { + createProfile("xoo", "Right", "xoo-right-12345"); + wsTester.newGetRequest("api/qualityprofiles", "compare") + .setParam("leftKey", "polop") + .setParam("rightKey", "xoo-right-12345") + .execute(); + } + + @Test(expected = IllegalArgumentException.class) + public void fail_on_right_profile_not_found() throws Exception { + createProfile("xoo", "Left", "xoo-left-12345"); + wsTester.newGetRequest("api/qualityprofiles", "compare") + .setParam("leftKey", "xoo-left-12345") + .setParam("rightKey", "polop") + .execute(); + } + + private QualityProfileDto createProfile(String lang, String name, String key) { + QualityProfileDto profile = QProfileTesting.newDto(new QProfileName(lang, name), key); + db.qualityProfileDao().insert(session, profile); + session.commit(); + return profile; + } + + private RuleDto createRule(String lang, String id) { + RuleDto rule = RuleDto.createFor(RuleKey.of("blah", id)) + .setName(StringUtils.capitalize(id)) + .setLanguage(lang) + .setSeverity(Severity.BLOCKER) + .setStatus(RuleStatus.READY); + db.ruleDao().insert(session, rule); + RuleParamDto param = RuleParamDto.createFor(rule).setName("param_" + id).setType(RuleParamType.STRING.toString()); + db.ruleDao().addRuleParam(session, rule, param); + return rule; + } + + private RuleDto createRuleWithParam(String lang, String id) { + RuleDto rule = createRule(lang, id); + RuleParamDto param = RuleParamDto.createFor(rule).setName("param_" + id).setType(RuleParamType.STRING.toString()); + db.ruleDao().addRuleParam(session, rule, param); + return rule; + } + + private ActiveRuleDto createActiveRule(RuleDto rule, QualityProfileDto profile) { + ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule) + .setSeverity(rule.getSeverityString()); + db.activeRuleDao().insert(session, activeRule); + return activeRule; + } + + private ActiveRuleDto createActiveRuleWithParam(RuleDto rule, QualityProfileDto profile, String value) { + ActiveRuleDto activeRule = createActiveRule(rule, profile); + RuleParamDto paramDto = db.ruleDao().findRuleParamsByRuleKey(session, rule.getKey()).get(0); + ActiveRuleParamDto activeRuleParam = ActiveRuleParamDto.createFor(paramDto).setValue(value); + db.activeRuleDao().addParam(session, activeRule, activeRuleParam); + return activeRule; + } + + private ActiveRuleDto createActiveRuleWithSeverity(RuleDto rule, QualityProfileDto profile, String severity) { + ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule) + .setSeverity(severity); + db.activeRuleDao().insert(session, activeRule); + return activeRule; + } +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_nominal.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_nominal.json new file mode 100644 index 00000000000..1d0ef292292 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileCompareActionMediumTest/compare_nominal.json @@ -0,0 +1,79 @@ +{ + "left" : { + "key" : "xoo-profile-1-01234", + "name" : "Profile 1" + }, + "right" : { + "key" : "xoo-profile-2-12345", + "name" : "Profile 2" + }, + "same" : [ + { + "key" : "blah:rule1", + "pluginKey" : "blah", + "pluginName" : "Blah", + "languageKey": "xoo", + "languageName": "Xoo", + "name" : "Rule1", + "severity" : "BLOCKER" + } + ], + "inLeft" : [ + { + "key" : "blah:rule2", + "pluginKey" : "blah", + "pluginName" : "Blah", + "languageKey": "xoo", + "languageName": "Xoo", + "name" : "Rule2", + "severity" : "BLOCKER" + } + ], + "inRight" : [ + { + "key" : "blah:rule3", + "pluginKey" : "blah", + "pluginName" : "Blah", + "languageKey": "xoo", + "languageName": "Xoo", + "name" : "Rule3", + "severity" : "BLOCKER" + } + ], + "modified" : [ + { + "key" : "blah:rule4", + "pluginKey" : "blah", + "pluginName" : "Blah", + "languageKey": "xoo", + "languageName": "Xoo", + "name" : "Rule4", + "left" : { + "severity" : "BLOCKER", + "params" : { + "param_rule4" : "polop" + } + }, + "right" : { + "severity" : "BLOCKER", + "params" : { + "param_rule4" : "palap" + } + } + }, + { + "key" : "blah:rule5", + "pluginKey" : "blah", + "pluginName" : "Blah", + "languageKey": "xoo", + "languageName": "Xoo", + "name" : "Rule5", + "left" : { + "severity" : "MINOR" + }, + "right" : { + "severity" : "MAJOR" + } + } + ] +} -- 2.39.5