]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-16361 adapt rule indexing to index multiple section description
authorAurelien Poscia <aurelien.poscia@sonarsource.com>
Thu, 5 May 2022 14:28:32 +0000 (16:28 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 9 May 2022 20:02:59 +0000 (20:02 +0000)
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleForIndexingDto.java
server/sonar-server-common/src/main/java/org/sonar/server/rule/HotspotRuleDescription.java
server/sonar-server-common/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java
server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleDoc.java
server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexer.java
server/sonar-server-common/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java
server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleDocTest.java [new file with mode: 0644]
server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexerTest.java

index cdc6b8d7844ae1719728dbd0b94bbdd2b36adfd4..e7d7aa4e43b9d13fd585e3b5ce307e7eed9bf744 100644 (file)
@@ -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<RuleDescriptionSectionDto> 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;
   }
index 8b09f8ca59bc6d5042763aad1add9cf5fbc8f703..82b09178a84154efa12db5f69a72435501240deb 100644 (file)
@@ -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;
index e4f7aced0880664822b5304cdc1e6006e1a6acb8..2de9e1fca838e695c3b222220e0838172461b1ab 100644 (file)
@@ -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<RuleDescriptionSectionDto> ruleDescriptionSectionDtos = ruleForIndexingDto.getRuleDescriptionSectionsDtos();
-    return retrieveDescription(ruleDescriptionSectionDtos, ruleForIndexingDto.getRuleKey().toString(), ruleForIndexingDto.getDescriptionFormat());
-  }
-
   private static String retrieveDescription(Collection<RuleDescriptionSectionDto> ruleDescriptionSectionDtos,
     String ruleKey, RuleDto.Format descriptionFormat) {
     Optional<RuleDescriptionSectionDto> ruleDescriptionSectionDto = findDefaultDescription(ruleDescriptionSectionDtos);
@@ -58,7 +49,6 @@ public class RuleDescriptionFormatter {
       .orElse(null);
   }
 
-
   private static Optional<RuleDescriptionSectionDto> findDefaultDescription(Collection<RuleDescriptionSectionDto> ruleDescriptionSectionDtos) {
     return ruleDescriptionSectionDtos.stream()
       .filter(RuleDescriptionSectionDto::isDefault)
index 292dbfb30a8cbb0c85c38932859ef7c2b85c6ecf..e9cc6b74875ae2812a34b18a6273d38c61c050a7 100644 (file)
@@ -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;
   }
 }
index 80ba06360dddfc7acfb4105a377119b1b7b19553..da9fa447957b19d6129a75a9d87a5a9852fe27ba 100644 (file)
@@ -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<String> field) {
-    return field.map(t -> "ok").orElse("missing");
-  }
 
   private BulkIndexer createBulkIndexer(Size bulkSize, IndexingListener listener) {
     return new BulkIndexer(esClient, TYPE_RULE, bulkSize, listener);
index c63f3ebbe8bd0e512176b1591ffbd2f06c9b6e59..7c0879424c0be2a0ec0a58ca3afd92544db3a50d 100644 (file)
  */
 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<RuleDescriptionSectionDto> 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<RuleDescriptionSectionDto> 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<RuleDescriptionSectionDto> 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 (file)
index 0000000..93d4a1e
--- /dev/null
@@ -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", "<p>html content 1</p>");
+    RuleDescriptionSectionDto section2 = buildRuleDescriptionSectionDto("section2", "<p>html content 2</p>");
+    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();
+  }
+}
index 87dc8cb23320b6dee4ce4809b4e9c1c9067b432b..e1aa5e079cf61a7fd3ff5114a30a8a1a764731e9 100644 (file)
@@ -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<RuleDoc> 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<RuleDoc> ruleDocs = es.getDocuments(TYPE_RULE, RuleDoc.class);
+    assertThat(ruleDocs).hasSize(1);
+    assertThat(ruleDocs.iterator().next().htmlDescription())
+      .isEqualTo("acme<br/>&lt;h2&gt;Ask Yourself Whether&lt;/h2&gt;<br/>bar<br/>"
+        + "&lt;h2&gt;Recommended Secure Coding Practices&lt;/h2&gt;<br/>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" +
-        "<h2>Ask Yourself Whether</h2>\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(), "<h2>Ask Yourself Whether</h2>\n" +
-        "bar\n" +
-        "<h2>Recommended Secure Coding Practices</h2>\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" +
-        "<h2>Recommended Secure Coding Practices</h2>\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()));
-  }
 }