import org.sonar.xoo.rule.OneBugIssuePerLineSensor;
import org.sonar.xoo.rule.OneDayDebtPerFileSensor;
import org.sonar.xoo.rule.OneExternalIssuePerLineSensor;
-import org.sonar.xoo.rule.OnePredefinedRuleExternalIssuePerLineSensor;
import org.sonar.xoo.rule.OneIssueOnDirPerFileSensor;
import org.sonar.xoo.rule.OneIssuePerDirectorySensor;
import org.sonar.xoo.rule.OneIssuePerFileSensor;
import org.sonar.xoo.rule.OneIssuePerModuleSensor;
import org.sonar.xoo.rule.OneIssuePerTestFileSensor;
import org.sonar.xoo.rule.OneIssuePerUnknownFileSensor;
+import org.sonar.xoo.rule.OnePredefinedAndAdHocRuleExternalIssuePerLineSensor;
+import org.sonar.xoo.rule.OnePredefinedRuleExternalIssuePerLineSensor;
import org.sonar.xoo.rule.OneVulnerabilityIssuePerModuleSensor;
import org.sonar.xoo.rule.RandomAccessSensor;
import org.sonar.xoo.rule.SaveDataTwiceSensor;
context.addExtensions(
OneExternalIssuePerLineSensor.class,
OnePredefinedRuleExternalIssuePerLineSensor.class,
+ OnePredefinedAndAdHocRuleExternalIssuePerLineSensor.class,
SignificantCodeSensor.class);
}
if (context.getSonarQubeVersion().isGreaterThanOrEqual(Version.create(7, 3))) {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.xoo.rule;
+
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputFile.Type;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.batch.sensor.Sensor;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.api.batch.sensor.issue.NewExternalIssue;
+import org.sonar.api.rules.RuleType;
+import org.sonar.xoo.Xoo;
+
+public class OnePredefinedAndAdHocRuleExternalIssuePerLineSensor implements Sensor {
+
+ public static final String ACTIVATE = "sonar.onePredefinedAndAdHocRuleExternalIssuePerLine.activate";
+ private static final String NAME = "One External Issue Per Line With A Predefined And An AdHoc Rule";
+
+ @Override
+ public void describe(SensorDescriptor descriptor) {
+ descriptor
+ .name(NAME)
+ .onlyOnLanguages(Xoo.KEY)
+ .onlyWhenConfiguration(c -> c.getBoolean(ACTIVATE).orElse(false));
+ }
+
+ @Override
+ public void execute(SensorContext context) {
+ FileSystem fs = context.fileSystem();
+ FilePredicates p = fs.predicates();
+ for (InputFile file : fs.inputFiles(p.and(p.hasLanguages(Xoo.KEY), p.hasType(Type.MAIN)))) {
+ createIssues(file, context);
+ }
+ }
+
+ private static void createIssues(InputFile file, SensorContext context) {
+ for (int line = 1; line <= file.lines(); line++) {
+ NewExternalIssue newIssue = context.newExternalIssue();
+ newIssue
+ .engineId(OnePredefinedRuleExternalIssuePerLineSensor.ENGINE_ID)
+ .ruleId(OnePredefinedRuleExternalIssuePerLineSensor.RULE_ID)
+ .at(newIssue.newLocation()
+ .on(file)
+ .at(file.selectLine(line))
+ .message("This issue is generated on each line and the rule is predefined"))
+ .severity(Severity.valueOf(OnePredefinedRuleExternalIssuePerLineSensor.SEVERITY))
+ .remediationEffortMinutes(OnePredefinedRuleExternalIssuePerLineSensor.EFFORT)
+ .type(OnePredefinedRuleExternalIssuePerLineSensor.TYPE)
+ .save();
+
+ // Even if the issue is on a predefined rule, the sensor is declaring an adHoc rule => this info should be ignored
+ context.newAdHocRule()
+ .engineId(OnePredefinedRuleExternalIssuePerLineSensor.ENGINE_ID)
+ .ruleId(OnePredefinedRuleExternalIssuePerLineSensor.RULE_ID)
+ .name("An ad hoc rule")
+ .description("blah blah")
+ .severity(Severity.BLOCKER)
+ .type(RuleType.BUG)
+ .save();
+ }
+ }
+}
Plugin.Context context = new PluginContextImpl.Builder().setSonarRuntime(runtime).build();
new XooPlugin().define(context);
assertThat(getExtensions(context))
- .hasSize(52)
+ .hasSize(53)
.contains(OneExternalIssuePerLineSensor.class);
}
Plugin.Context context = new PluginContextImpl.Builder().setSonarRuntime(runtime).build();
new XooPlugin().define(context);
assertThat(getExtensions(context))
- .hasSize(53)
+ .hasSize(54)
.contains(OneExternalIssuePerLineSensor.class);
}
private Integer id;
private String repositoryKey;
private String ruleKey;
+
+ /**
+ * Description can be null on external rule, otherwise it should never be null
+ */
private String description;
+
+ /**
+ * Description format can be null on external rule, otherwise it should never be null
+ */
private RuleDto.Format descriptionFormat;
private RuleStatus status;
private String name;
private String configKey;
+
+ /**
+ * Severity can be null on external rule, otherwise it should never be null
+ */
private Integer severity;
+
private boolean isTemplate;
/**
return this;
}
+ @CheckForNull
public String getDescription() {
return description;
}
- public RuleDefinitionDto setDescription(String description) {
+ public RuleDefinitionDto setDescription(@Nullable String description) {
this.description = description;
return this;
}
+ @CheckForNull
public RuleDto.Format getDescriptionFormat() {
return descriptionFormat;
}
- public RuleDefinitionDto setDescriptionFormat(RuleDto.Format descriptionFormat) {
+ public RuleDefinitionDto setDescriptionFormat(@Nullable RuleDto.Format descriptionFormat) {
this.descriptionFormat = descriptionFormat;
return this;
}
}
public RuleParamDto insertRuleParam(RuleDefinitionDto rule) {
- return insertRuleParam(rule, p -> {});
+ return insertRuleParam(rule, p -> {
+ });
}
@SafeVarargs
return ruleDto;
}
- public RuleDto updateRule(RuleDto ruleDto) {
- update(ruleDto.getDefinition());
- RuleMetadataDto metadata = ruleDto.getMetadata();
- if (metadata.getOrganizationUuid() != null) {
- db.getDbClient().ruleDao().insertOrUpdate(db.getSession(), metadata.setRuleId(ruleDto.getId()));
- db.commit();
- }
- return ruleDto;
- }
/**
* Create and persist a rule with random values.
*/
return deprecatedRuleKeyDto;
}
-
public RuleParamDto insertRuleParam(RuleDto rule) {
RuleParamDto param = new RuleParamDto();
param.setRuleId(rule.getId());
package org.sonar.server.rule.ws;
import com.google.common.base.Function;
-import com.google.common.collect.FluentIterable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction;
import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleDto.Scope;
import org.sonar.db.rule.RuleMetadataDto;
import org.sonar.db.rule.RuleParamDto;
import static java.lang.String.format;
import static org.sonar.api.utils.DateUtils.formatDateTime;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_CREATED_AT;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DEBT_OVERLOADED;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DEBT_REM_FUNCTION;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_TEMPLATE_KEY;
/**
- * Conversion of {@link org.sonar.db.rule.RuleDto} to {@link org.sonarqube.ws.Rules.Rule}
+ * Conversion of {@link RuleDto} to {@link Rules.Rule}
*/
public class RuleMapper {
return ruleResponse.build();
}
- public Rules.Rule toWsRule(RuleDefinitionDto ruleDefinitionDto, SearchResult result, Set<String> fieldsToReturn, RuleMetadataDto metadata, Map<String, UserDto> usersByUuid) {
+ public Rules.Rule toWsRule(RuleDefinitionDto ruleDefinition, SearchResult result, Set<String> fieldsToReturn, RuleMetadataDto metadata, Map<String, UserDto> usersByUuid) {
Rules.Rule.Builder ruleResponse = Rules.Rule.newBuilder();
- applyRuleDefinition(ruleResponse, ruleDefinitionDto, result, fieldsToReturn);
- applyRuleMetadata(ruleResponse, metadata, usersByUuid, fieldsToReturn);
- setDebtRemediationFunctionFields(ruleResponse, ruleDefinitionDto, metadata, fieldsToReturn);
+ applyRuleDefinition(ruleResponse, ruleDefinition, result, fieldsToReturn);
+ applyRuleMetadata(ruleResponse, ruleDefinition, metadata, usersByUuid, fieldsToReturn);
+ setDebtRemediationFunctionFields(ruleResponse, ruleDefinition, metadata, fieldsToReturn);
return ruleResponse.build();
}
- public Rules.Rule.Builder applyRuleDefinition(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDefinitionDto, SearchResult result, Set<String> fieldsToReturn) {
+ private Rules.Rule.Builder applyRuleDefinition(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDefinitionDto, SearchResult result, Set<String> fieldsToReturn) {
// Mandatory fields
ruleResponse.setKey(ruleDefinitionDto.getKey().toString());
ruleResponse.setType(Common.RuleType.forNumber(ruleDefinitionDto.getType()));
// Optional fields
- setRepository(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setName(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setRepository(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setStatus(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setSysTags(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setParams(ruleResponse, ruleDefinitionDto, result, fieldsToReturn);
return ruleResponse;
}
- private void applyRuleMetadata(Rules.Rule.Builder ruleResponse, RuleMetadataDto metadata, Map<String, UserDto> usersByUuid, Set<String> fieldsToReturn) {
+ private void applyRuleMetadata(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDefinition, RuleMetadataDto metadata, Map<String, UserDto> usersByUuid,
+ Set<String> fieldsToReturn) {
setTags(ruleResponse, metadata, fieldsToReturn);
setNotesFields(ruleResponse, metadata, usersByUuid, fieldsToReturn);
setIsRemediationFunctionOverloaded(ruleResponse, metadata, fieldsToReturn);
+ if (ruleDefinition.isAdHoc()) {
+ setAdHocName(ruleResponse, metadata, fieldsToReturn);
+ setAdHocDescription(ruleResponse, metadata, fieldsToReturn);
+ setAdHocSeverity(ruleResponse, metadata, fieldsToReturn);
+ setAdHocType(ruleResponse, metadata);
+ }
+ }
+
+ private static void setAdHocName(Rules.Rule.Builder ruleResponse, RuleMetadataDto metadata, Set<String> fieldsToReturn) {
+ String adHocName = metadata.getAdHocName();
+ if (adHocName != null && shouldReturnField(fieldsToReturn, FIELD_NAME)) {
+ ruleResponse.setName(adHocName);
+ }
+ }
+
+ private void setAdHocDescription(Rules.Rule.Builder ruleResponse, RuleMetadataDto metadata, Set<String> fieldsToReturn) {
+ String adHocDescription = metadata.getAdHocDescription();
+ if (adHocDescription != null && shouldReturnField(fieldsToReturn, FIELD_HTML_DESCRIPTION)) {
+ ruleResponse.setHtmlDesc(macroInterpreter.interpret(adHocDescription));
+ }
+ }
+
+ private static void setAdHocSeverity(Rules.Rule.Builder ruleResponse, RuleMetadataDto metadata, Set<String> fieldsToReturn) {
+ String severity = metadata.getAdHocSeverity();
+ if (shouldReturnField(fieldsToReturn, FIELD_SEVERITY) && severity != null) {
+ ruleResponse.setSeverity(severity);
+ }
+ }
+
+ private static void setAdHocType(Rules.Rule.Builder ruleResponse, RuleMetadataDto metadata) {
+ Integer ruleType = metadata.getAdHocType();
+ if (ruleType != null) {
+ ruleResponse.setType(Common.RuleType.forNumber(ruleType));
+ }
}
private static void setRepository(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
}
private static void setEffortToFixDescription(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
+ String gapDescription = ruleDto.getGapDescription();
if ((shouldReturnField(fieldsToReturn, FIELD_EFFORT_TO_FIX_DESCRIPTION) || shouldReturnField(fieldsToReturn, FIELD_GAP_DESCRIPTION))
- && ruleDto.getGapDescription() != null) {
- ruleResponse.setEffortToFixDescription(ruleDto.getGapDescription());
- ruleResponse.setGapDescription(ruleDto.getGapDescription());
+ && gapDescription != null) {
+ ruleResponse.setEffortToFixDescription(gapDescription);
+ ruleResponse.setGapDescription(gapDescription);
}
}
private static void setParams(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, SearchResult searchResult, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_PARAMS)) {
List<RuleParamDto> ruleParameters = searchResult.getRuleParamsByRuleId().get(ruleDto.getId());
- ruleResponse.getParamsBuilder().addAllParams(FluentIterable.from(ruleParameters)
- .transform(RuleParamDtoToWsRuleParam.INSTANCE)
- .toList());
+ ruleResponse.getParamsBuilder().addAllParams(ruleParameters.stream().map(RuleParamDtoToWsRuleParam.INSTANCE::apply).collect(toList()));
}
}
}
private void setDescriptionFields(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
+ String description = ruleDto.getDescription();
if (shouldReturnField(fieldsToReturn, FIELD_HTML_DESCRIPTION)) {
- String description = ruleDto.getDescription();
- if (description != null) {
- switch (ruleDto.getDescriptionFormat()) {
+ RuleDto.Format descriptionFormat = ruleDto.getDescriptionFormat();
+ if (description != null && descriptionFormat != null) {
+ switch (descriptionFormat) {
case MARKDOWN:
ruleResponse.setHtmlDesc(macroInterpreter.interpret(Markdown.convertToHtml(description)));
break;
ruleResponse.setHtmlDesc(macroInterpreter.interpret(description));
break;
default:
- throw new IllegalStateException(format("Rule description format '%s' is unknown for key '%s'", ruleDto.getDescriptionFormat(), ruleDto.getKey().toString()));
+ throw new IllegalStateException(format("Rule description format '%s' is unknown for key '%s'", descriptionFormat, ruleDto.getKey().toString()));
}
}
}
- if (shouldReturnField(fieldsToReturn, FIELD_MARKDOWN_DESCRIPTION) && ruleDto.getDescription() != null) {
- ruleResponse.setMdDesc(ruleDto.getDescription());
+ if (shouldReturnField(fieldsToReturn, FIELD_MARKDOWN_DESCRIPTION) && description != null) {
+ ruleResponse.setMdDesc(description);
}
}
}
private void setLanguageName(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
- if (shouldReturnField(fieldsToReturn, FIELD_LANGUAGE_NAME) && ruleDto.getLanguage() != null) {
- String languageKey = ruleDto.getLanguage();
+ String languageKey = ruleDto.getLanguage();
+ if (shouldReturnField(fieldsToReturn, FIELD_LANGUAGE_NAME) && languageKey != null) {
Language language = languages.get(languageKey);
ruleResponse.setLangName(language == null ? languageKey : language.getName());
}
ruleResponse.setIsTemplate(ruleDto.isTemplate());
}
}
-
+
private static void setIsExternal(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_IS_EXTERNAL)) {
ruleResponse.setIsExternal(ruleDto.isExternal());
assertThat(searchedRule.getTemplateKey()).isEqualTo(templateRule.getRepositoryKey() + ":" + templateRule.getRuleKey());
}
+ @Test
+ public void do_not_return_external_rule() {
+ db.rules().insert(r -> r.setIsExternal(true));
+ indexRules();
+
+ SearchResponse result = ws.newRequest().executeProtobuf(SearchResponse.class);
+
+ assertThat(result.getTotal()).isZero();
+ assertThat(result.getRulesCount()).isZero();
+ }
+
@Test
public void search_all_active_rules() {
OrganizationDto organization = db.organizations().insert();
import org.junit.rules.ExpectedException;
import org.sonar.api.resources.Languages;
import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.RuleType;
import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbTester;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.text.MacroInterpreter;
import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.Common;
import org.sonarqube.ws.Rules;
import org.sonarqube.ws.Rules.Rule;
import org.sonarqube.ws.Rules.ShowResponse;
import static org.sonar.server.rule.ws.ShowAction.PARAM_ACTIVES;
import static org.sonar.server.rule.ws.ShowAction.PARAM_KEY;
import static org.sonar.server.rule.ws.ShowAction.PARAM_ORGANIZATION;
+import static org.sonarqube.ws.Common.RuleType.UNKNOWN;
+import static org.sonarqube.ws.Common.RuleType.VULNERABILITY;
public class ShowActionTest {
Rule resultRule = result.getRule();
assertThat(resultRule.getDefaultRemFnType()).isEqualTo("LINEAR_OFFSET");
+ assertThat(resultRule.getDefaultRemFnType()).isEqualTo("LINEAR_OFFSET");
assertThat(resultRule.getDefaultRemFnGapMultiplier()).isEqualTo("5d");
assertThat(resultRule.getDefaultRemFnBaseEffort()).isEqualTo("10h");
assertThat(resultRule.getRemFnType()).isEqualTo("CONSTANT_ISSUE");
verify(macroInterpreter).interpret("<div>line1<br/>line2</div>");
}
+ @Test
+ public void show_external_rule() {
+ RuleDefinitionDto externalRule = db.rules().insert(r -> r
+ .setIsExternal(true)
+ .setName("ext rule name"));
+
+ ShowResponse result = ws.newRequest()
+ .setParam(PARAM_KEY, externalRule.getKey().toString())
+ .executeProtobuf(ShowResponse.class);
+
+ Rule resultRule = result.getRule();
+ assertThat(resultRule.getName()).isEqualTo("ext rule name");
+ }
+
+ @Test
+ public void show_adhoc_rule() {
+ OrganizationDto organization = db.organizations().insert();
+ RuleDefinitionDto externalRule = db.rules().insert(r -> r
+ .setIsExternal(true)
+ .setIsAdHoc(true));
+ RuleMetadataDto metadata = db.rules().insertOrUpdateMetadata(externalRule, organization, m -> m
+ .setAdHocName("adhoc name")
+ .setAdHocDescription("<div>desc</div>")
+ .setAdHocSeverity(Severity.BLOCKER)
+ .setAdHocType(RuleType.VULNERABILITY)
+ .setNoteData(null)
+ .setNoteUserUuid(null));
+ doReturn("<div>desc2</div>").when(macroInterpreter).interpret(metadata.getAdHocDescription());
+
+ ShowResponse result = ws.newRequest()
+ .setParam(PARAM_KEY, externalRule.getKey().toString())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .executeProtobuf(ShowResponse.class);
+
+ Rule resultRule = result.getRule();
+ assertThat(resultRule)
+ .extracting(Rule::getName, Rule::getHtmlDesc, Rule::getSeverity, Rule::getType)
+ .containsExactlyInAnyOrder("adhoc name", "<div>desc2</div>", Severity.BLOCKER, VULNERABILITY);
+ }
+
+ @Test
+ public void ignore_predefined_info_on_adhoc_rule() {
+ OrganizationDto organization = db.organizations().insert();
+ RuleDefinitionDto externalRule = db.rules().insert(r -> r
+ .setIsExternal(true)
+ .setIsAdHoc(true)
+ .setName("predefined name")
+ .setDescription("<div>predefined desc</div>")
+ .setSeverity(Severity.BLOCKER)
+ .setType(RuleType.VULNERABILITY));
+ RuleMetadataDto metadata = db.rules().insertOrUpdateMetadata(externalRule, organization, m -> m
+ .setAdHocName("adhoc name")
+ .setAdHocDescription("<div>adhoc desc</div>")
+ .setAdHocSeverity(Severity.MAJOR)
+ .setAdHocType(RuleType.CODE_SMELL)
+ .setNoteData(null)
+ .setNoteUserUuid(null));
+ doReturn("<div>adhoc desc</div>").when(macroInterpreter).interpret(metadata.getAdHocDescription());
+
+ ShowResponse result = ws.newRequest()
+ .setParam(PARAM_KEY, externalRule.getKey().toString())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .executeProtobuf(ShowResponse.class);
+
+ Rule resultRule = result.getRule();
+ assertThat(resultRule)
+ .extracting(Rule::getName, Rule::getHtmlDesc, Rule::getSeverity, Rule::getType)
+ .containsExactlyInAnyOrder("adhoc name", "<div>adhoc desc</div>", Severity.MAJOR, Common.RuleType.CODE_SMELL);
+ }
+
+ @Test
+ public void adhoc_info_are_empty_when_no_metadata() {
+ OrganizationDto organization = db.organizations().insert();
+ RuleDefinitionDto externalRule = db.rules().insert(r -> r
+ .setIsExternal(true)
+ .setIsAdHoc(true)
+ .setName(null)
+ .setDescription(null)
+ .setDescriptionFormat(null)
+ .setSeverity((String) null)
+ .setType(0));
+
+ ShowResponse result = ws.newRequest()
+ .setParam(PARAM_KEY, externalRule.getKey().toString())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
+ .executeProtobuf(ShowResponse.class);
+
+ Rule resultRule = result.getRule();
+ assertThat(resultRule)
+ .extracting(Rule::hasName, Rule::hasHtmlDesc, Rule::hasSeverity, Rule::getType)
+ .containsExactlyInAnyOrder(false, false, false, UNKNOWN);
+ }
+
@Test
public void show_rule_with_activation() {
OrganizationDto organization = db.organizations().insert();