From 71876a9a53fd2562c00d2eb135d3141d3591862c Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 28 Apr 2021 14:17:43 +0200 Subject: [PATCH] SONAR-14559 Update active rule for descendant when rule inherited --- .../server/qualityprofile/RuleActivator.java | 114 +++++++--- .../BuiltInQProfileUpdateImplTest.java | 95 +++++++- .../qualityprofile/RuleActivatorTest.java | 207 ++++++++++++++++++ 3 files changed, 378 insertions(+), 38 deletions(-) create mode 100644 server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/RuleActivatorTest.java diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java index 6b56e27aa8c..80fe80d8423 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java @@ -161,60 +161,106 @@ public class RuleActivator { ActiveRuleWrapper activeRule = context.getActiveRule(); ActiveRuleWrapper parentActiveRule = context.getParentActiveRule(); - // First apply severity - String severity; if (request.isReset()) { - // load severity from parent profile, else from default values - severity = firstNonNull( - parentActiveRule != null ? parentActiveRule.get().getSeverityString() : null, - rule.get().getSeverityString()); + applySeverityAndParamsWhenResetRequested(change, rule, parentActiveRule); } else if (context.getRulesProfile().isBuiltIn()) { - // for builtin quality profiles, the severity from profile, when null use the default severity of the rule - severity = firstNonNull(request.getSeverity(), rule.get().getSeverityString()); + applySeverityAndParamsWhenBuiltInProfile(request, context, change, rule); } else { - // load severity from request, else keep existing one (if already activated), else from parent, else from default - severity = firstNonNull( - request.getSeverity(), - activeRule == null ? null : activeRule.get().getSeverityString(), - parentActiveRule != null ? parentActiveRule.get().getSeverityString() : null, - rule.get().getSeverityString()); + applySeverityAndParamsWhenNonBuiltInProfile(request, context, change, rule, activeRule, parentActiveRule); + } + } + + private void applySeverityAndParamsWhenResetRequested(ActiveRuleChange change, RuleWrapper rule, @Nullable ActiveRuleWrapper parentActiveRule) { + String severity = firstNonNull( + parentActiveRule != null ? parentActiveRule.get().getSeverityString() : null, + rule.get().getSeverityString()); + change.setSeverity(severity); + + for (RuleParamDto ruleParamDto : rule.getParams()) { + String paramKey = ruleParamDto.getName(); + // load params from parent profile, else from default values + String paramValue = firstNonNull( + parentActiveRule != null ? parentActiveRule.getParamValue(paramKey) : null, + rule.getParamDefaultValue(paramKey)); + + change.setParameter(paramKey, validateParam(ruleParamDto, paramValue)); + } + } + + private void applySeverityAndParamsWhenBuiltInProfile(RuleActivation request, RuleActivationContext context, ActiveRuleChange change, + RuleWrapper rule) { + // for builtin quality profiles, the severity from profile, when null use the default severity of the rule + String severity = firstNonNull(request.getSeverity(), rule.get().getSeverityString()); + change.setSeverity(severity); + + for (RuleParamDto ruleParamDto : rule.getParams()) { + String paramKey = ruleParamDto.getName(); + // use the value defined in the profile definition, else the rule default value + String paramValue = firstNonNull( + context.getRequestedParamValue(request, paramKey), + rule.getParamDefaultValue(paramKey)); + change.setParameter(paramKey, validateParam(ruleParamDto, paramValue)); } + } + + /** + * 1. apply requested severity and param + * 2. if rule activated and overridden - apply user value + * 3. apply parent value + * 4. apply defaults + */ + private void applySeverityAndParamsWhenNonBuiltInProfile(RuleActivation request, RuleActivationContext context, ActiveRuleChange change, + RuleWrapper rule, @Nullable ActiveRuleWrapper activeRule, @Nullable ActiveRuleWrapper parentActiveRule) { + String severity = getSeverityForNonBuiltInProfile(request, rule, activeRule, parentActiveRule); change.setSeverity(severity); - // Apply param values for (RuleParamDto ruleParamDto : rule.getParams()) { String paramKey = ruleParamDto.getName(); + String parentValue = parentActiveRule != null ? parentActiveRule.getParamValue(paramKey) : null; String paramValue; - if (request.isReset()) { - // load params from parent profile, else from default values + if (context.hasRequestedParamValue(request, paramKey)) { + // If the request contains the parameter then we're using either value from request, or parent value, or default value paramValue = firstNonNull( - parentActiveRule != null ? parentActiveRule.getParamValue(paramKey) : null, + context.getRequestedParamValue(request, paramKey), + parentValue, rule.getParamDefaultValue(paramKey)); - } else if (context.getRulesProfile().isBuiltIn()) { - // use the value defined in the profile definition, else the rule default value + } else if (activeRule != null) { + // If the request doesn't contain the parameter, then we're using either user value from db, or parent value if rule inherited, or default + // value paramValue = firstNonNull( - context.getRequestedParamValue(request, paramKey), + activeRule.get().doesOverride() ? activeRule.getParamValue(paramKey) : null, + parentValue == null ? activeRule.getParamValue(paramKey) : parentValue, rule.getParamDefaultValue(paramKey)); } else { - String parentValue = parentActiveRule != null ? parentActiveRule.getParamValue(paramKey) : null; - String activeRuleValue = activeRule == null ? null : activeRule.getParamValue(paramKey); - paramValue = context.hasRequestedParamValue(request, paramKey) ? - // If the request contains the parameter then we're using either value from request, or parent value, or default value - firstNonNull( - context.getRequestedParamValue(request, paramKey), + paramValue = firstNonNull( parentValue, - rule.getParamDefaultValue(paramKey)) - // If the request doesn't contain the parameter, then we're using either value in DB, or parent value, or default value - : firstNonNull( - activeRuleValue, - parentValue, - rule.getParamDefaultValue(paramKey)); + rule.getParamDefaultValue(paramKey)); } - change.setParameter(paramKey, validateParam(ruleParamDto, paramValue)); } } + private static String getSeverityForNonBuiltInProfile(RuleActivation request, RuleWrapper rule, @Nullable ActiveRuleWrapper activeRule, + @Nullable ActiveRuleWrapper parentActiveRule) { + String severity; + if (activeRule != null) { + ActiveRuleDto activeRuleDto = activeRule.get(); + // load severity from request, else keep existing one (if overridden), else from parent if rule inherited, else from default + severity = firstNonNull( + request.getSeverity(), + activeRuleDto.doesOverride() ? activeRuleDto.getSeverityString() : null, + parentActiveRule != null ? parentActiveRule.get().getSeverityString() : activeRuleDto.getSeverityString(), + rule.get().getSeverityString()); + } else { + // load severity from request, else from parent, else from default + severity = firstNonNull( + request.getSeverity(), + parentActiveRule != null ? parentActiveRule.get().getSeverityString() : null, + rule.get().getSeverityString()); + } + return severity; + } + private List propagateActivationToDescendants(DbSession dbSession, RuleActivation activation, RuleActivationContext context) { List changes = new ArrayList<>(); diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java index d3716ea34a0..dde53fb8f1b 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java @@ -29,6 +29,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.sonar.api.impl.utils.TestSystem2; +import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; import org.sonar.api.rules.RulePriority; import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; @@ -37,6 +38,7 @@ import org.sonar.api.utils.System2; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.qualityprofile.ActiveRuleDto; +import org.sonar.db.qualityprofile.ActiveRuleKey; import org.sonar.db.qualityprofile.ActiveRuleParamDto; import org.sonar.db.qualityprofile.OrgActiveRuleDto; import org.sonar.db.qualityprofile.QProfileDto; @@ -61,6 +63,7 @@ import static org.sonar.api.rules.RulePriority.MAJOR; import static org.sonar.api.rules.RulePriority.MINOR; import static org.sonar.db.qualityprofile.QualityProfileTesting.newRuleProfileDto; import static org.sonar.server.qualityprofile.ActiveRuleInheritance.INHERITED; +import static org.sonar.server.qualityprofile.ActiveRuleInheritance.OVERRIDES; public class BuiltInQProfileUpdateImplTest { @@ -272,6 +275,61 @@ public class BuiltInQProfileUpdateImplTest { assertThatRuleIsActivated(grandchildProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap()); } + // SONAR-14559 + @Test + public void propagate_rule_update_to_descendant_active_rule() { + RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo").setSeverity(Severity.BLOCKER)); + + QProfileDto parentProfile = db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true)); + activateRuleInDb(RulesProfileDto.from(parentProfile), rule, RulePriority.valueOf(Severity.MINOR), null); + + QProfileDto childProfile = createChildProfile(parentProfile); + activateRuleInDb(RulesProfileDto.from(childProfile), rule, RulePriority.valueOf(Severity.MINOR), INHERITED); + + BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context(); + NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile(parentProfile.getName(), parentProfile.getLanguage()); + newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()); + newQp.done(); + BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile(parentProfile.getLanguage(), parentProfile.getName()), rule); + List changes = underTest.update(db.getSession(), builtIn, RulesProfileDto.from(parentProfile)); + + assertThat(changes).hasSize(2); + + List parentActiveRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), RulesProfileDto.from(parentProfile)); + assertThatRuleIsUpdated(parentActiveRules, rule, RulePriority.BLOCKER, null); + + List childActiveRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), RulesProfileDto.from(childProfile)); + assertThatRuleIsUpdated(childActiveRules, rule, RulePriority.BLOCKER, INHERITED); + } + + @Test + public void propagate_rule_param_update_to_descendant_active_rule_params() { + RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo").setSeverity(Severity.BLOCKER)); + RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10")); + + QProfileDto parentProfile = db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true)); + ActiveRuleDto parentActiveRuleDto = activateRuleInDb(RulesProfileDto.from(parentProfile), rule, + RulePriority.valueOf(Severity.MINOR), null); + activateRuleParamInDb(parentActiveRuleDto, ruleParam, "20"); + + QProfileDto childProfile = createChildProfile(parentProfile); + ActiveRuleDto childActiveRuleDto = activateRuleInDb(RulesProfileDto.from(childProfile), rule, + RulePriority.valueOf(Severity.MINOR), INHERITED); + activateRuleParamInDb(childActiveRuleDto, ruleParam, "20"); + + BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context(); + NewBuiltInQualityProfile newQp = context.createBuiltInQualityProfile(parentProfile.getName(), parentProfile.getLanguage()); + newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()); + newQp.done(); + BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile(parentProfile.getLanguage(), parentProfile.getName()), rule); + List changes = underTest.update(db.getSession(), builtIn, RulesProfileDto.from(parentProfile)); + + assertThat(changes).hasSize(2); + + assertThatRuleHasParams(db, parentActiveRuleDto, tuple("min", "10")); + assertThatRuleHasParams(db, childActiveRuleDto, tuple("min", "10")); + } + @Test public void do_not_load_descendants_if_no_changes() { RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo")); @@ -380,15 +438,27 @@ public class BuiltInQProfileUpdateImplTest { assertThat(activeRule.getUpdatedAt()).isEqualTo(NOW); } - private static void assertThatRuleIsUpdated(List activeRules, RuleDefinitionDto rule, RulePriority severity) { + private static void assertThatRuleIsUpdated(List activeRules, RuleDefinitionDto rule, RulePriority severity, @Nullable ActiveRuleInheritance expectedInheritance) { ActiveRuleDto activeRule = findRule(activeRules, rule).get(); - assertThat(activeRule.getInheritance()).isNull(); + if (expectedInheritance != null) { + assertThat(activeRule.getInheritance()).isEqualTo(expectedInheritance.name()); + } else { + assertThat(activeRule.getInheritance()).isNull(); + } assertThat(activeRule.getSeverityString()).isEqualTo(severity.name()); assertThat(activeRule.getCreatedAt()).isEqualTo(PAST); assertThat(activeRule.getUpdatedAt()).isEqualTo(NOW); } + private static void assertThatRuleIsUpdated(List activeRules, RuleDefinitionDto rule, RulePriority severity) { + assertThatRuleIsUpdated(activeRules, rule, severity, null); + } + + private static void assertThatRuleIsUpdated(ActiveRuleDto activeRules, RuleDefinitionDto rule, RulePriority severity, @Nullable ActiveRuleInheritance expectedInheritance) { + assertThatRuleIsUpdated(singletonList(activeRules), rule, severity, expectedInheritance); + } + private static void assertThatRuleIsUntouched(List activeRules, RuleDefinitionDto rule, RulePriority severity) { ActiveRuleDto activeRule = findRule(activeRules, rule).get(); @@ -432,14 +502,31 @@ public class BuiltInQProfileUpdateImplTest { .findFirst(); } - private void activateRuleInDb(RulesProfileDto profile, RuleDefinitionDto rule, RulePriority severity) { + private ActiveRuleDto activateRuleInDb(RulesProfileDto profile, RuleDefinitionDto rule, RulePriority severity) { + return activateRuleInDb(profile, rule, severity, null); + } + + private ActiveRuleDto activateRuleInDb(RulesProfileDto ruleProfile, RuleDefinitionDto rule, RulePriority severity, @Nullable ActiveRuleInheritance inheritance) { ActiveRuleDto dto = new ActiveRuleDto() - .setProfileUuid(profile.getUuid()) + .setKey(ActiveRuleKey.of(ruleProfile, RuleKey.of(rule.getRepositoryKey(), rule.getRuleKey()))) + .setProfileUuid(ruleProfile.getUuid()) .setSeverity(severity.name()) .setRuleUuid(rule.getUuid()) + .setInheritance(inheritance != null ? inheritance.name() : null) .setCreatedAt(PAST) .setUpdatedAt(PAST); db.getDbClient().activeRuleDao().insert(db.getSession(), dto); db.commit(); + return dto; + } + + private void activateRuleParamInDb(ActiveRuleDto activeRuleDto, RuleParamDto ruleParamDto, String value) { + ActiveRuleParamDto dto = new ActiveRuleParamDto() + .setActiveRuleUuid(activeRuleDto.getUuid()) + .setRulesParameterUuid(ruleParamDto.getUuid()) + .setKey(ruleParamDto.getName()) + .setValue(value); + db.getDbClient().activeRuleDao().insertParam(db.getSession(), activeRuleDto, dto); + db.commit(); } } diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/RuleActivatorTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/RuleActivatorTest.java new file mode 100644 index 00000000000..a36173fa87b --- /dev/null +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/RuleActivatorTest.java @@ -0,0 +1,207 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.collect.ImmutableMap; +import java.util.List; +import javax.annotation.Nullable; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.impl.utils.TestSystem2; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.Severity; +import org.sonar.api.rules.RulePriority; +import org.sonar.api.utils.System2; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.db.qualityprofile.ActiveRuleDto; +import org.sonar.db.qualityprofile.ActiveRuleKey; +import org.sonar.db.qualityprofile.ActiveRuleParamDto; +import org.sonar.db.qualityprofile.QProfileDto; +import org.sonar.db.qualityprofile.RulesProfileDto; +import org.sonar.db.rule.RuleDefinitionDto; +import org.sonar.db.rule.RuleParamDto; +import org.sonar.server.qualityprofile.DescendantProfilesSupplier.Result; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.util.IntegerTypeValidation; +import org.sonar.server.util.StringTypeValidation; +import org.sonar.server.util.TypeValidations; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.server.qualityprofile.ActiveRuleInheritance.INHERITED; +import static org.sonar.server.qualityprofile.ActiveRuleInheritance.OVERRIDES; + +/** + * Class org.sonar.server.qualityprofile.RuleActivator is mostly covered in + * org.sonar.server.qualityprofile.BuiltInQProfileUpdateImplTest + */ +public class RuleActivatorTest { + @Rule + public final DbTester db = DbTester.create(); + + @Rule + public final UserSessionRule userSession = UserSessionRule.standalone(); + + private static final long NOW = 1_000; + private static final long PAST = NOW - 100; + private final System2 system2 = new TestSystem2().setNow(NOW); + private final TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation())); + + private final RuleActivator underTest = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession); + + @Test + public void reset_overridden_active_rule() { + RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo").setSeverity(Severity.BLOCKER)); + RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10")); + + QProfileDto parentProfile = db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true)); + ActiveRuleDto parentActiveRuleDto = activateRuleInDb(RulesProfileDto.from(parentProfile), rule, + RulePriority.valueOf(Severity.BLOCKER), null); + ActiveRuleParamDto parentActiveRuleParam = activateRuleParamInDb(parentActiveRuleDto, ruleParam, "10"); + + QProfileDto childProfile = createChildProfile(parentProfile); + ActiveRuleDto childActiveRuleDto = activateRuleInDb(RulesProfileDto.from(childProfile), rule, + RulePriority.valueOf(Severity.MINOR), OVERRIDES); + ActiveRuleParamDto childActiveRuleParam = activateRuleParamInDb(childActiveRuleDto, ruleParam, "15"); + + DbSession session = db.getSession(); + RuleActivation resetRequest = RuleActivation.createReset(rule.getUuid()); + RuleActivationContext context = new RuleActivationContext.Builder() + .setProfiles(asList(parentProfile, childProfile)) + .setBaseProfile(RulesProfileDto.from(childProfile)) + .setDate(NOW) + .setDescendantProfilesSupplier((profiles, ruleUuids) -> new Result(emptyList(), emptyList(), emptyList())) + .setRules(singletonList(rule)) + .setRuleParams(singletonList(ruleParam)) + .setActiveRules(asList(parentActiveRuleDto, childActiveRuleDto)) + .setActiveRuleParams(asList(parentActiveRuleParam, childActiveRuleParam)) + .build(); + + List result = underTest.activate(session, resetRequest, context); + + assertThat(result).hasSize(1); + assertThat(result.get(0).getParameters()).containsEntry("min", "10"); + assertThat(result.get(0).getSeverity()).isEqualTo(Severity.BLOCKER); + assertThat(result.get(0).getInheritance()).isEqualTo(ActiveRuleInheritance.INHERITED); + } + + @Test + public void request_new_severity_and_param_for_child_rule() { + RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo").setSeverity(Severity.BLOCKER)); + RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10")); + + QProfileDto parentProfile = db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true)); + ActiveRuleDto parentActiveRuleDto = activateRuleInDb(RulesProfileDto.from(parentProfile), rule, + RulePriority.valueOf(Severity.BLOCKER), null); + ActiveRuleParamDto parentActiveRuleParam = activateRuleParamInDb(parentActiveRuleDto, ruleParam, "10"); + + QProfileDto childProfile = createChildProfile(parentProfile); + ActiveRuleDto childActiveRuleDto = activateRuleInDb(RulesProfileDto.from(childProfile), rule, + RulePriority.valueOf(Severity.BLOCKER), INHERITED); + ActiveRuleParamDto childActiveRuleParam = activateRuleParamInDb(childActiveRuleDto, ruleParam, "10"); + + DbSession session = db.getSession(); + RuleActivation resetRequest = RuleActivation.create(rule.getUuid(), Severity.MINOR, ImmutableMap.of("min", "15")); + RuleActivationContext context = new RuleActivationContext.Builder() + .setProfiles(asList(parentProfile, childProfile)) + .setBaseProfile(RulesProfileDto.from(childProfile)) + .setDate(NOW) + .setDescendantProfilesSupplier((profiles, ruleUuids) -> new Result(emptyList(), emptyList(), emptyList())) + .setRules(singletonList(rule)) + .setRuleParams(singletonList(ruleParam)) + .setActiveRules(asList(parentActiveRuleDto, childActiveRuleDto)) + .setActiveRuleParams(asList(parentActiveRuleParam, childActiveRuleParam)) + .build(); + + List result = underTest.activate(session, resetRequest, context); + + assertThat(result).hasSize(1); + assertThat(result.get(0).getParameters()).containsEntry("min", "15"); + assertThat(result.get(0).getSeverity()).isEqualTo(Severity.MINOR); + assertThat(result.get(0).getInheritance()).isEqualTo(OVERRIDES); + } + + @Test + public void set_severity_and_param_for_child_rule_when_activating() { + RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo").setSeverity(Severity.BLOCKER)); + RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10")); + + QProfileDto parentProfile = db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true)); + + QProfileDto childProfile = createChildProfile(parentProfile); + + DbSession session = db.getSession(); + RuleActivation resetRequest = RuleActivation.create(rule.getUuid()); + RuleActivationContext context = new RuleActivationContext.Builder() + .setProfiles(asList(parentProfile, childProfile)) + .setBaseProfile(RulesProfileDto.from(childProfile)) + .setDate(NOW) + .setDescendantProfilesSupplier((profiles, ruleUuids) -> new Result(emptyList(), emptyList(), emptyList())) + .setRules(singletonList(rule)) + .setRuleParams(singletonList(ruleParam)) + .setActiveRules(emptyList()) + .setActiveRuleParams(emptyList()) + .build(); + + List result = underTest.activate(session, resetRequest, context); + + assertThat(result).hasSize(1); + assertThat(result.get(0).getParameters()).containsEntry("min", "10"); + assertThat(result.get(0).getSeverity()).isEqualTo(Severity.BLOCKER); + assertThat(result.get(0).getInheritance()).isNull(); + } + + + private ActiveRuleDto activateRuleInDb(RulesProfileDto ruleProfile, RuleDefinitionDto rule, RulePriority severity, @Nullable ActiveRuleInheritance inheritance) { + ActiveRuleDto dto = new ActiveRuleDto() + .setKey(ActiveRuleKey.of(ruleProfile, RuleKey.of(rule.getRepositoryKey(), rule.getRuleKey()))) + .setProfileUuid(ruleProfile.getUuid()) + .setSeverity(severity.name()) + .setRuleUuid(rule.getUuid()) + .setInheritance(inheritance != null ? inheritance.name() : null) + .setCreatedAt(PAST) + .setUpdatedAt(PAST); + db.getDbClient().activeRuleDao().insert(db.getSession(), dto); + db.commit(); + return dto; + } + + private ActiveRuleParamDto activateRuleParamInDb(ActiveRuleDto activeRuleDto, RuleParamDto ruleParamDto, String value) { + ActiveRuleParamDto dto = new ActiveRuleParamDto() + .setActiveRuleUuid(activeRuleDto.getUuid()) + .setRulesParameterUuid(ruleParamDto.getUuid()) + .setKey(ruleParamDto.getName()) + .setValue(value); + db.getDbClient().activeRuleDao().insertParam(db.getSession(), activeRuleDto, dto); + db.commit(); + return dto; + } + + private QProfileDto createChildProfile(QProfileDto parent) { + return db.qualityProfiles().insert(p -> p + .setLanguage(parent.getLanguage()) + .setParentKee(parent.getKee()) + .setName("Child of " + parent.getName())) + .setIsBuiltIn(false); + } +} -- 2.39.5