From 04346ea53f588f8f7333badb4dbd87c9989a9958 Mon Sep 17 00:00:00 2001 From: lukasz-jarocki-sonarsource Date: Tue, 15 Aug 2023 11:52:36 +0200 Subject: [PATCH] SONAR-20021 Add test for cleanCodeAttribute for SearchAction --- .../java/org/sonar/db/issue/ImpactDto.java | 1 + .../sonar/server/issue/ws/SearchActionIT.java | 90 ++++++++++++++++--- 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/ImpactDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/ImpactDto.java index 82da4d3b0b4..426cd3461f1 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/ImpactDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/ImpactDto.java @@ -86,4 +86,5 @@ public class ImpactDto implements Serializable { public int hashCode() { return Objects.hash(uuid, softwareQuality, severity); } + } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/SearchActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/SearchActionIT.java index 87e055fa282..c29575c6e44 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/SearchActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/SearchActionIT.java @@ -26,6 +26,7 @@ import java.time.Clock; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Random; import java.util.Set; @@ -38,7 +39,10 @@ import org.junit.Rule; import org.junit.Test; import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.api.resources.Languages; +import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rules.CleanCodeAttribute; +import org.sonar.api.rules.CleanCodeAttributeCategory; import org.sonar.api.rules.RuleType; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.Durations; @@ -63,9 +67,9 @@ import org.sonar.db.protobuf.DbIssues; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleTesting; import org.sonar.db.user.UserDto; +import org.sonar.server.common.avatar.AvatarResolverImpl; import org.sonar.server.es.EsTester; import org.sonar.server.es.SearchOptions; -import org.sonar.server.common.avatar.AvatarResolverImpl; import org.sonar.server.issue.IssueFieldsSetter; import org.sonar.server.issue.TextRangeResponseFormatter; import org.sonar.server.issue.TransitionService; @@ -122,6 +126,7 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_ASSIGN; import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SET_TAGS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ADDITIONAL_FIELDS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNEES; +import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CODE_VARIANTS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENTS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AFTER; @@ -630,25 +635,36 @@ public class SearchActionIT { ComponentDto project = db.components().insertPublicProject("PROJECT_ID", c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID").setLanguage("java")).getMainBranchComponent(); ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY").setLanguage("java")); + IssueDto issue1 = db.issues().insertIssue(rule, project, file, i -> i - .addImpact(new ImpactDto(uuidFactory.create(), SoftwareQuality.SECURITY, org.sonar.api.issue.impact.Severity.HIGH)) - .addImpact(new ImpactDto(uuidFactory.create(), SoftwareQuality.RELIABILITY, org.sonar.api.issue.impact.Severity.HIGH))); + .addImpact(new ImpactDto().setSoftwareQuality(SoftwareQuality.SECURITY).setSeverity(org.sonar.api.issue.impact.Severity.HIGH).setUuid(uuidFactory.create())) + .addImpact(new ImpactDto().setSoftwareQuality(SoftwareQuality.RELIABILITY).setSeverity(org.sonar.api.issue.impact.Severity.HIGH).setUuid(uuidFactory.create()))); IssueDto issue2 = db.issues().insertIssue(rule, project, file, i -> i - .addImpact(new ImpactDto(uuidFactory.create(), SoftwareQuality.RELIABILITY, org.sonar.api.issue.impact.Severity.HIGH))); + .addImpact(new ImpactDto().setSoftwareQuality(SoftwareQuality.RELIABILITY).setSeverity(org.sonar.api.issue.impact.Severity.HIGH).setUuid(uuidFactory.create()))); IssueDto issue3 = db.issues().insertIssue(rule, project, file, i -> i - .addImpact(new ImpactDto(uuidFactory.create(), SoftwareQuality.SECURITY, org.sonar.api.issue.impact.Severity.MEDIUM)) - .addImpact(new ImpactDto(uuidFactory.create(), SoftwareQuality.RELIABILITY, org.sonar.api.issue.impact.Severity.LOW))); + .addImpact(new ImpactDto().setSoftwareQuality(SoftwareQuality.SECURITY).setSeverity(org.sonar.api.issue.impact.Severity.MEDIUM).setUuid(uuidFactory.create())) + .addImpact(new ImpactDto().setSoftwareQuality(SoftwareQuality.RELIABILITY).setSeverity(org.sonar.api.issue.impact.Severity.LOW).setUuid(uuidFactory.create()))); indexPermissionsAndIssues(); + Map expectedImpacts = Map.of(Common.SoftwareQuality.SECURITY, Common.ImpactSeverity.MEDIUM, + Common.SoftwareQuality.RELIABILITY, Common.ImpactSeverity.LOW, + Common.SoftwareQuality.MAINTAINABILITY, Common.ImpactSeverity.HIGH); SearchWsResponse response = ws.newRequest() .setParam(PARAM_IMPACT_SEVERITIES, org.sonar.api.issue.impact.Severity.LOW.name()) .setParam(FACETS, PARAM_IMPACT_SOFTWARE_QUALITIES) .executeProtobuf(SearchWsResponse.class); - assertThat(response.getIssuesList()) + List issuesList = response.getIssuesList(); + assertThat(issuesList) .extracting(Issue::getKey) - .containsExactlyInAnyOrder(issue3.getKey()) - .doesNotContain(issue1.getKey(), issue2.getKey()); + .containsExactlyInAnyOrder(issue3.getKey()); + + Issue issue = issuesList.get(0); + Map impactsInResponse = issue.getImpactsList() + .stream() + .collect(Collectors.toMap(Common.Impact::getSoftwareQuality, Common.Impact::getSeverity)); + assertThat(impactsInResponse).isEqualTo(expectedImpacts); + assertThat(issue.getCleanCodeAttribute()).isEqualTo(Common.CleanCodeAttribute.CLEAR); Optional first = response.getFacets().getFacetsList() .stream().filter(facet -> facet.getProperty().equals(PARAM_IMPACT_SOFTWARE_QUALITIES)) @@ -706,7 +722,7 @@ public class SearchActionIT { IssueDto issue1 = db.issues().insertIssue(rule, project, file, i -> i.replaceAllImpacts(List.of( new ImpactDto(uuidFactory.create(), SoftwareQuality.SECURITY, org.sonar.api.issue.impact.Severity.HIGH), new ImpactDto(uuidFactory.create(), SoftwareQuality.RELIABILITY, org.sonar.api.issue.impact.Severity.HIGH)))); - IssueDto issue2 = db.issues().insertIssue(rule, project, file, i -> i.replaceAllImpacts(List.of( + db.issues().insertIssue(rule, project, file, i -> i.replaceAllImpacts(List.of( new ImpactDto(uuidFactory.create(), SoftwareQuality.RELIABILITY, org.sonar.api.issue.impact.Severity.HIGH)))); IssueDto issue3 = db.issues().insertIssue(rule, project, file, i -> i.replaceAllImpacts(List.of( new ImpactDto(uuidFactory.create(), SoftwareQuality.MAINTAINABILITY, org.sonar.api.issue.impact.Severity.LOW), @@ -721,8 +737,7 @@ public class SearchActionIT { assertThat(response.getIssuesList()) .extracting(Issue::getKey) - .containsExactlyInAnyOrder(issue1.getKey(), issue3.getKey()) - .doesNotContain(issue2.getKey()); + .containsExactlyInAnyOrder(issue1.getKey(), issue3.getKey()); Optional first = response.getFacets().getFacetsList() .stream().filter(facet -> facet.getProperty().equals(PARAM_IMPACT_SEVERITIES)) @@ -735,6 +750,46 @@ public class SearchActionIT { tuple("LOW", 0L)); } + @Test + public void search_whenFilteredByCleanCodeAttributeCategory_shouldReturnFacet() { + // INTENTIONAL + RuleDto rule1 = newIssueRule("clear-rule", ruleDto -> ruleDto.setCleanCodeAttribute(CleanCodeAttribute.CLEAR)); + RuleDto rule2 = newIssueRule("complete-rule", ruleDto -> ruleDto.setCleanCodeAttribute(CleanCodeAttribute.COMPLETE)); + // ADAPTABLE + RuleDto rule3 = newIssueRule("distinct-rule", ruleDto -> ruleDto.setCleanCodeAttribute(CleanCodeAttribute.DISTINCT)); + // RESPONSIBLE + RuleDto rule4 = newIssueRule("lawful-rule", ruleDto -> ruleDto.setCleanCodeAttribute(CleanCodeAttribute.LAWFUL)); + ComponentDto project = db.components().insertPublicProject("PROJECT_ID", + c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID").setLanguage("java")).getMainBranchComponent(); + ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setKey("FILE_KEY").setLanguage("java")); + IssueDto issue1 = db.issues().insertIssue(rule1, project, file); + IssueDto issue2 = db.issues().insertIssue(rule2, project, file); + IssueDto issue3 = db.issues().insertIssue(rule3, project, file); + IssueDto issue4 = db.issues().insertIssue(rule4, project, file); + IssueDto issue5 = db.issues().insertIssue(rule1, project, file); + indexPermissionsAndIssues(); + + SearchWsResponse response = ws.newRequest() + .setParam(PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES, CleanCodeAttributeCategory.INTENTIONAL.name()) + .setParam(FACETS, PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES) + .executeProtobuf(SearchWsResponse.class); + + assertThat(response.getIssuesList()) + .extracting(Issue::getKey) + .containsExactlyInAnyOrder(issue1.getKey(), issue2.getKey(), issue5.getKey()); + + Optional first = response.getFacets().getFacetsList() + .stream().filter(facet -> facet.getProperty().equals(PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES)) + .findFirst(); + assertThat(first.get().getValuesList()) + .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount) + .containsExactlyInAnyOrder( + tuple("INTENTIONAL", 3L), + tuple("ADAPTABLE", 1L), + tuple("RESPONSIBLE", 1L), + tuple("CONSISTENT", 0L)); + } + @Test public void issue_on_removed_file() { RuleDto rule = newIssueRule(); @@ -2016,6 +2071,17 @@ public class SearchActionIT { return rule; } + private RuleDto newIssueRule(String ruleKey, Consumer consumer) { + RuleDto rule = newRule(RuleKey.of("xoo", ruleKey), + createDefaultRuleDescriptionSection(uuidFactory.create(), "Rule desc")) + .setLanguage("xoo") + .setName("Rule name") + .setStatus(RuleStatus.READY); + consumer.accept(rule); + db.rules().insert(rule); + return rule; + } + private RuleDto newHotspotRule() { RuleDto rule = newRule(XOO_X2, createDefaultRuleDescriptionSection(uuidFactory.create(), "Rule desc")) .setLanguage("xoo") -- 2.39.5