소스 검색

SONAR-16518 Add context to RuleDescriptionSectionDto

tags/9.6.0.59041
Léo Geoffroy 2 년 전
부모
커밋
b207941149
21개의 변경된 파일409개의 추가작업 그리고 64개의 파일을 삭제
  1. 77
    0
      server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDescriptionSectionContextDto.java
  2. 27
    5
      server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDescriptionSectionDto.java
  3. 29
    14
      server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java
  4. 17
    3
      server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml
  5. 57
    5
      server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java
  6. 97
    0
      server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDescriptionSectionContextDtoTest.java
  7. 3
    2
      server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDescriptionSectionDtoTest.java
  8. 63
    0
      server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDtoTest.java
  9. 5
    5
      server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java
  10. 4
    3
      server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexerTest.java
  11. 9
    7
      server/sonar-webserver-core/src/main/java/org/sonar/server/rule/RegisterRules.java
  12. 1
    1
      server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java
  13. 1
    1
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleUpdater.java
  14. 2
    2
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java
  15. 2
    2
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java
  16. 2
    2
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/RuleCreatorTest.java
  17. 2
    2
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/RuleUpdaterTest.java
  18. 1
    1
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/CreateActionTest.java
  19. 6
    5
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java
  20. 2
    2
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java
  21. 2
    2
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/UpdateActionTest.java

+ 77
- 0
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDescriptionSectionContextDto.java 파일 보기

@@ -0,0 +1,77 @@
/*
* 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.db.rule;

import java.util.Objects;

import static org.apache.commons.lang.StringUtils.isNotEmpty;
import static org.sonar.api.utils.Preconditions.checkArgument;

public class RuleDescriptionSectionContextDto {

static final String KEY_MUST_BE_SET_ERROR = "key must be set";
static final String DISPLAY_NAME_MUST_BE_SET_ERROR = "displayName must be set";
private final String key;
private final String displayName;

private RuleDescriptionSectionContextDto(String key, String displayName) {
checkArgument(isNotEmpty(key), KEY_MUST_BE_SET_ERROR);
checkArgument(isNotEmpty(displayName), DISPLAY_NAME_MUST_BE_SET_ERROR);
this.key = key;
this.displayName = displayName;
}

public static RuleDescriptionSectionContextDto of(String key, String displayName) {
return new RuleDescriptionSectionContextDto(key, displayName);
}

public String getKey() {
return key;
}

public String getDisplayName() {
return displayName;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
RuleDescriptionSectionContextDto that = (RuleDescriptionSectionContextDto) o;
return getKey().equals(that.getKey()) && getDisplayName().equals(that.getDisplayName());
}

@Override
public int hashCode() {
return Objects.hash(getKey(), getDisplayName());
}

@Override
public String toString() {
return "RuleDescriptionSectionContextDto[" +
"key='" + key + '\'' +
", displayName='" + displayName + '\'' +
']';
}
}

+ 27
- 5
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDescriptionSectionDto.java 파일 보기

@@ -20,20 +20,27 @@
package org.sonar.db.rule;

import java.util.StringJoiner;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;

import static org.sonar.api.utils.Preconditions.checkArgument;

public class RuleDescriptionSectionDto {
public static final String DEFAULT_KEY = "default";

private final String uuid;
private final String key;
private final String content;
private String uuid;
private String key;
private String content;
private RuleDescriptionSectionContextDto context;

private RuleDescriptionSectionDto(String uuid, String key, String content) {
private RuleDescriptionSectionDto() {
}

private RuleDescriptionSectionDto(String uuid, String key, String content, @Nullable RuleDescriptionSectionContextDto context) {
this.uuid = uuid;
this.key = key;
this.content = content;
this.context = context;
}

public String getUuid() {
@@ -48,6 +55,11 @@ public class RuleDescriptionSectionDto {
return content;
}

@CheckForNull
public RuleDescriptionSectionContextDto getContext() {
return context;
}

public static RuleDescriptionSectionDto createDefaultRuleDescriptionSection(String uuid, String description) {
return RuleDescriptionSectionDto.builder()
.setDefault()
@@ -70,13 +82,17 @@ public class RuleDescriptionSectionDto {
.add("uuid='" + uuid + "'")
.add("key='" + key + "'")
.add("content='" + content + "'")
.add("context='" + context + "'")
.toString();
}



public static final class RuleDescriptionSectionDtoBuilder {
private String uuid;
private String key = null;
private String content;
private RuleDescriptionSectionContextDto context;

private RuleDescriptionSectionDtoBuilder() {
}
@@ -103,8 +119,14 @@ public class RuleDescriptionSectionDto {
return this;
}

public RuleDescriptionSectionDtoBuilder context(@Nullable RuleDescriptionSectionContextDto context) {
this.context = context;
return this;
}

public RuleDescriptionSectionDto build() {
return new RuleDescriptionSectionDto(uuid, key, content);
return new RuleDescriptionSectionDto(uuid, key, content, context);
}
}

}

+ 29
- 14
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java 파일 보기

@@ -19,11 +19,13 @@
*/
package org.sonar.db.rule;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -38,10 +40,13 @@ import org.sonar.api.rules.RuleType;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Collections.emptySet;
import static java.util.Optional.ofNullable;
import static org.sonar.db.rule.RuleDescriptionSectionDto.DEFAULT_KEY;

