From 7c886613a7fe113c15cd09d4341579eb9c072feb Mon Sep 17 00:00:00 2001 From: Aurelien Poscia Date: Thu, 5 May 2022 16:28:32 +0200 Subject: [PATCH] SONAR-16361 adapt rule indexing to index multiple section description --- .../org/sonar/db/rule/RuleForIndexingDto.java | 12 -- .../server/rule/HotspotRuleDescription.java | 5 - .../server/rule/RuleDescriptionFormatter.java | 10 -- .../org/sonar/server/rule/index/RuleDoc.java | 39 ++++-- .../sonar/server/rule/index/RuleIndexer.java | 15 --- .../rule/RuleDescriptionFormatterTest.java | 39 ------ .../sonar/server/rule/index/RuleDocTest.java | 125 ++++++++++++++++++ .../server/rule/index/RuleIndexerTest.java | 113 ++++++---------- 8 files changed, 191 insertions(+), 167 deletions(-) create mode 100644 server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleDocTest.java diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleForIndexingDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleForIndexingDto.java index cdc6b8d7844..e7d7aa4e43b 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleForIndexingDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleForIndexingDto.java @@ -23,15 +23,12 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Sets; import java.util.Collections; import java.util.HashSet; -import java.util.Optional; import java.util.Set; import javax.annotation.CheckForNull; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; import org.sonar.api.rules.RuleType; -import static org.sonar.db.rule.RuleDescriptionSectionDto.DEFAULT_KEY; - public class RuleForIndexingDto { private String uuid; @@ -196,15 +193,6 @@ public class RuleForIndexingDto { this.ruleDescriptionSectionsDtos = ruleDescriptionSectionsDtos; } - private Optional findExistingSectionWithSameKey(String ruleDescriptionSectionKey) { - return ruleDescriptionSectionsDtos.stream().filter(section -> section.getKey().equals(ruleDescriptionSectionKey)).findAny(); - } - - @CheckForNull - public RuleDescriptionSectionDto getDefaultRuleDescriptionSectionDto() { - return findExistingSectionWithSameKey(DEFAULT_KEY).orElse(null); - } - public void setTemplateRuleKey(String templateRuleKey) { this.templateRuleKey = templateRuleKey; } diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/HotspotRuleDescription.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/HotspotRuleDescription.java index 8b09f8ca59b..82b09178a84 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/HotspotRuleDescription.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/HotspotRuleDescription.java @@ -23,7 +23,6 @@ import java.util.Optional; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.db.rule.RuleDto; -import org.sonar.db.rule.RuleForIndexingDto; import static java.util.Optional.ofNullable; @@ -52,10 +51,6 @@ public class HotspotRuleDescription { return from(description); } - public static HotspotRuleDescription from(RuleForIndexingDto dto) { - return from(RuleDescriptionFormatter.getDescriptionAsHtml(dto)); - } - private static HotspotRuleDescription from(@Nullable String description) { if (description == null) { return NO_DESCRIPTION; diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java index e4f7aced088..2de9e1fca83 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java @@ -24,7 +24,6 @@ import java.util.Objects; import java.util.Optional; import org.sonar.db.rule.RuleDescriptionSectionDto; import org.sonar.db.rule.RuleDto; -import org.sonar.db.rule.RuleForIndexingDto; import org.sonar.markdown.Markdown; import static com.google.common.collect.MoreCollectors.toOptional; @@ -42,14 +41,6 @@ public class RuleDescriptionFormatter { return retrieveDescription(ruleDescriptionSectionDtos, ruleDto.getRuleKey(), Objects.requireNonNull(ruleDto.getDescriptionFormat())); } - public static String getDescriptionAsHtml(RuleForIndexingDto ruleForIndexingDto) { - if (ruleForIndexingDto.getDescriptionFormat() == null) { - return null; - } - Collection ruleDescriptionSectionDtos = ruleForIndexingDto.getRuleDescriptionSectionsDtos(); - return retrieveDescription(ruleDescriptionSectionDtos, ruleForIndexingDto.getRuleKey().toString(), ruleForIndexingDto.getDescriptionFormat()); - } - private static String retrieveDescription(Collection ruleDescriptionSectionDtos, String ruleKey, RuleDto.Format descriptionFormat) { Optional ruleDescriptionSectionDto = findDefaultDescription(ruleDescriptionSectionDtos); @@ -58,7 +49,6 @@ public class RuleDescriptionFormatter { .orElse(null); } - private static Optional findDefaultDescription(Collection ruleDescriptionSectionDtos) { return ruleDescriptionSectionDtos.stream() .filter(RuleDescriptionSectionDto::isDefault) diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleDoc.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleDoc.java index 292dbfb30a8..e9cc6b74875 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleDoc.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleDoc.java @@ -33,14 +33,15 @@ import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; import org.sonar.api.rules.RuleType; +import org.sonar.db.rule.RuleDescriptionSectionDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleForIndexingDto; import org.sonar.markdown.Markdown; import org.sonar.server.es.BaseDoc; -import org.sonar.server.rule.RuleDescriptionFormatter; import org.sonar.server.security.SecurityStandards; import org.sonar.server.security.SecurityStandards.SQCategory; +import static java.util.stream.Collectors.joining; import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_RULE; /** @@ -259,7 +260,11 @@ public class RuleDoc extends BaseDoc { @CheckForNull public RuleType type() { - return RuleType.valueOfNullable(getNullableField(RuleIndexDefinition.FIELD_RULE_TYPE)); + String type = getNullableField(RuleIndexDefinition.FIELD_RULE_TYPE); + if (type == null) { + return null; + } + return RuleType.valueOf(type); } public RuleDoc setType(@Nullable RuleType ruleType) { @@ -291,7 +296,7 @@ public class RuleDoc extends BaseDoc { } public static RuleDoc of(RuleForIndexingDto dto, SecurityStandards securityStandards) { - RuleDoc ruleDoc = new RuleDoc() + return new RuleDoc() .setUuid(dto.getUuid()) .setKey(dto.getRuleKey().toString()) .setRepository(dto.getRepository()) @@ -311,16 +316,30 @@ public class RuleDoc extends BaseDoc { .setType(dto.getTypeAsRuleType()) .setCreatedAt(dto.getCreatedAt()) .setTags(Sets.union(dto.getTags(), dto.getSystemTags())) - .setUpdatedAt(dto.getUpdatedAt()); + .setUpdatedAt(dto.getUpdatedAt()) + .setHtmlDescription(getConcatenatedSectionsInHtml(dto)) + .setTemplateKey(getRuleKey(dto)); + } + @CheckForNull + private static String getRuleKey(RuleForIndexingDto dto) { if (dto.getTemplateRuleKey() != null && dto.getTemplateRepository() != null) { - ruleDoc.setTemplateKey(RuleKey.of(dto.getTemplateRepository(), dto.getTemplateRuleKey()).toString()); - } else { - ruleDoc.setTemplateKey(null); + return RuleKey.of(dto.getTemplateRepository(), dto.getTemplateRuleKey()).toString(); } + return null; + } - String descriptionAsHtml = RuleDescriptionFormatter.getDescriptionAsHtml(dto); - ruleDoc.setHtmlDescription(descriptionAsHtml); - return ruleDoc; + private static String getConcatenatedSectionsInHtml(RuleForIndexingDto dto) { + return dto.getRuleDescriptionSectionsDtos().stream() + .map(RuleDescriptionSectionDto::getContent) + .map(content -> convertToHtmlIfNecessary(dto.getDescriptionFormat(), content)) + .collect(joining(" ")); + } + + private static String convertToHtmlIfNecessary(RuleDto.Format format, String content) { + if (RuleDto.Format.MARKDOWN.equals(format)) { + return Markdown.convertToHtml(content); + } + return content; } } diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexer.java b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexer.java index 80ba06360dd..da9fa447957 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexer.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexer.java @@ -26,7 +26,6 @@ import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Stream; -import org.sonar.api.rules.RuleType; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.core.util.stream.MoreCollectors; @@ -42,7 +41,6 @@ import org.sonar.server.es.IndexingListener; import org.sonar.server.es.IndexingResult; import org.sonar.server.es.OneToOneResilientIndexingListener; import org.sonar.server.es.ResilientIndexer; -import org.sonar.server.rule.HotspotRuleDescription; import org.sonar.server.security.SecurityStandards; import static java.util.Arrays.asList; @@ -162,22 +160,9 @@ public class RuleIndexer implements ResilientIndexer { .sorted(SQ_CATEGORY_KEYS_ORDERING) .collect(joining(", "))); } - if (dto.getTypeAsRuleType() == RuleType.SECURITY_HOTSPOT) { - HotspotRuleDescription ruleDescription = HotspotRuleDescription.from(dto); - if (!ruleDescription.isComplete()) { - LOG.debug( - "Description of Security Hotspot Rule {} can't be fully parsed: What is the risk?={}, Are you vulnerable?={}, How to fix it={}", - dto.getRuleKey(), - toOkMissing(ruleDescription.getRisk()), toOkMissing(ruleDescription.getVulnerable()), - toOkMissing(ruleDescription.getFixIt())); - } - } return RuleDoc.of(dto, securityStandards); } - private static String toOkMissing(Optional field) { - return field.map(t -> "ok").orElse("missing"); - } private BulkIndexer createBulkIndexer(Size bulkSize, IndexingListener listener) { return new BulkIndexer(esClient, TYPE_RULE, bulkSize, listener); diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java index c63f3ebbe8b..7c0879424c0 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java @@ -19,14 +19,9 @@ */ package org.sonar.server.rule; -import com.google.common.collect.Sets; -import java.util.Collections; -import java.util.Set; -import org.jetbrains.annotations.NotNull; import org.junit.Test; import org.sonar.db.rule.RuleDescriptionSectionDto; import org.sonar.db.rule.RuleDto; -import org.sonar.db.rule.RuleForIndexingDto; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.db.rule.RuleDescriptionSectionDto.createDefaultRuleDescriptionSection; @@ -65,38 +60,4 @@ public class RuleDescriptionFormatterTest { assertThat(result).isNull(); } - @Test - public void getHtmlDescriptionForRuleForIndexingDtoAsIs() { - Set sectionsDtos = Sets.newHashSet( - createDefaultRuleDescriptionSection("uuid", HTML_SECTION.getContent())); - RuleForIndexingDto rule = createRuleForIndexingDto(sectionsDtos, RuleDto.Format.HTML); - String html = RuleDescriptionFormatter.getDescriptionAsHtml(rule); - assertThat(html).isEqualTo(HTML_SECTION.getContent()); - } - - @Test - public void handleEmptyDescriptionForRuleForIndexingDto() { - RuleForIndexingDto rule = createRuleForIndexingDto(Collections.emptySet(), RuleDto.Format.HTML); - String result = RuleDescriptionFormatter.getDescriptionAsHtml(rule); - assertThat(result).isNull(); - } - - @Test - public void handleNullDescriptionFormatForRuleForIndexingDto() { - Set sectionsDtos = Sets.newHashSet( - createDefaultRuleDescriptionSection("uuid", HTML_SECTION.getContent())); - RuleForIndexingDto rule = createRuleForIndexingDto(sectionsDtos, null); - String result = RuleDescriptionFormatter.getDescriptionAsHtml(rule); - assertThat(result).isNull(); - } - - @NotNull - private static RuleForIndexingDto createRuleForIndexingDto(Set sectionsDtos, RuleDto.Format format) { - RuleForIndexingDto rule = new RuleForIndexingDto(); - rule.setRuleDescriptionSectionsDtos(sectionsDtos); - rule.setDescriptionFormat(format); - rule.setRepository("repository"); - rule.setPluginRuleKey("pluginKey"); - return rule; - } } diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleDocTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleDocTest.java new file mode 100644 index 00000000000..93d4a1e3530 --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleDocTest.java @@ -0,0 +1,125 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 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.rule.index; + +import org.junit.Test; +import org.sonar.db.rule.RuleDescriptionSectionDto; +import org.sonar.db.rule.RuleDto; +import org.sonar.db.rule.RuleForIndexingDto; +import org.sonar.db.rule.RuleTesting; +import org.sonar.server.security.SecurityStandards; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.markdown.Markdown.convertToHtml; +import static org.sonar.server.security.SecurityStandards.fromSecurityStandards; + +public class RuleDocTest { + + @Test + public void ruleDocOf_mapsFieldCorrectly() { + RuleDto ruleDto = RuleTesting.newRule(); + RuleForIndexingDto ruleForIndexingDto = RuleForIndexingDto.fromRuleDto(ruleDto); + ruleForIndexingDto.setTemplateRuleKey("templateKey"); + ruleForIndexingDto.setTemplateRepository("repoKey"); + SecurityStandards securityStandards = fromSecurityStandards(ruleDto.getSecurityStandards()); + + RuleDoc ruleDoc = RuleDoc.of(ruleForIndexingDto, securityStandards); + + assertThat(ruleDoc.getId()).isEqualTo(ruleDto.getUuid()); + assertThat(ruleDoc.key()).isEqualTo(ruleForIndexingDto.getRuleKey()); + assertThat(ruleDoc.repository()).isEqualTo(ruleForIndexingDto.getRepository()); + assertThat(ruleDoc.internalKey()).isEqualTo(ruleForIndexingDto.getInternalKey()); + assertThat(ruleDoc.isExternal()).isEqualTo(ruleForIndexingDto.isExternal()); + assertThat(ruleDoc.language()).isEqualTo(ruleForIndexingDto.getLanguage()); + assertThat(ruleDoc.getCwe()).isEqualTo(securityStandards.getCwe()); + assertThat(ruleDoc.getOwaspTop10()).isEqualTo(securityStandards.getOwaspTop10()); + assertThat(ruleDoc.getOwaspTop10For2021()).isEqualTo(securityStandards.getOwaspTop10For2021()); + assertThat(ruleDoc.getSansTop25()).isEqualTo(securityStandards.getSansTop25()); + assertThat(ruleDoc.getSonarSourceSecurityCategory()).isEqualTo(securityStandards.getSqCategory()); + assertThat(ruleDoc.name()).isEqualTo(ruleForIndexingDto.getName()); + assertThat(ruleDoc.ruleKey()).isEqualTo(ruleForIndexingDto.getPluginRuleKey()); + assertThat(ruleDoc.severity()).isEqualTo(ruleForIndexingDto.getSeverityAsString()); + assertThat(ruleDoc.status()).isEqualTo(ruleForIndexingDto.getStatus()); + assertThat(ruleDoc.type().name()).isEqualTo(ruleForIndexingDto.getTypeAsRuleType().name()); + assertThat(ruleDoc.createdAt()).isEqualTo(ruleForIndexingDto.getCreatedAt()); + assertThat(ruleDoc.getTags()).isEqualTo(ruleForIndexingDto.getSystemTags()); + assertThat(ruleDoc.updatedAt()).isEqualTo(ruleForIndexingDto.getUpdatedAt()); + assertThat(ruleDoc.templateKey().repository()).isEqualTo(ruleForIndexingDto.getTemplateRepository()); + assertThat(ruleDoc.templateKey().rule()).isEqualTo(ruleForIndexingDto.getTemplateRuleKey()); + + } + + @Test + public void ruleDocOf_whenGivenNoHtmlSections_hasEmptyStringInHtmlDescription() { + RuleDto ruleDto = RuleTesting.newRule(); + ruleDto.setDescriptionFormat(RuleDto.Format.HTML); + ruleDto.getRuleDescriptionSectionDtos().clear(); + + RuleForIndexingDto ruleForIndexingDto = RuleForIndexingDto.fromRuleDto(ruleDto); + SecurityStandards securityStandards = fromSecurityStandards(ruleDto.getSecurityStandards()); + + RuleDoc ruleDoc = RuleDoc.of(ruleForIndexingDto, securityStandards); + assertThat(ruleDoc.htmlDescription()).isEmpty(); + } + + @Test + public void ruleDocOf_whenGivenMultipleHtmlSections_hasConcatenationInHtmlDescription() { + RuleDto ruleDto = RuleTesting.newRule(); + ruleDto.setDescriptionFormat(RuleDto.Format.HTML); + ruleDto.getRuleDescriptionSectionDtos().clear(); + RuleDescriptionSectionDto section1 = buildRuleDescriptionSectionDto("section1", "

html content 1

"); + RuleDescriptionSectionDto section2 = buildRuleDescriptionSectionDto("section2", "

html content 2

"); + ruleDto.addRuleDescriptionSectionDto(section1); + ruleDto.addRuleDescriptionSectionDto(section2); + + RuleForIndexingDto ruleForIndexingDto = RuleForIndexingDto.fromRuleDto(ruleDto); + SecurityStandards securityStandards = fromSecurityStandards(ruleDto.getSecurityStandards()); + + RuleDoc ruleDoc = RuleDoc.of(ruleForIndexingDto, securityStandards); + assertThat(ruleDoc.htmlDescription()) + .contains(section1.getContent()) + .contains(section2.getContent()) + .hasSameSizeAs(section1.getContent() + " " + section2.getContent()); + } + + @Test + public void ruleDocOf_whenGivenMultipleMarkdownSections_transformToHtmlAndConcatenatesInHtmlDescription() { + RuleDto ruleDto = RuleTesting.newRule(); + ruleDto.setDescriptionFormat(RuleDto.Format.MARKDOWN); + ruleDto.getRuleDescriptionSectionDtos().clear(); + RuleDescriptionSectionDto section1 = buildRuleDescriptionSectionDto("section1", "*html content 1*"); + RuleDescriptionSectionDto section2 = buildRuleDescriptionSectionDto("section2", "*html content 2*"); + ruleDto.addRuleDescriptionSectionDto(section1); + ruleDto.addRuleDescriptionSectionDto(section2); + + RuleForIndexingDto ruleForIndexingDto = RuleForIndexingDto.fromRuleDto(ruleDto); + SecurityStandards securityStandards = fromSecurityStandards(ruleDto.getSecurityStandards()); + + RuleDoc ruleDoc = RuleDoc.of(ruleForIndexingDto, securityStandards); + assertThat(ruleDoc.htmlDescription()) + .contains(convertToHtml(section1.getContent())) + .contains(convertToHtml(section2.getContent())) + .hasSameSizeAs(convertToHtml(section1.getContent()) + " " + convertToHtml(section2.getContent())); + } + + private static RuleDescriptionSectionDto buildRuleDescriptionSectionDto(String key, String content) { + return RuleDescriptionSectionDto.builder().key(key).content(content).build(); + } +} diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexerTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexerTest.java index 87dc8cb2332..e1aa5e079cf 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexerTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexerTest.java @@ -24,6 +24,7 @@ import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.util.EnumSet; +import java.util.List; import java.util.Random; import java.util.Set; import java.util.stream.IntStream; @@ -53,7 +54,6 @@ import static java.lang.String.format; import static java.util.Collections.emptyList; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toSet; -import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.db.rule.RuleDescriptionSectionDto.createDefaultRuleDescriptionSection; import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_RULE; @@ -71,6 +71,11 @@ public class RuleIndexerTest { private static final UuidFactoryFast uuidFactory = UuidFactoryFast.getInstance(); private static final RuleDescriptionSectionDto RULE_DESCRIPTION_SECTION_DTO = createDefaultRuleDescriptionSection(uuidFactory.create(), VALID_HOTSPOT_RULE_DESCRIPTION); + private static final RuleDescriptionSectionDto RULE_DESCRIPTION_SECTION_DTO2 = RuleDescriptionSectionDto.builder() + .uuid(uuidFactory.create()) + .key("section2") + .content("rule descriptions section 2") + .build(); @Rule public EsTester es = EsTester.create(); @@ -139,6 +144,37 @@ public class RuleIndexerTest { assertThat(es.countDocuments(TYPE_RULE)).isOne(); } + @Test + public void index_long_rule_with_several_sections() { + RuleDto rule = dbTester.rules().insert(r -> { + r.addOrReplaceRuleDescriptionSectionDto(RULE_DESCRIPTION_SECTION_DTO); + r.addRuleDescriptionSectionDto(RULE_DESCRIPTION_SECTION_DTO2); + }); + + underTest.commitAndIndex(dbTester.getSession(), rule.getUuid()); + + List ruleDocs = es.getDocuments(TYPE_RULE, RuleDoc.class); + assertThat(ruleDocs).hasSize(1); + assertThat(ruleDocs.iterator().next().htmlDescription()) + .isEqualTo(RULE_DESCRIPTION_SECTION_DTO.getContent() + " " + RULE_DESCRIPTION_SECTION_DTO2.getContent()); + } + + @Test + public void index_long_rule_with_section_in_markdown() { + RuleDto rule = dbTester.rules().insert(r -> { + r.setDescriptionFormat(RuleDto.Format.MARKDOWN); + r.addOrReplaceRuleDescriptionSectionDto(RULE_DESCRIPTION_SECTION_DTO); + }); + + underTest.commitAndIndex(dbTester.getSession(), rule.getUuid()); + + List ruleDocs = es.getDocuments(TYPE_RULE, RuleDoc.class); + assertThat(ruleDocs).hasSize(1); + assertThat(ruleDocs.iterator().next().htmlDescription()) + .isEqualTo("acme
<h2>Ask Yourself Whether</h2>
bar
" + + "<h2>Recommended Secure Coding Practices</h2>
foo"); + } + @Test @UseDataProvider("twoDifferentCategoriesButOTHERS") public void log_debug_if_hotspot_rule_maps_to_multiple_SQCategories(SQCategory sqCategory1, SQCategory sqCategory2) { @@ -179,79 +215,4 @@ public class RuleIndexerTest { }; } - @Test - public void log_debug_when_hotspot_rule_no_description () { - RuleDto rule = dbTester.rules().insert(RuleTesting.newRuleWithoutDescriptionSection() - .setType(RuleType.SECURITY_HOTSPOT)); - underTest.commitAndIndex(dbTester.getSession(), rule.getUuid()); - - assertThat(logTester.getLogs()).hasSize(1); - assertThat(logTester.logs(LoggerLevel.DEBUG).get(0)) - .isEqualTo(format( - "Description of Security Hotspot Rule %s can't be fully parsed: What is the risk?=missing, Are you vulnerable?=missing, How to fix it=missing", - rule.getKey())); - } - - @Test - public void log_debug_when_hotspot_rule_description_has_none_of_the_key_titles() { - RuleDto rule = dbTester.rules().insert(RuleTesting.newRuleWithoutDescriptionSection() - .setType(RuleType.SECURITY_HOTSPOT) - .addRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), randomAlphabetic(30)))); - underTest.commitAndIndex(dbTester.getSession(), rule.getUuid()); - - assertThat(logTester.getLogs()).hasSize(1); - assertThat(logTester.logs(LoggerLevel.DEBUG).get(0)) - .isEqualTo(format( - "Description of Security Hotspot Rule %s can't be fully parsed: What is the risk?=ok, Are you vulnerable?=missing, How to fix it=missing", - rule.getKey())); - } - - @Test - public void log_debug_when_hotspot_rule_description_is_missing_fixIt_tab_content() { - RuleDto rule = dbTester.rules().insert(RuleTesting.newRuleWithoutDescriptionSection() - .setType(RuleType.SECURITY_HOTSPOT) - .addRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "bar\n" + - "

Ask Yourself Whether

\n" + - "foo"))); - underTest.commitAndIndex(dbTester.getSession(), rule.getUuid()); - - assertThat(logTester.getLogs()).hasSize(1); - assertThat(logTester.logs(LoggerLevel.DEBUG).get(0)) - .isEqualTo(format( - "Description of Security Hotspot Rule %s can't be fully parsed: What is the risk?=ok, Are you vulnerable?=ok, How to fix it=missing", - rule.getKey())); - } - - @Test - public void log_debug_when_hotspot_rule_description_is_missing_risk_tab_content() { - RuleDto rule = dbTester.rules().insert(RuleTesting.newRuleWithoutDescriptionSection() - .setType(RuleType.SECURITY_HOTSPOT) - .addRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "

Ask Yourself Whether

\n" + - "bar\n" + - "

Recommended Secure Coding Practices

\n" + - "foo"))); - underTest.commitAndIndex(dbTester.getSession(), rule.getUuid()); - - assertThat(logTester.getLogs()).hasSize(1); - assertThat(logTester.logs(LoggerLevel.DEBUG).get(0)) - .isEqualTo(format( - "Description of Security Hotspot Rule %s can't be fully parsed: What is the risk?=missing, Are you vulnerable?=ok, How to fix it=ok", - rule.getKey())); - } - - @Test - public void log_debug_when_hotspot_rule_description_is_missing_vulnerable_tab_content() { - RuleDto rule = dbTester.rules().insert(RuleTesting.newRuleWithoutDescriptionSection() - .setType(RuleType.SECURITY_HOTSPOT) - .addRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "bar\n" + - "

Recommended Secure Coding Practices

\n" + - "foo"))); - underTest.commitAndIndex(dbTester.getSession(), rule.getUuid()); - - assertThat(logTester.getLogs()).hasSize(1); - assertThat(logTester.logs(LoggerLevel.DEBUG).get(0)) - .isEqualTo(format( - "Description of Security Hotspot Rule %s can't be fully parsed: What is the risk?=ok, Are you vulnerable?=missing, How to fix it=ok", - rule.getKey())); - } } -- 2.39.5