public class RuleDto {

static final String ERROR_MESSAGE_SECTION_ALREADY_EXISTS = "A section with key '%s' and context key '%s' already exists";

public enum Format {
HTML, MARKDOWN
}
@@ -56,7 +61,7 @@ public class RuleDto {
private String repositoryKey = null;
private String ruleKey = null;

private Set<RuleDescriptionSectionDto> ruleDescriptionSectionDtos = new HashSet<>();
private final Set<RuleDescriptionSectionDto> ruleDescriptionSectionDtos = new HashSet<>();

/**
* Description format can be null on external rule, otherwise it should never be null
@@ -198,7 +203,10 @@ public class RuleDto {

@CheckForNull
public RuleDescriptionSectionDto getDefaultRuleDescriptionSection() {
return findExistingSectionWithSameKey(DEFAULT_KEY).orElse(null);
return ruleDescriptionSectionDtos.stream()
.filter(ruleDesc -> ruleDesc.getKey().equals(DEFAULT_KEY))
.findAny()
.orElse(null);
}

public RuleDto replaceRuleDescriptionSectionDtos(Collection<RuleDescriptionSectionDto> ruleDescriptionSectionDtos) {
@@ -207,26 +215,33 @@ public class RuleDto {
return this;
}

@VisibleForTesting
public RuleDto replaceRuleDescriptionSectionDtos(RuleDescriptionSectionDto ruleDescriptionSectionDto) {
replaceRuleDescriptionSectionDtos(List.of(ruleDescriptionSectionDto));
return this;
}

public RuleDto addRuleDescriptionSectionDto(RuleDescriptionSectionDto ruleDescriptionSectionDto) {
checkArgument(sectionWithSameKeyShouldNotExist(ruleDescriptionSectionDto),
"A section with key %s already exists", ruleDescriptionSectionDto.getKey());
checkArgument(!hasDescriptionSectionWithSameKeyAndContext(ruleDescriptionSectionDto),
ERROR_MESSAGE_SECTION_ALREADY_EXISTS, ruleDescriptionSectionDto.getKey(),
Optional.ofNullable(ruleDescriptionSectionDto.getContext()).map(RuleDescriptionSectionContextDto::getKey).orElse(null));
ruleDescriptionSectionDtos.add(ruleDescriptionSectionDto);
return this;
}

private boolean sectionWithSameKeyShouldNotExist(RuleDescriptionSectionDto ruleDescriptionSectionDto) {
return findExistingSectionWithSameKey(ruleDescriptionSectionDto.getKey()).isEmpty();
private boolean hasDescriptionSectionWithSameKeyAndContext(RuleDescriptionSectionDto ruleDescriptionSectionDto) {
return ruleDescriptionSectionDtos.stream()
.anyMatch(ruleDesc -> hasSameKeyAndContextKey(ruleDescriptionSectionDto, ruleDesc));
}

public RuleDto addOrReplaceRuleDescriptionSectionDto(RuleDescriptionSectionDto ruleDescriptionSectionDto) {
Optional<RuleDescriptionSectionDto> existingSectionWithSameKey = findExistingSectionWithSameKey(ruleDescriptionSectionDto.getKey());
existingSectionWithSameKey.ifPresent(ruleDescriptionSectionDtos::remove);
ruleDescriptionSectionDtos.add(ruleDescriptionSectionDto);
return this;
}
private static boolean hasSameKeyAndContextKey(RuleDescriptionSectionDto ruleDescriptionSectionDto, RuleDescriptionSectionDto other) {
if (!ruleDescriptionSectionDto.getKey().equals(other.getKey())){
return false;
}

private Optional<RuleDescriptionSectionDto> findExistingSectionWithSameKey(String ruleDescriptionSectionKey) {
return ruleDescriptionSectionDtos.stream().filter(section -> section.getKey().equals(ruleDescriptionSectionKey)).findAny();
String contextKey = ofNullable(ruleDescriptionSectionDto.getContext()).map(RuleDescriptionSectionContextDto::getKey).orElse(null);
String otherContextKey = ofNullable(other.getContext()).map(RuleDescriptionSectionContextDto::getKey).orElse(null);
return Objects.equals(contextKey, otherContextKey);
}

@CheckForNull

+ 17
- 3
server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml 파일 보기

@@ -50,6 +50,8 @@
rds.content as "rds_content",
rds.uuid as "rds_uuid",
rds.kee as "rds_kee",
rds.context_key as "rds_contextKey",
rds.context_display_name as "rds_contextDisplayName",
r.uuid as "r_uuid",

<include refid="ruleColumns"/>
@@ -68,7 +70,14 @@

<collection property="ruleDescriptionSectionDtos" ofType="org.sonar.db.rule.RuleDescriptionSectionDto" autoMapping="true"
columnPrefix="rds_">
<id property="uuid" column="uuid"/>
<result property="key" column="kee"/>
<association property="context" javaType="org.sonar.db.rule.RuleDescriptionSectionContextDto" autoMapping="false">
<constructor>
<arg column="contextKey" javaType="String"/>
<arg column="contextDisplayName" javaType="String"/>
</constructor>
</association>
</collection>
</resultMap>

@@ -195,7 +204,8 @@
<foreach collection="languages" item="language" separator="," open="(" close=")">#{language, jdbcType=VARCHAR}</foreach>
</select>

<select id="selectByLanguage" parameterType="String" resultType="org.sonar.db.rule.RuleDto" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
<select id="selectByLanguage" parameterType="String" resultType="org.sonar.db.rule.RuleDto" fetchSize="${_scrollFetchSize}"
resultSetType="FORWARD_ONLY">
select
r.uuid as uuid,
<include refid="ruleColumns"/>
@@ -212,13 +222,17 @@
uuid,
rule_uuid,
kee,
content
content,
context_key,
context_display_name
)
values (
#{dto.uuid,jdbcType=VARCHAR},
#{ruleUuid,jdbcType=VARCHAR},
#{dto.key,jdbcType=VARCHAR},
#{dto.content,jdbcType=VARCHAR}
#{dto.content,jdbcType=VARCHAR},
#{dto.context.key,jdbcType=VARCHAR},
#{dto.context.displayName,jdbcType=VARCHAR}
)
</insert>


+ 57
- 5
server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java 파일 보기

@@ -83,7 +83,6 @@ public class RuleDaoTest {
}



@Test
public void selectByUuid() {
RuleDto ruleDto = db.rules().insert();
@@ -202,6 +201,7 @@ public class RuleDaoTest {
}

private void assertEquals(RuleDto actual, RuleDto expected) {

assertThat(actual.getUuid()).isEqualTo(expected.getUuid());
assertThat(actual.getRepositoryKey()).isEqualTo(expected.getRepositoryKey());
assertThat(actual.getRuleKey()).isEqualTo(expected.getRuleKey());
@@ -236,7 +236,7 @@ public class RuleDaoTest {
assertThat(actual.getAdHocSeverity()).isEqualTo(expected.getAdHocSeverity());
assertThat(actual.getAdHocType()).isEqualTo(expected.getAdHocType());
assertThat(actual.getRuleDescriptionSectionDtos()).usingRecursiveFieldByFieldElementComparator()
.isEqualTo(expected.getRuleDescriptionSectionDtos());
.containsExactlyInAnyOrderElementsOf(expected.getRuleDescriptionSectionDtos());
}

@Test
@@ -401,6 +401,35 @@ public class RuleDaoTest {
RuleQuery.create().withKey("S001").withConfigKey("S1").withRepositoryKey("java"))).hasSize(1);
}

@Test
public void insert_rule_with_description_section_context() {
RuleDto rule = db.rules().insert(r -> r
.addRuleDescriptionSectionDto(createDescriptionSectionWithContext("how_to_fix", "spring", "Spring")));

Optional<RuleDto> ruleDto = underTest.selectByUuid(rule.getUuid(), db.getSession());
assertEquals(ruleDto.get(), rule);
}

@NotNull
private static RuleDescriptionSectionDto createDescriptionSectionWithContext(String key, String contextKey, String contextDisplayName) {
return RuleDescriptionSectionDto.builder()
.uuid(UuidFactoryFast.getInstance().create())
.content("content")
.key(key)
.context(RuleDescriptionSectionContextDto.of(contextKey, contextDisplayName))
.build();
}

@Test
public void insert_rule_with_different_section_context() {
RuleDto rule = db.rules().insert(r -> r
.addRuleDescriptionSectionDto(createDescriptionSectionWithContext("how_to_fix", "spring", "Spring"))
.addRuleDescriptionSectionDto(createDescriptionSectionWithContext("how_to_fix", "myBatis", "My Batis")));

Optional<RuleDto> ruleDto = underTest.selectByUuid(rule.getUuid(), db.getSession());
assertEquals(ruleDto.get(), rule);
}

@Test
public void insert() {
RuleDescriptionSectionDto sectionDto = createDefaultRuleDescriptionSection();
@@ -552,7 +581,29 @@ public class RuleDaoTest {
.content(randomAlphanumeric(1000))
.build();

rule.addOrReplaceRuleDescriptionSectionDto(replacingSection);
rule.replaceRuleDescriptionSectionDtos(replacingSection);

underTest.update(db.getSession(), rule);
db.getSession().commit();

RuleDto ruleDto = underTest.selectOrFailByKey(db.getSession(), RuleKey.of(rule.getRepositoryKey(), rule.getRuleKey()));

assertThat(ruleDto.getRuleDescriptionSectionDtos())
.usingRecursiveFieldByFieldElementComparator()
.containsOnly(replacingSection);
}

@Test
public void update_rule_sections_replaces_section_with_context() {
RuleDto rule = db.rules().insert();
RuleDescriptionSectionDto existingSection = rule.getRuleDescriptionSectionDtos().iterator().next();
RuleDescriptionSectionDto replacingSection = RuleDescriptionSectionDto.builder()
.uuid(randomAlphanumeric(20))
.key(existingSection.getKey())
.content(randomAlphanumeric(1000))
.build();

rule.replaceRuleDescriptionSectionDtos(replacingSection);

underTest.update(db.getSession(), rule);
db.getSession().commit();
@@ -816,6 +867,7 @@ public class RuleDaoTest {
.key("DESC")
.uuid("uuid")
.content("my description")
.context(RuleDescriptionSectionContextDto.of("context key", "context display name"))
.build();
RuleDto r1 = db.rules().insert(r -> {
r.addRuleDescriptionSectionDto(ruleDescriptionSectionDto);
@@ -838,8 +890,8 @@ public class RuleDaoTest {
assertThat(firstRule.getRuleDescriptionSectionsDtos().stream()
.filter(s -> s.getKey().equals(ruleDescriptionSectionDto.getKey()))
.collect(MoreCollectors.onlyElement()))
.usingRecursiveComparison()
.isEqualTo(ruleDescriptionSectionDto);
.usingRecursiveComparison()
.isEqualTo(ruleDescriptionSectionDto);
assertThat(firstRule.getDescriptionFormat()).isEqualTo(r1.getDescriptionFormat());
assertThat(firstRule.getSeverity()).isEqualTo(r1.getSeverity());
assertThat(firstRule.getStatus()).isEqualTo(r1.getStatus());

+ 97
- 0
server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDescriptionSectionContextDtoTest.java 파일 보기

@@ -0,0 +1,97 @@
/*
* 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.db.rule;

import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.sonar.db.rule.RuleDescriptionSectionContextDto.DISPLAY_NAME_MUST_BE_SET_ERROR;
import static org.sonar.db.rule.RuleDescriptionSectionContextDto.KEY_MUST_BE_SET_ERROR;

public class RuleDescriptionSectionContextDtoTest {

private static final String CONTEXT_KEY = "key";
private static final String CONTEXT_DISPLAY_NAME = "displayName";

@Test
public void check_of_instantiate_object() {
RuleDescriptionSectionContextDto context = RuleDescriptionSectionContextDto.of(CONTEXT_KEY, CONTEXT_DISPLAY_NAME);

assertThat(context).extracting(RuleDescriptionSectionContextDto::getKey,
RuleDescriptionSectionContextDto::getDisplayName).contains(CONTEXT_KEY, CONTEXT_DISPLAY_NAME);
}

@Test
public void check_of_with_key_is_empty() {
assertThatThrownBy(() -> RuleDescriptionSectionContextDto.of("", CONTEXT_DISPLAY_NAME))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage(KEY_MUST_BE_SET_ERROR);
}

@Test
public void check_of_with_display_name_is_empty() {
assertThatThrownBy(() -> RuleDescriptionSectionContextDto.of(CONTEXT_KEY, ""))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage(DISPLAY_NAME_MUST_BE_SET_ERROR);
}

@Test
public void equals_with_equals_objects_should_return_true() {
RuleDescriptionSectionContextDto context1 = RuleDescriptionSectionContextDto.of(CONTEXT_KEY, CONTEXT_DISPLAY_NAME);
RuleDescriptionSectionContextDto context2 = RuleDescriptionSectionContextDto.of(CONTEXT_KEY, CONTEXT_DISPLAY_NAME);
assertThat(context1).isEqualTo(context2);
}

@Test
public void equals_with_same_objects_should_return_true() {
RuleDescriptionSectionContextDto context1 = RuleDescriptionSectionContextDto.of(CONTEXT_KEY, CONTEXT_DISPLAY_NAME);
assertThat(context1).isEqualTo(context1);
}
@Test
public void equals_with_one_null_objet_should_return_false() {
RuleDescriptionSectionContextDto context1 = RuleDescriptionSectionContextDto.of(CONTEXT_KEY, CONTEXT_DISPLAY_NAME);
assertThat(context1).isNotEqualTo(null);
}

@Test
public void equals_with_different_display_names_should_return_false() {
RuleDescriptionSectionContextDto context1 = RuleDescriptionSectionContextDto.of(CONTEXT_KEY, CONTEXT_DISPLAY_NAME);
RuleDescriptionSectionContextDto context2 = RuleDescriptionSectionContextDto.of(CONTEXT_KEY, CONTEXT_DISPLAY_NAME + "2");
assertThat(context1).isNotEqualTo(context2);
}

@Test
public void equals_with_different_context_keys_should_return_false() {
RuleDescriptionSectionContextDto context1 = RuleDescriptionSectionContextDto.of(CONTEXT_KEY, CONTEXT_DISPLAY_NAME);
RuleDescriptionSectionContextDto context2 = RuleDescriptionSectionContextDto.of(CONTEXT_KEY + "2", CONTEXT_DISPLAY_NAME);
assertThat(context1).isNotEqualTo(context2);
}

@Test
public void hashcode_with_equals_objects_should_return_same_hash() {
RuleDescriptionSectionContextDto context1 = RuleDescriptionSectionContextDto.of(CONTEXT_KEY, CONTEXT_DISPLAY_NAME);
RuleDescriptionSectionContextDto context2 = RuleDescriptionSectionContextDto.of(CONTEXT_KEY, CONTEXT_DISPLAY_NAME);
assertThat(context1).hasSameHashCodeAs(context2);
}


}

+ 3
- 2
server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDescriptionSectionDtoTest.java 파일 보기

@@ -28,6 +28,7 @@ public class RuleDescriptionSectionDtoTest {
private static final RuleDescriptionSectionDto SECTION = RuleDescriptionSectionDto.builder()
.key("key")
.uuid("uuid")
.context(RuleDescriptionSectionContextDto.of("key", "displayName"))
.content("desc").build();


@@ -49,9 +50,9 @@ public class RuleDescriptionSectionDtoTest {
.withMessage("Only one of setDefault and key methods can be called");
}


@Test
public void testToString() {
Assertions.assertThat(SECTION).hasToString("RuleDescriptionSectionDto[uuid='uuid', key='key', content='desc']");
Assertions.assertThat(SECTION)
.hasToString("RuleDescriptionSectionDto[uuid='uuid', key='key', content='desc', context='RuleDescriptionSectionContextDto[key='key', displayName='displayName']']");
}
}

+ 63
- 0
server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDtoTest.java 파일 보기

@@ -23,17 +23,21 @@ import com.google.common.collect.ImmutableSet;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import org.sonar.core.util.Uuids;

import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.apache.commons.lang.StringUtils.repeat;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.sonar.db.rule.RuleDto.ERROR_MESSAGE_SECTION_ALREADY_EXISTS;
import static org.sonar.db.rule.RuleTesting.newRule;

public class RuleDtoTest {


public static final String SECTION_KEY = "section key";
@Test
public void fail_if_key_is_too_long() {
assertThatThrownBy(() -> new RuleDto().setRuleKey(repeat("x", 250)))
@@ -115,4 +119,63 @@ public class RuleDtoTest {
.isNotEqualTo(newRule().setRuleKey(dto.getRuleKey()).setUuid(Uuids.createFast()).hashCode())
.isNotEqualTo(newRule().setUuid(Uuids.createFast()).hashCode());
}

@Test
public void add_rule_description_section_same_key_should_throw_error() {
RuleDto dto = new RuleDto();

RuleDescriptionSectionDto section1 = createSection(SECTION_KEY);
dto.addRuleDescriptionSectionDto(section1);

RuleDescriptionSectionDto section2 = createSection(SECTION_KEY);
assertThatThrownBy(() -> dto.addRuleDescriptionSectionDto(section2))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage(String.format(ERROR_MESSAGE_SECTION_ALREADY_EXISTS, SECTION_KEY, "null"));
}

@Test
public void add_rule_description_section_with_different_context() {
RuleDto dto = new RuleDto();

RuleDescriptionSectionDto section1 = createSection(RuleDtoTest.SECTION_KEY, "context key 1", "context display Name 1");
dto.addRuleDescriptionSectionDto(section1);

RuleDescriptionSectionDto section2 = createSection(RuleDtoTest.SECTION_KEY, "context key 2", "context display Name 2");
dto.addRuleDescriptionSectionDto(section2);

assertThat(dto.getRuleDescriptionSectionDtos())
.usingRecursiveFieldByFieldElementComparator()
.containsExactlyInAnyOrder(section1, section2);

}

@Test
public void add_rule_description_section_with_same_section_and_context_should_throw_error() {
RuleDto dto = new RuleDto();
String contextKey = randomAlphanumeric(50);
String displayName = randomAlphanumeric(50);
RuleDescriptionSectionDto section1 = createSection(SECTION_KEY, contextKey, displayName);
dto.addRuleDescriptionSectionDto(section1);
RuleDescriptionSectionDto section2 = createSection(SECTION_KEY, contextKey, displayName);

assertThatThrownBy(() -> dto.addRuleDescriptionSectionDto(section2))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage(String.format(ERROR_MESSAGE_SECTION_ALREADY_EXISTS, SECTION_KEY, contextKey));

}

@NotNull
private static RuleDescriptionSectionDto createSection(String section_key, String contextKey, String contextDisplayName) {
return RuleDescriptionSectionDto.builder()
.key(section_key)
.context(RuleDescriptionSectionContextDto.of(contextKey, contextDisplayName))
.build();
}

@NotNull
private static RuleDescriptionSectionDto createSection(String section_key) {
return RuleDescriptionSectionDto.builder()
.key(section_key)
.build();
}
}

+ 5
- 5
server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexTest.java 파일 보기

@@ -216,20 +216,20 @@ public class RuleIndexTest {
// otherwise the generated random values may raise false-positives
RuleDto rule1 = createJavaRule(rule -> rule.setRuleKey("123")
.setName("rule 123")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "My great rule CWE-123 which makes your code 1000 times better!")));
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "My great rule CWE-123 which makes your code 1000 times better!")));
RuleDto rule2 = createJavaRule(rule -> rule.setRuleKey("124")
.setName("rule 124")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "Another great and shiny rule CWE-124")));
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "Another great and shiny rule CWE-124")));
RuleDto rule3 = createJavaRule(rule -> rule.setRuleKey("1000")
.setName("rule 1000")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "Another great rule CWE-1000")));
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "Another great rule CWE-1000")));
RuleDto rule4 = createJavaRule(rule -> rule.setRuleKey("404")
.setName("rule 404")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(),
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(),
"<h1>HTML-Geeks</h1><p style=\"color:blue\">special formatting!</p><table><tr><td>inside</td><td>tables</td></tr></table>")));
RuleDto rule5 = createJavaRule(rule -> rule.setRuleKey("405")
.setName("rule 405")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "internationalization missunderstandings alsdkjfnadklsjfnadkdfnsksdjfn")));
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "internationalization missunderstandings alsdkjfnadklsjfnadkdfnsksdjfn")));
index();

// partial match at word boundary

+ 4
- 3
server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexerTest.java 파일 보기

@@ -139,7 +139,8 @@ public class RuleIndexerTest {
public void index_long_rule_description() {
String description = IntStream.range(0, 100000).map(i -> i % 100).mapToObj(Integer::toString).collect(joining(" "));
RuleDescriptionSectionDto ruleDescriptionSectionDto = createDefaultRuleDescriptionSection(uuidFactory.create(), description);
RuleDto rule = dbTester.rules().insert(r -> r.addOrReplaceRuleDescriptionSectionDto(ruleDescriptionSectionDto));

RuleDto rule = dbTester.rules().insert(r -> r.replaceRuleDescriptionSectionDtos(ruleDescriptionSectionDto));
underTest.commitAndIndex(dbTester.getSession(), rule.getUuid());

assertThat(es.countDocuments(TYPE_RULE)).isOne();
@@ -148,7 +149,7 @@ public class RuleIndexerTest {
@Test
public void index_long_rule_with_several_sections() {
RuleDto rule = dbTester.rules().insert(r -> {
r.addOrReplaceRuleDescriptionSectionDto(RULE_DESCRIPTION_SECTION_DTO);
r.replaceRuleDescriptionSectionDtos(RULE_DESCRIPTION_SECTION_DTO);
r.addRuleDescriptionSectionDto(RULE_DESCRIPTION_SECTION_DTO2);
});

@@ -166,7 +167,7 @@ public class RuleIndexerTest {
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);
r.replaceRuleDescriptionSectionDtos(RULE_DESCRIPTION_SECTION_DTO);
});

underTest.commitAndIndex(dbTester.getSession(), rule.getUuid());

+ 9
- 7
server/sonar-webserver-core/src/main/java/org/sonar/server/rule/RegisterRules.java 파일 보기

@@ -517,15 +517,17 @@ public class RegisterRules implements Startable {
}

private static boolean ruleDescriptionSectionsUnchanged(RuleDto ruleDto, Set<RuleDescriptionSectionDto> newRuleDescriptionSectionDtos) {
Map<String, String> oldKeysToSections = toMap(ruleDto.getRuleDescriptionSectionDtos());
Map<String, String> newKeysToSections = toMap(newRuleDescriptionSectionDtos);
return oldKeysToSections.equals(newKeysToSections);
if (ruleDto.getRuleDescriptionSectionDtos().size() != newRuleDescriptionSectionDtos.size()) {
return false;
}
return ruleDto.getRuleDescriptionSectionDtos().stream()
.allMatch(sectionDto -> contains(newRuleDescriptionSectionDtos, sectionDto));
}

private static Map<String, String> toMap(Set<RuleDescriptionSectionDto> ruleDto) {
return ruleDto
.stream()
.collect(Collectors.toMap(RuleDescriptionSectionDto::getKey, RuleDescriptionSectionDto::getContent));
private static boolean contains(Set<RuleDescriptionSectionDto> sectionDtos, RuleDescriptionSectionDto sectionDto) {
return sectionDtos.stream()
.filter(s -> s.getKey().equals(sectionDto.getKey()) && s.getContent().equals(sectionDto.getContent()))
.anyMatch(s -> Objects.equals(s.getContext(), sectionDto.getContext()));
}

private static boolean mergeDebtDefinitions(RulesDefinition.Rule def, RuleDto dto) {

+ 1
- 1
server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java 파일 보기

@@ -71,7 +71,7 @@ public class QualityProfileChangeEventServiceImplTest {
.setRepositoryKey("repo")
.setRuleKey("ruleKey")
.setDescriptionFormat(RuleDto.Format.MARKDOWN)
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection("uuid", "<div>line1\nline2</div>"));
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection("uuid", "<div>line1\nline2</div>"));
db.rules().insert(rule1);

ActiveRuleDto activeRuleDto = ActiveRuleDto.createFor(qualityProfileDto, rule1);

+ 1
- 1
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleUpdater.java 파일 보기

@@ -142,7 +142,7 @@ public class RuleUpdater {
}
RuleDescriptionSectionDto descriptionSectionDto = createDefaultRuleDescriptionSection(uuidFactory.create(), description);
rule.setDescriptionFormat(RuleDto.Format.MARKDOWN);
rule.addOrReplaceRuleDescriptionSectionDto(descriptionSectionDto);
rule.replaceRuleDescriptionSectionDtos(List.of(descriptionSectionDto));
}

private static void updateSeverity(RuleUpdate update, RuleDto rule) {

+ 2
- 2
server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java 파일 보기

@@ -1489,7 +1489,7 @@ public class SearchActionTest {
private RuleDto newIssueRule() {
RuleDto rule = RuleTesting.newXooX1()
.setName("Rule name")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "Rule desc"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "Rule desc"))
.setStatus(RuleStatus.READY);
db.rules().insert(rule);
return rule;
@@ -1498,7 +1498,7 @@ public class SearchActionTest {
private RuleDto newHotspotRule() {
RuleDto rule = RuleTesting.newXooX2()
.setName("Rule name")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "Rule desc"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "Rule desc"))
.setStatus(RuleStatus.READY)
.setType(SECURITY_HOTSPOT_VALUE);
db.rules().insert(rule);

+ 2
- 2
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java 파일 보기

@@ -145,7 +145,7 @@ public class QProfileBackuperImplTest {
RuleDto templateRule = db.rules().insert(ruleDefinitionDto -> ruleDefinitionDto
.setIsTemplate(true));
RuleDto rule = db.rules().insert(ruleDefinitionDto -> ruleDefinitionDto
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(UuidFactoryFast.getInstance().create(), "custom rule description"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(UuidFactoryFast.getInstance().create(), "custom rule description"))
.setName("custom rule name")
.setStatus(RuleStatus.READY)
.setTemplateUuid(templateRule.getUuid()));
@@ -404,7 +404,7 @@ public class QProfileBackuperImplTest {
RuleDto templateRule = db.rules().insert(ruleDefinitionDto -> ruleDefinitionDto
.setIsTemplate(true));
RuleDto rule = db.rules().insert(ruleDefinitionDto -> ruleDefinitionDto
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(UuidFactoryFast.getInstance().create(), "custom rule description"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(UuidFactoryFast.getInstance().create(), "custom rule description"))
.setName("custom rule name")
.setStatus(RuleStatus.READY)
.setTemplateUuid(templateRule.getUuid()));

+ 2
- 2
server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/RuleCreatorTest.java 파일 보기

@@ -323,7 +323,7 @@ public class RuleCreatorTest {
.setRuleKey(key)
.setStatus(RuleStatus.REMOVED)
.setName("Old name")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "Old description"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "Old description"))
.setDescriptionFormat(Format.MARKDOWN)
.setSeverity(Severity.INFO);
dbTester.rules().insert(rule);
@@ -363,7 +363,7 @@ public class RuleCreatorTest {
.setRuleKey(key)
.setStatus(RuleStatus.REMOVED)
.setName("Old name")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "Old description"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "Old description"))
.setSeverity(Severity.INFO);
dbTester.rules().insert(rule);
dbTester.rules().insertRuleParam(rule, param -> param.setDefaultValue("a.*"));

+ 2
- 2
server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/RuleUpdaterTest.java 파일 보기

@@ -338,7 +338,7 @@ public class RuleUpdaterTest {
// Create custom rule
RuleDto customRule = newCustomRule(templateRule)
.setName("Old name")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "Old description"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "Old description"))
.setSeverity(Severity.MINOR)
.setStatus(RuleStatus.BETA)
;
@@ -386,7 +386,7 @@ public class RuleUpdaterTest {
// Create custom rule
RuleDto customRule = newCustomRule(templateRule)
.setName("Old name")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "Old description"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "Old description"))
.setSeverity(Severity.MINOR)
.setStatus(RuleStatus.BETA);
db.rules().insert(customRule);

+ 1
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/CreateActionTest.java 파일 보기

@@ -140,7 +140,7 @@ public class CreateActionTest {
.setRuleKey("MY_CUSTOM")
.setStatus(RuleStatus.REMOVED)
.setName("My custom rule")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "Description"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "Description"))
.setDescriptionFormat(RuleDto.Format.MARKDOWN)
.setSeverity(Severity.MAJOR);
db.rules().insert(customRule);

+ 6
- 5
server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java 파일 보기

@@ -84,6 +84,7 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.sonar.api.rule.Severity.BLOCKER;
import static org.sonar.db.rule.RuleDescriptionSectionDto.createDefaultRuleDescriptionSection;
import static org.sonar.db.rule.RuleTesting.newRuleWithoutDescriptionSection;
import static org.sonar.db.rule.RuleTesting.setSystemTags;
import static org.sonar.db.rule.RuleTesting.setTags;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVATION;
@@ -239,7 +240,7 @@ public class SearchActionTest {
RuleDto rule1 = db.rules()
.insert(
r1 -> r1
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "This is the <bold>best</bold> rule now&amp;for<b>ever</b>"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "This is the <bold>best</bold> rule now&amp;for<b>ever</b>"))
.setNoteUserUuid(null));
db.rules().insert(r1 -> r1.setName("Some other stuff").setNoteUserUuid(null));
indexRules();
@@ -251,10 +252,10 @@ public class SearchActionTest {

@Test
public void filter_by_rule_name_or_descriptions_requires_all_words_to_match_anywhere() {
RuleDto rule1 = db.rules().insert(r1 -> r1.setName("Best rule ever").setNoteUserUuid(null)
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "This is a good rule")));
db.rules().insert(r1 -> r1.setName("Another thing").setNoteUserUuid(null)
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "Another thing")));
RuleDto rule1 = db.rules().insert(newRuleWithoutDescriptionSection().setName("Best rule ever").setNoteUserUuid(null)
.addRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "This is a good rule")));
db.rules().insert(newRuleWithoutDescriptionSection().setName("Another thing").setNoteUserUuid(null)
.addRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "Another thing")));
indexRules();

verify(r -> r.setParam("q", "Best good"), rule1);

+ 2
- 2
server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java 파일 보기

@@ -297,7 +297,7 @@ public class ShowActionTest {
db.rules().insert(templateRule);
// Custom rule
RuleDto customRule = newCustomRule(templateRule)
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "<div>line1\nline2</div>"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "<div>line1\nline2</div>"))
.setDescriptionFormat(MARKDOWN)
.setNoteUserUuid(userDto.getUuid());
db.rules().insert(customRule);
@@ -435,7 +435,7 @@ public class ShowActionTest {
.setIsExternal(true)
.setIsAdHoc(true)
.setName("predefined name")
.addOrReplaceRuleDescriptionSectionDto(createDefaultRuleDescriptionSection(uuidFactory.create(), "<div>predefined desc</div>"))
.replaceRuleDescriptionSectionDtos(createDefaultRuleDescriptionSection(uuidFactory.create(), "<div>predefined desc</div>"))
.setSeverity(Severity.BLOCKER)
.setType(RuleType.VULNERABILITY)
.setAdHocName("adhoc name")

+ 2
- 2
server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/UpdateActionTest.java 파일 보기

@@ -113,7 +113,7 @@ public class UpdateActionTest {
RuleDto customRule = db.rules().insert(
r -> r.setRuleKey(RuleKey.of("java", "MY_CUSTOM")),
r -> r.setName("Old custom"),
r -> r.addOrReplaceRuleDescriptionSectionDto(createRuleDescriptionSectionDto()),
r -> r.replaceRuleDescriptionSectionDtos(createRuleDescriptionSectionDto()),
r -> r.setSeverity(Severity.MINOR),
r -> r.setStatus(RuleStatus.BETA),
r -> r.setTemplateUuid(templateRule.getUuid()),
@@ -249,7 +249,7 @@ public class UpdateActionTest {
RuleDto customRule = db.rules().insert(
r -> r.setRuleKey(RuleKey.of("java", "MY_CUSTOM")),
r -> r.setName("Old custom"),
r -> r.addOrReplaceRuleDescriptionSectionDto(createRuleDescriptionSectionDto()),
r -> r.replaceRuleDescriptionSectionDtos(createRuleDescriptionSectionDto()),
r -> r.setTemplateUuid(templateRule.getUuid()),
r -> r.setCreatedAt(PAST),
r -> r.setUpdatedAt(PAST));

Loading…
취소
저장