diff options
author | Dimitris Kavvathas <dimitris.kavvathas@sonarsource.com> | 2022-07-22 10:24:21 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-07-25 20:03:58 +0000 |
commit | 20cc332ffff7701ca9a4ac73186fa2adb62bee72 (patch) | |
tree | 8064dd3adbdd64aed0cac0a54d1a93b7e046742b /server/sonar-webserver-es | |
parent | b27a1274bfc7babaec18bbd46571a5b1cd037c91 (diff) | |
download | sonarqube-20cc332ffff7701ca9a4ac73186fa2adb62bee72.tar.gz sonarqube-20cc332ffff7701ca9a4ac73186fa2adb62bee72.zip |
SONAR-17061 Add PCI DSS parameter and facet in 'api/issues/search' API endpoint
Diffstat (limited to 'server/sonar-webserver-es')
12 files changed, 329 insertions, 351 deletions
diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java index d9c53eed857..2ed15da00f5 100644 --- a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -455,8 +455,8 @@ public class IssueIndex { filters.addFilter(FIELD_ISSUE_STATUS, STATUSES.getFilterScope(), createTermsFilter(FIELD_ISSUE_STATUS, query.statuses())); // security category - addSecurityCategoryFilter(FIELD_ISSUE_PCI_DSS_32, PCI_DSS_32, query.pciDss32(), filters); - addSecurityCategoryFilter(FIELD_ISSUE_PCI_DSS_40, PCI_DSS_40, query.pciDss40(), filters); + addPciDssSecurityCategoryFilter(FIELD_ISSUE_PCI_DSS_32, PCI_DSS_32, query.pciDss32(), filters); + addPciDssSecurityCategoryFilter(FIELD_ISSUE_PCI_DSS_40, PCI_DSS_40, query.pciDss40(), filters); addSecurityCategoryFilter(FIELD_ISSUE_OWASP_TOP_10, OWASP_TOP_10, query.owaspTop10(), filters); addSecurityCategoryFilter(FIELD_ISSUE_OWASP_TOP_10_2021, OWASP_TOP_10_2021, query.owaspTop10For2021(), filters); addSecurityCategoryFilter(FIELD_ISSUE_SANS_TOP_25, SANS_TOP_25, query.sansTop25(), filters); @@ -485,6 +485,49 @@ public class IssueIndex { } } + /** + * <p>Builds the Elasticsearch boolean query to filter the PCI DSS categories.</p> + * + * <p>The PCI DSS security report handles all the subcategories as one level. This means that subcategory 1.1 doesn't include the issues from 1.1.1. + * Taking this into account, the search filter follows the same logic and uses prefix matching for top-level categories and exact matching for subcategories</p> + * + * <p>Example</p> + * <p>List of PCI DSS categories in issues: {1.5.8, 1.5.9, 1.6.7} + * <ul> + * <li>Search: {1}, returns {1.5.8, 1.5.9, 1.6.7}</li> + * <li>Search: {1.5.8}, returns {1.5.8}</li> + * <li>Search: {1.5}, returns {}</li> + * </ul> + * </p> + * + * @param fieldName The PCI DSS version, e.g. pciDss-3.2 + * @param facet The facet used for the filter + * @param values The PCI DSS categories to search for + * @param allFilters Object that holds all the filters for the Elastic search call + */ + private static void addPciDssSecurityCategoryFilter(String fieldName, Facet facet, Collection<String> values, AllFilters allFilters) { + if (values.isEmpty()) { + return; + } + + BoolQueryBuilder boolQueryBuilder = boolQuery() + // ensures that at least one "should" query is matched. Without it, "should" queries are optional, when a "must" is also present. + .minimumShouldMatch(1) + // the field type must be vulnerability or security hotspot + .must(termsQuery(FIELD_ISSUE_TYPE, VULNERABILITY.name(), SECURITY_HOTSPOT.name())); + // for top level categories a prefix query is added, while for subcategories a term query is used for exact matching + values.stream().map(v -> choosePciDssQuery(fieldName, v)).forEach(boolQueryBuilder::should); + + allFilters.addFilter( + fieldName, + facet.getFilterScope(), + boolQueryBuilder); + } + + private static QueryBuilder choosePciDssQuery(String fieldName, String value) { + return value.contains(".") ? createTermFilter(fieldName, value) : createPrefixFilter(fieldName, value + "."); + } + private static void addSeverityFilter(IssueQuery query, AllFilters allFilters) { QueryBuilder severityFieldFilter = createTermsFilter(FIELD_ISSUE_SEVERITY, query.severities()); if (severityFieldFilter != null) { @@ -615,6 +658,10 @@ public class IssueIndex { return value == null ? null : termQuery(field, value); } + private static QueryBuilder createPrefixFilter(String field, String value) { + return prefixQuery(field, value); + } + private void configureSorting(IssueQuery query, SearchSourceBuilder esRequest) { createSortBuilders(query).forEach(esRequest::sort); } @@ -715,6 +762,8 @@ public class IssueIndex { addFacetIfNeeded(options, aggregationHelper, esRequest, TAGS, query.tags().toArray()); addFacetIfNeeded(options, aggregationHelper, esRequest, TYPES, query.types().toArray()); + addSecurityCategoryFacetIfNeeded(PARAM_PCI_DSS_32, PCI_DSS_32, options, aggregationHelper, esRequest, query.pciDss32().toArray()); + addSecurityCategoryFacetIfNeeded(PARAM_PCI_DSS_40, PCI_DSS_40, options, aggregationHelper, esRequest, query.pciDss40().toArray()); addSecurityCategoryFacetIfNeeded(PARAM_OWASP_TOP_10, OWASP_TOP_10, options, aggregationHelper, esRequest, query.owaspTop10().toArray()); addSecurityCategoryFacetIfNeeded(PARAM_OWASP_TOP_10_2021, OWASP_TOP_10_2021, options, aggregationHelper, esRequest, query.owaspTop10For2021().toArray()); addSecurityCategoryFacetIfNeeded(PARAM_SANS_TOP_25, SANS_TOP_25, options, aggregationHelper, esRequest, query.sansTop25().toArray()); @@ -1003,7 +1052,7 @@ public class IssueIndex { requestBuilder.source(sourceBuilder); SearchResponse response = client.search(requestBuilder); return response.getAggregations().asList().stream() - .map(x -> (ParsedFilter) x) + .map(ParsedFilter.class::cast) .flatMap(projectBucket -> ((ParsedStringTerms) projectBucket.getAggregations().get("branchUuid")).getBuckets().stream() .flatMap(branchBucket -> { long count = ((ParsedValueCount) branchBucket.getAggregations().get(AGG_COUNT)).getValue(); diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java index 989936ff93b..ef43b30c23a 100644 --- a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java +++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java @@ -133,6 +133,8 @@ public class IssueQueryFactory { .languages(request.getLanguages()) .tags(request.getTags()) .types(request.getTypes()) + .pciDss32(request.getPciDss32()) + .pciDss40(request.getPciDss40()) .owaspTop10(request.getOwaspTop10()) .owaspTop10For2021(request.getOwaspTop10For2021()) .sansTop25(request.getSansTop25()) @@ -199,8 +201,8 @@ public class IssueQueryFactory { if (!QUALIFIERS_WITHOUT_LEAK_PERIOD.contains(component.qualifier()) && request.getPullRequest() == null) { Optional<SnapshotDto> snapshot = getLastAnalysis(dbSession, component); if (!snapshot.isEmpty() && isLastAnalysisFromReAnalyzedReferenceBranch(dbSession, snapshot.get())) { - builder.newCodeOnReference(true); - return; + builder.newCodeOnReference(true); + return; } // if last analysis has no period date, then no issue should be considered new. Date createdAfterFromSnapshot = findCreatedAfterFromComponentUuid(snapshot); diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java index 0a595df01e9..94225742656 100644 --- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java @@ -20,54 +20,25 @@ package org.sonar.server.issue.index; import java.util.Map; -import java.util.TimeZone; -import org.junit.Rule; import org.junit.Test; -import org.sonar.api.impl.utils.TestSystem2; import org.sonar.api.issue.Issue; import org.sonar.api.rule.Severity; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; -import org.sonar.server.es.EsTester; import org.sonar.server.es.Facets; import org.sonar.server.es.SearchOptions; import org.sonar.server.issue.IssueDocTesting; import org.sonar.server.issue.index.IssueQuery.Builder; -import org.sonar.server.permission.index.IndexPermissions; -import org.sonar.server.permission.index.PermissionIndexerTester; -import org.sonar.server.permission.index.WebAuthorizationTypeSupport; -import org.sonar.server.tester.UserSessionRule; -import static java.util.Arrays.asList; -import static java.util.Arrays.stream; import static java.util.Collections.singletonList; -import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; -import static org.mockito.Mockito.mock; import static org.sonar.api.issue.Issue.STATUS_CLOSED; import static org.sonar.api.issue.Issue.STATUS_OPEN; -import static org.sonar.api.resources.Qualifiers.PROJECT; import static org.sonar.api.utils.DateUtils.parseDateTime; import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT; -public class IssueIndexDebtTest { - - private final System2 system2 = new TestSystem2().setNow(1_500_000_000_000L).setDefaultTimeZone(TimeZone.getTimeZone("GMT-01:00")); - - @Rule - public EsTester es = EsTester.create(); - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); - @Rule - public DbTester db = DbTester.create(system2); - - private final AsyncIssueIndexing asyncIssueIndexing = mock(AsyncIssueIndexing.class); - private final IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()), asyncIssueIndexing); - private final PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, issueIndexer); - private final IssueIndex underTest = new IssueIndex(es.client(), system2, userSessionRule, new WebAuthorizationTypeSupport(userSessionRule)); +public class IssueIndexDebtTest extends IssueIndexTestCommon { @Test public void facets_on_projects() { @@ -248,11 +219,6 @@ public class IssueIndexDebtTest { return new SearchOptions().addFacets("createdAt"); } - private void indexIssues(IssueDoc... issues) { - issueIndexer.index(asList(issues).iterator()); - authorizationIndexer.allow(stream(issues).map(issue -> new IndexPermissions(issue.projectUuid(), PROJECT).allowAnyone()).collect(toList())); - } - private Facets search(String additionalFacet) { return new Facets(underTest.search(newQueryBuilder().build(), new SearchOptions().addFacets(singletonList(additionalFacet))), system2.getDefaultTimeZone().toZoneId()); } diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFacetsTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFacetsTest.java index ac1062dde0a..20d86b48c40 100644 --- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFacetsTest.java +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFacetsTest.java @@ -23,30 +23,17 @@ import java.time.ZoneId; import java.util.Collections; import java.util.Date; import java.util.Map; -import java.util.TimeZone; import org.elasticsearch.action.search.SearchResponse; -import org.junit.Rule; import org.junit.Test; -import org.sonar.api.impl.utils.TestSystem2; import org.sonar.api.rules.RuleType; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.rule.RuleDto; -import org.sonar.server.es.EsTester; import org.sonar.server.es.Facets; import org.sonar.server.es.SearchOptions; -import org.sonar.server.permission.index.IndexPermissions; -import org.sonar.server.permission.index.PermissionIndexerTester; -import org.sonar.server.permission.index.WebAuthorizationTypeSupport; import org.sonar.server.security.SecurityStandards.SQCategory; -import org.sonar.server.tester.UserSessionRule; import static java.util.Arrays.asList; -import static java.util.Arrays.stream; import static java.util.Collections.singletonList; -import static java.util.TimeZone.getTimeZone; -import static java.util.stream.Collectors.toList; import static java.util.stream.IntStream.rangeClosed; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; @@ -59,7 +46,6 @@ import static org.sonar.api.issue.Issue.STATUS_CONFIRMED; import static org.sonar.api.issue.Issue.STATUS_OPEN; import static org.sonar.api.issue.Issue.STATUS_REOPENED; import static org.sonar.api.issue.Issue.STATUS_RESOLVED; -import static org.sonar.api.resources.Qualifiers.PROJECT; import static org.sonar.api.rule.Severity.BLOCKER; import static org.sonar.api.rule.Severity.CRITICAL; import static org.sonar.api.rule.Severity.INFO; @@ -67,6 +53,8 @@ import static org.sonar.api.rule.Severity.MAJOR; import static org.sonar.api.rule.Severity.MINOR; import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2017; import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2021; +import static org.sonar.api.server.rule.RulesDefinition.PciDssVersion.V3_2; +import static org.sonar.api.server.rule.RulesDefinition.PciDssVersion.V4_0; import static org.sonar.api.utils.DateUtils.parseDateTime; import static org.sonar.db.component.ComponentTesting.newDirectory; import static org.sonar.db.component.ComponentTesting.newFileDto; @@ -74,21 +62,7 @@ import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; import static org.sonar.db.rule.RuleTesting.newRule; import static org.sonar.server.issue.IssueDocTesting.newDoc; -public class IssueIndexFacetsTest { - - @Rule - public EsTester es = EsTester.create(); - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); - private final TimeZone defaultTimezone = getTimeZone("GMT-01:00"); - private System2 system2 = new TestSystem2().setNow(1_500_000_000_000L).setDefaultTimeZone(defaultTimezone); - @Rule - public DbTester db = DbTester.create(system2); - - private IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()), null); - private PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, issueIndexer); - - private IssueIndex underTest = new IssueIndex(es.client(), system2, userSessionRule, new WebAuthorizationTypeSupport(userSessionRule)); +public class IssueIndexFacetsTest extends IssueIndexTestCommon { @Test public void facet_on_projectUuids() { @@ -188,6 +162,38 @@ public class IssueIndexFacetsTest { } @Test + public void facets_on_pciDss32() { + ComponentDto project = newPrivateProjectDto(); + ComponentDto file = newFileDto(project, null); + + indexIssues( + newDoc("I1", file).setType(RuleType.VULNERABILITY).setPciDss32(asList("1", "2")), + newDoc("I2", file).setType(RuleType.VULNERABILITY).setPciDss32(singletonList("3")), + newDoc("I3", file)); + + assertThatFacetHasOnly(IssueQuery.builder(), V3_2.prefix(), + entry("1", 1L), + entry("2", 1L), + entry("3", 1L)); + } + + @Test + public void facets_on_pciDss40() { + ComponentDto project = newPrivateProjectDto(); + ComponentDto file = newFileDto(project, null); + + indexIssues( + newDoc("I1", file).setType(RuleType.VULNERABILITY).setPciDss40(asList("1", "2")), + newDoc("I2", file).setType(RuleType.VULNERABILITY).setPciDss40(singletonList("3")), + newDoc("I3", file)); + + assertThatFacetHasOnly(IssueQuery.builder(), V4_0.prefix(), + entry("1", 1L), + entry("2", 1L), + entry("3", 1L)); + } + + @Test public void facets_on_owaspTop10() { ComponentDto project = newPrivateProjectDto(); ComponentDto file = newFileDto(project, null); @@ -637,11 +643,6 @@ public class IssueIndexFacetsTest { return new SearchOptions().addFacets("createdAt"); } - private void indexIssues(IssueDoc... issues) { - issueIndexer.index(asList(issues).iterator()); - authorizationIndexer.allow(stream(issues).map(issue -> new IndexPermissions(issue.projectUuid(), PROJECT).allowAnyone()).collect(toList())); - } - @SafeVarargs private final void assertThatFacetHasExactly(IssueQuery.Builder query, String facet, Map.Entry<String, Long>... expectedEntries) { SearchResponse result = underTest.search(query.build(), new SearchOptions().addFacets(singletonList(facet))); diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFiltersTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFiltersTest.java index a41d651ba9a..8312ff90cf4 100644 --- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFiltersTest.java +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFiltersTest.java @@ -20,43 +20,26 @@ package org.sonar.server.issue.index; import com.google.common.collect.ImmutableMap; -import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import org.assertj.core.api.Fail; -import org.elasticsearch.search.SearchHit; -import org.junit.Rule; import org.junit.Test; -import org.sonar.api.impl.utils.TestSystem2; import org.sonar.api.issue.Issue; import org.sonar.api.rule.Severity; import org.sonar.api.rules.RuleType; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.rule.RuleDto; -import org.sonar.server.es.EsTester; import org.sonar.server.es.SearchOptions; -import org.sonar.server.permission.index.IndexPermissions; -import org.sonar.server.permission.index.PermissionIndexerTester; -import org.sonar.server.permission.index.WebAuthorizationTypeSupport; import org.sonar.server.security.SecurityStandards.SQCategory; -import org.sonar.server.tester.UserSessionRule; import org.sonar.server.view.index.ViewDoc; -import org.sonar.server.view.index.ViewIndexer; import static java.util.Arrays.asList; -import static java.util.Arrays.stream; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; -import static java.util.TimeZone.getTimeZone; -import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.sonar.api.resources.Qualifiers.APP; -import static org.sonar.api.resources.Qualifiers.PROJECT; import static org.sonar.api.utils.DateUtils.addDays; import static org.sonar.api.utils.DateUtils.parseDate; import static org.sonar.api.utils.DateUtils.parseDateTime; @@ -66,20 +49,7 @@ import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; import static org.sonar.db.rule.RuleTesting.newRule; import static org.sonar.server.issue.IssueDocTesting.newDoc; -public class IssueIndexFiltersTest { - - @Rule - public EsTester es = EsTester.create(); - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); - private final System2 system2 = new TestSystem2().setNow(1_500_000_000_000L).setDefaultTimeZone(getTimeZone("GMT-01:00")); - @Rule - public DbTester db = DbTester.create(system2); - - private final IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()), null); - private final ViewIndexer viewIndexer = new ViewIndexer(db.getDbClient(), es.client()); - private final PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, issueIndexer); - private final IssueIndex underTest = new IssueIndex(es.client(), system2, userSessionRule, new WebAuthorizationTypeSupport(userSessionRule)); +public class IssueIndexFiltersTest extends IssueIndexTestCommon { @Test public void filter_by_keys() { @@ -844,31 +814,7 @@ public class IssueIndexFiltersTest { assertThatSearchReturnsOnly(IssueQuery.builder().sonarsourceSecurity(singletonList("buffer-overflow")), "I1"); } - private void indexIssues(IssueDoc... issues) { - issueIndexer.index(asList(issues).iterator()); - authorizationIndexer.allow(stream(issues).map(issue -> new IndexPermissions(issue.projectUuid(), PROJECT).allowAnyone()).collect(toList())); - } - private void indexView(String viewUuid, List<String> projects) { viewIndexer.index(new ViewDoc().setUuid(viewUuid).setProjects(projects)); } - - /** - * Execute the search request and return the document ids of results. - */ - private List<String> searchAndReturnKeys(IssueQuery.Builder query) { - return Arrays.stream(underTest.search(query.build(), new SearchOptions()).getHits().getHits()) - .map(SearchHit::getId) - .collect(Collectors.toList()); - } - - private void assertThatSearchReturnsOnly(IssueQuery.Builder query, String... expectedIssueKeys) { - List<String> keys = searchAndReturnKeys(query); - assertThat(keys).containsExactlyInAnyOrder(expectedIssueKeys); - } - - private void assertThatSearchReturnsEmpty(IssueQuery.Builder query) { - List<String> keys = searchAndReturnKeys(query); - assertThat(keys).isEmpty(); - } } diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexProjectStatisticsTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexProjectStatisticsTest.java index 07279338865..59739bf78be 100644 --- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexProjectStatisticsTest.java +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexProjectStatisticsTest.java @@ -21,44 +21,22 @@ package org.sonar.server.issue.index; import java.util.Date; import java.util.List; -import org.junit.Rule; import org.junit.Test; import org.sonar.api.issue.Issue; -import org.sonar.api.utils.System2; import org.sonar.db.component.ComponentDto; -import org.sonar.server.es.EsTester; -import org.sonar.server.permission.index.IndexPermissions; -import org.sonar.server.permission.index.PermissionIndexerTester; -import org.sonar.server.permission.index.WebAuthorizationTypeSupport; -import org.sonar.server.tester.UserSessionRule; import static java.util.Arrays.asList; -import static java.util.Arrays.stream; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; -import static java.util.stream.Collectors.toList; import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.Mockito.mock; -import static org.sonar.api.resources.Qualifiers.PROJECT; +import static org.sonar.db.component.ComponentTesting.newBranchComponent; import static org.sonar.db.component.ComponentTesting.newBranchDto; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; -import static org.sonar.db.component.ComponentTesting.newBranchComponent; import static org.sonar.server.issue.IssueDocTesting.newDoc; -public class IssueIndexProjectStatisticsTest { - - private System2 system2 = mock(System2.class); - @Rule - public EsTester es = EsTester.create(); - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); - - private IssueIndexer issueIndexer = new IssueIndexer(es.client(), null, new IssueIteratorFactory(null), null); - private PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, issueIndexer); - - private IssueIndex underTest = new IssueIndex(es.client(), system2, userSessionRule, new WebAuthorizationTypeSupport(userSessionRule)); +public class IssueIndexProjectStatisticsTest extends IssueIndexTestCommon { @Test public void searchProjectStatistics_returns_empty_list_if_no_input() { @@ -249,9 +227,4 @@ public class IssueIndexProjectStatisticsTest { tuple(2L, branch.uuid(), from + 2L), tuple(1L, project.uuid(), from + 1L)); } - - private void indexIssues(IssueDoc... issues) { - issueIndexer.index(asList(issues).iterator()); - authorizationIndexer.allow(stream(issues).map(issue -> new IndexPermissions(issue.projectUuid(), PROJECT).allowAnyone()).collect(toList())); - } } diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityCategoriesTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityCategoriesTest.java new file mode 100644 index 00000000000..4477c766de2 --- /dev/null +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityCategoriesTest.java @@ -0,0 +1,140 @@ +/* + * 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.issue.index; + +import java.util.List; +import org.junit.Test; +import org.sonar.api.issue.Issue; +import org.sonar.api.rule.Severity; +import org.sonar.api.rules.RuleType; +import org.sonar.db.component.ComponentDto; + +import static java.util.Arrays.asList; +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.toList; +import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; +import static org.sonar.server.issue.IssueDocTesting.newDoc; + +public class IssueIndexSecurityCategoriesTest extends IssueIndexTestCommon { + + @Test + public void searchSinglePciDss32Category() { + ComponentDto project = newPrivateProjectDto(); + + indexIssues( + newDoc("openvul1", project).setPciDss32(asList("1.2.0", "3.4.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN) + .setSeverity(Severity.MAJOR), + newDoc("openvul2", project).setPciDss32(asList("3.3.2", "1.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) + .setSeverity(Severity.MINOR) + ); + + assertThatSearchReturnsOnly(queryPciDss32("1"), "openvul1", "openvul2"); + assertThatSearchReturnsOnly(queryPciDss32("1.2.0"), "openvul1"); + assertThatSearchReturnsEmpty(queryPciDss32("1.2")); + } + + @Test + public void searchMultiplePciDss32Categories() { + ComponentDto project = newPrivateProjectDto(); + + indexIssues( + newDoc("openvul1", project).setPciDss32(asList("1.2.0", "3.4.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN) + .setSeverity(Severity.MAJOR), + newDoc("openvul2", project).setPciDss32(asList("3.3.2", "2.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) + .setSeverity(Severity.MINOR), + newDoc("openvul3", project).setPciDss32(asList("4.1", "5.4")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) + .setSeverity(Severity.MINOR) + ); + + assertThatSearchReturnsOnly(queryPciDss32("1", "4"), "openvul1", "openvul3"); + assertThatSearchReturnsOnly(queryPciDss32("1.2.0", "5.4"), "openvul1", "openvul3"); + assertThatSearchReturnsEmpty(queryPciDss32("6", "7", "8", "9", "10", "11", "12")); + } + + @Test + public void searchSinglePciDss40Category() { + ComponentDto project = newPrivateProjectDto(); + + indexIssues( + newDoc("openvul1", project).setPciDss40(asList("1.2.0", "3.4.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN) + .setSeverity(Severity.MAJOR), + newDoc("openvul2", project).setPciDss40(asList("3.3.2", "1.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) + .setSeverity(Severity.MINOR) + ); + + assertThatSearchReturnsOnly(queryPciDss40("1"), "openvul1", "openvul2"); + assertThatSearchReturnsOnly(queryPciDss40("1.2.0"), "openvul1"); + assertThatSearchReturnsEmpty(queryPciDss40("1.2")); + } + + @Test + public void searchMultiplePciDss40Categories() { + ComponentDto project = newPrivateProjectDto(); + + indexIssues( + newDoc("openvul1", project).setPciDss40(asList("1.2.0", "3.4.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN) + .setSeverity(Severity.MAJOR), + newDoc("openvul2", project).setPciDss40(asList("3.3.2", "2.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) + .setSeverity(Severity.MINOR), + newDoc("openvul3", project).setPciDss40(asList("4.1", "5.4")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) + .setSeverity(Severity.MINOR) + ); + + assertThatSearchReturnsOnly(queryPciDss40("1", "4"), "openvul1", "openvul3"); + assertThatSearchReturnsOnly(queryPciDss40("1.2.0", "5.4"), "openvul1", "openvul3"); + assertThatSearchReturnsEmpty(queryPciDss40("6", "7", "8", "9", "10", "11", "12")); + } + + @Test + public void searchMixedPciDssCategories() { + ComponentDto project = newPrivateProjectDto(); + + indexIssues( + newDoc("openvul1", project).setPciDss40(asList("1.2.0", "3.4.5")).setPciDss32(List.of("2.1")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN) + .setSeverity(Severity.MAJOR), + newDoc("openvul2", project).setPciDss40(asList("3.3.2", "2.5")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) + .setSeverity(Severity.MINOR), + newDoc("openvul3", project).setPciDss32(asList("4.1", "5.4")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED) + .setSeverity(Severity.MINOR) + ); + + assertThatSearchReturnsOnly(queryPciDss40("1", "4"), "openvul1"); + assertThatSearchReturnsOnly(queryPciDss40("1.2.0", "5.4"), "openvul1"); + assertThatSearchReturnsEmpty(queryPciDss40("6", "7", "8", "9", "10", "11", "12")); + + assertThatSearchReturnsOnly(queryPciDss32("3", "2.1"), "openvul1"); + assertThatSearchReturnsOnly(queryPciDss32("1", "2"), "openvul1"); + assertThatSearchReturnsOnly(queryPciDss32("4", "3"), "openvul3"); + assertThatSearchReturnsEmpty(queryPciDss32("1", "3", "6", "7", "8", "9", "10", "11", "12")); + + } + + private IssueQuery.Builder queryPciDss32(String... values) { + return IssueQuery.builder() + .pciDss32(stream(values).collect(toList())) + .types(List.of("CODE_SMELL", "BUG", "VULNERABILITY")); + } + + private IssueQuery.Builder queryPciDss40(String... values) { + return IssueQuery.builder() + .pciDss40(stream(values).collect(toList())) + .types(List.of("CODE_SMELL", "BUG", "VULNERABILITY")); + } +} diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityHotspotsTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityHotspotsTest.java index ee9d8d94c80..951397edc6d 100644 --- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityHotspotsTest.java +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityHotspotsTest.java @@ -19,31 +19,18 @@ */ package org.sonar.server.issue.index; -import java.util.Arrays; -import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.search.SearchHit; -import org.junit.Rule; import org.junit.Test; -import org.sonar.api.impl.utils.TestSystem2; import org.sonar.api.rule.Severity; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; -import org.sonar.server.es.EsTester; import org.sonar.server.es.Facets; import org.sonar.server.es.SearchOptions; import org.sonar.server.permission.index.IndexPermissions; -import org.sonar.server.permission.index.PermissionIndexerTester; -import org.sonar.server.permission.index.WebAuthorizationTypeSupport; -import org.sonar.server.tester.UserSessionRule; import static java.util.Arrays.asList; import static java.util.Arrays.stream; import static java.util.Collections.singletonList; -import static java.util.TimeZone.getTimeZone; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; @@ -58,20 +45,7 @@ import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; import static org.sonar.server.issue.IssueDocTesting.newDoc; -public class IssueIndexSecurityHotspotsTest { - - @Rule - public EsTester es = EsTester.create(); - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); - private System2 system2 = new TestSystem2().setNow(1_500_000_000_000L).setDefaultTimeZone(getTimeZone("GMT-01:00")); - @Rule - public DbTester db = DbTester.create(system2); - - private IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()), null); - private PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, issueIndexer); - - private IssueIndex underTest = new IssueIndex(es.client(), system2, userSessionRule, new WebAuthorizationTypeSupport(userSessionRule)); +public class IssueIndexSecurityHotspotsTest extends IssueIndexTestCommon { @Test public void filter_by_security_hotspots_type() { @@ -129,11 +103,6 @@ public class IssueIndexSecurityHotspotsTest { assertThatFacetHasOnly(IssueQuery.builder().types(singletonList(SECURITY_HOTSPOT.name())), "severities"); } - private void indexIssues(IssueDoc... issues) { - issueIndexer.index(asList(issues).iterator()); - authorizationIndexer.allow(stream(issues).map(issue -> new IndexPermissions(issue.projectUuid(), PROJECT).allowAnyone()).collect(toList())); - } - @SafeVarargs private final void assertThatFacetHasOnly(IssueQuery.Builder query, String facet, Map.Entry<String, Long>... expectedEntries) { SearchResponse result = underTest.search(query.build(), new SearchOptions().addFacets(singletonList(facet))); @@ -142,20 +111,4 @@ public class IssueIndexSecurityHotspotsTest { assertThat(facets.get(facet)).containsOnly(expectedEntries); } - private void assertThatSearchReturnsOnly(IssueQuery.Builder query, String... expectedIssueKeys) { - List<String> keys = searchAndReturnKeys(query); - assertThat(keys).containsExactlyInAnyOrder(expectedIssueKeys); - } - - private void assertThatSearchReturnsEmpty(IssueQuery.Builder query) { - List<String> keys = searchAndReturnKeys(query); - assertThat(keys).isEmpty(); - } - - private List<String> searchAndReturnKeys(IssueQuery.Builder query) { - return Arrays.stream(underTest.search(query.build(), new SearchOptions()).getHits().getHits()) - .map(SearchHit::getId) - .collect(Collectors.toList()); - } - } diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java index 82bf992f1b8..8a7952c6e1c 100644 --- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java @@ -23,34 +23,21 @@ import java.util.List; import java.util.Map; import java.util.OptionalInt; import java.util.stream.Collectors; -import org.junit.Rule; import org.junit.Test; -import org.sonar.api.impl.utils.TestSystem2; import org.sonar.api.issue.Issue; import org.sonar.api.rule.Severity; import org.sonar.api.rules.RuleType; import org.sonar.api.server.rule.RulesDefinition; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; -import org.sonar.server.es.EsTester; -import org.sonar.server.permission.index.IndexPermissions; -import org.sonar.server.permission.index.PermissionIndexerTester; -import org.sonar.server.permission.index.WebAuthorizationTypeSupport; -import org.sonar.server.tester.UserSessionRule; import org.sonar.server.view.index.ViewDoc; -import org.sonar.server.view.index.ViewIndexer; import static java.lang.Integer.parseInt; import static java.util.Arrays.asList; -import static java.util.Arrays.stream; import static java.util.Collections.singletonList; import static java.util.Comparator.comparing; -import static java.util.TimeZone.getTimeZone; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; -import static org.sonar.api.resources.Qualifiers.PROJECT; import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2017; import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2021; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; @@ -60,21 +47,7 @@ import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_POROUS_DEF import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_RISKY_RESOURCE; import static org.sonar.server.security.SecurityStandards.UNKNOWN_STANDARD; -public class IssueIndexSecurityReportsTest { - - @Rule - public EsTester es = EsTester.create(); - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); - private System2 system2 = new TestSystem2().setNow(1_500_000_000_000L).setDefaultTimeZone(getTimeZone("GMT-01:00")); - @Rule - public DbTester db = DbTester.create(system2); - - private IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()), null); - private ViewIndexer viewIndexer = new ViewIndexer(db.getDbClient(), es.client()); - private PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, issueIndexer); - - private IssueIndex underTest = new IssueIndex(es.client(), system2, userSessionRule, new WebAuthorizationTypeSupport(userSessionRule)); +public class IssueIndexSecurityReportsTest extends IssueIndexTestCommon { @Test public void getOwaspTop10Report_dont_count_vulnerabilities_from_other_projects() { @@ -675,11 +648,6 @@ public class IssueIndexSecurityReportsTest { return statistics.getChildren().stream().filter(stat -> stat.getCategory().equals(cweId)).findAny().orElse(null); } - private void indexIssues(IssueDoc... issues) { - issueIndexer.index(asList(issues).iterator()); - authorizationIndexer.allow(stream(issues).map(issue -> new IndexPermissions(issue.projectUuid(), PROJECT).allowAnyone()).collect(toList())); - } - private void indexView(String viewUuid, List<String> projects) { viewIndexer.index(new ViewDoc().setUuid(viewUuid).setProjects(projects)); } diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSortTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSortTest.java index 200a0010f3e..3fb1906468b 100644 --- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSortTest.java +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexSortTest.java @@ -19,52 +19,19 @@ */ package org.sonar.server.issue.index; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.search.SearchHit; -import org.junit.Rule; import org.junit.Test; -import org.sonar.api.impl.utils.TestSystem2; import org.sonar.api.issue.Issue; import org.sonar.api.rule.Severity; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; -import org.sonar.server.es.EsTester; import org.sonar.server.es.SearchOptions; -import org.sonar.server.permission.index.IndexPermissions; -import org.sonar.server.permission.index.PermissionIndexerTester; -import org.sonar.server.permission.index.WebAuthorizationTypeSupport; -import org.sonar.server.tester.UserSessionRule; - -import static java.util.Arrays.asList; -import static java.util.Arrays.stream; -import static java.util.TimeZone.getTimeZone; -import static java.util.stream.Collectors.toList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.sonar.api.resources.Qualifiers.PROJECT; + import static org.sonar.api.utils.DateUtils.parseDateTime; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; import static org.sonar.server.issue.IssueDocTesting.newDoc; -public class IssueIndexSortTest { - - @Rule - public EsTester es = EsTester.create(); - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); - private final System2 system2 = new TestSystem2().setNow(1_500_000_000_000L).setDefaultTimeZone(getTimeZone("GMT-01:00")); - @Rule - public DbTester db = DbTester.create(system2); - - private final AsyncIssueIndexing asyncIssueIndexing = mock(AsyncIssueIndexing.class); - private final IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()), asyncIssueIndexing); - private final PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, issueIndexer); - private final IssueIndex underTest = new IssueIndex(es.client(), system2, userSessionRule, new WebAuthorizationTypeSupport(userSessionRule)); +public class IssueIndexSortTest extends IssueIndexTestCommon { @Test public void sort_by_status() { @@ -209,23 +176,4 @@ public class IssueIndexSortTest { assertThatSearchReturnsOnly(IssueQuery.builder(), "F3_1", "F1_2", "F1_1", "F1_3", "F2_1", "F2_2", "F2_3", "F3_2"); } - private void indexIssues(IssueDoc... issues) { - issueIndexer.index(asList(issues).iterator()); - authorizationIndexer.allow(stream(issues).map(issue -> new IndexPermissions(issue.projectUuid(), PROJECT).allowAnyone()).collect(toList())); - } - - /** - * Execute the search request and return the document ids of results. - */ - private List<String> searchAndReturnKeys(IssueQuery.Builder query) { - return Arrays.stream(underTest.search(query.build(), new SearchOptions()).getHits().getHits()) - .map(SearchHit::getId) - .collect(Collectors.toList()); - } - - private void assertThatSearchReturnsOnly(IssueQuery.Builder query, String... expectedIssueKeys) { - List<String> keys = searchAndReturnKeys(query); - assertThat(keys).containsExactlyInAnyOrder(expectedIssueKeys); - } - } diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java index 3b887d76704..e62a4b63528 100644 --- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java @@ -22,46 +22,29 @@ package org.sonar.server.issue.index; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterators; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.IntStream; import org.apache.lucene.search.TotalHits; import org.apache.lucene.search.TotalHits.Relation; import org.assertj.core.groups.Tuple; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.search.SearchHit; -import org.junit.Rule; import org.junit.Test; -import org.sonar.api.impl.utils.TestSystem2; import org.sonar.api.issue.Issue; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; -import org.sonar.server.es.EsTester; import org.sonar.server.es.SearchOptions; -import org.sonar.server.permission.index.IndexPermissions; -import org.sonar.server.permission.index.PermissionIndexerTester; -import org.sonar.server.permission.index.WebAuthorizationTypeSupport; -import org.sonar.server.rule.index.RuleIndexer; -import org.sonar.server.tester.UserSessionRule; import static com.google.common.collect.ImmutableSortedSet.of; import static java.util.Arrays.asList; -import static java.util.Arrays.stream; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; -import static java.util.TimeZone.getTimeZone; -import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.Mockito.mock; import static org.sonar.api.issue.Issue.RESOLUTION_FIXED; -import static org.sonar.api.resources.Qualifiers.PROJECT; import static org.sonar.api.rules.RuleType.BUG; import static org.sonar.api.rules.RuleType.CODE_SMELL; import static org.sonar.api.rules.RuleType.VULNERABILITY; @@ -71,22 +54,7 @@ import static org.sonar.db.user.GroupTesting.newGroupDto; import static org.sonar.db.user.UserTesting.newUserDto; import static org.sonar.server.issue.IssueDocTesting.newDoc; -public class IssueIndexTest { - - @Rule - public EsTester es = EsTester.create(); - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); - private final System2 system2 = new TestSystem2().setNow(1_500_000_000_000L).setDefaultTimeZone(getTimeZone("GMT-01:00")); - @Rule - public DbTester db = DbTester.create(system2); - - private final AsyncIssueIndexing asyncIssueIndexing = mock(AsyncIssueIndexing.class); - private final IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()), asyncIssueIndexing); - private final RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient()); - private final PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, issueIndexer); - - private final IssueIndex underTest = new IssueIndex(es.client(), system2, userSessionRule, new WebAuthorizationTypeSupport(userSessionRule)); +public class IssueIndexTest extends IssueIndexTestCommon { @Test public void paging() { @@ -387,32 +355,7 @@ public class IssueIndexTest { return IssueQuery.builder().projectUuids(singletonList(projectUuid)).resolved(false).build(); } - private void indexIssues(IssueDoc... issues) { - issueIndexer.index(asList(issues).iterator()); - authorizationIndexer.allow(stream(issues).map(issue -> new IndexPermissions(issue.projectUuid(), PROJECT).allowAnyone()).collect(toList())); - } - private void indexIssue(IssueDoc issue) { issueIndexer.index(Iterators.singletonIterator(issue)); } - - /** - * Execute the search request and return the document ids of results. - */ - private List<String> searchAndReturnKeys(IssueQuery.Builder query) { - return Arrays.stream(underTest.search(query.build(), new SearchOptions()).getHits().getHits()) - .map(SearchHit::getId) - .collect(Collectors.toList()); - } - - private void assertThatSearchReturnsOnly(IssueQuery.Builder query, String... expectedIssueKeys) { - List<String> keys = searchAndReturnKeys(query); - assertThat(keys).containsExactlyInAnyOrder(expectedIssueKeys); - } - - private void assertThatSearchReturnsEmpty(IssueQuery.Builder query) { - List<String> keys = searchAndReturnKeys(query); - assertThat(keys).isEmpty(); - } - } diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexTestCommon.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexTestCommon.java new file mode 100644 index 00000000000..ca097cc2e21 --- /dev/null +++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexTestCommon.java @@ -0,0 +1,89 @@ +/* + * 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.issue.index; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.elasticsearch.search.SearchHit; +import org.junit.Rule; +import org.sonar.api.impl.utils.TestSystem2; +import org.sonar.api.utils.System2; +import org.sonar.db.DbTester; +import org.sonar.server.es.EsTester; +import org.sonar.server.es.SearchOptions; +import org.sonar.server.permission.index.IndexPermissions; +import org.sonar.server.permission.index.PermissionIndexerTester; +import org.sonar.server.permission.index.WebAuthorizationTypeSupport; +import org.sonar.server.rule.index.RuleIndexer; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.view.index.ViewIndexer; + +import static java.util.Arrays.asList; +import static java.util.Arrays.stream; +import static java.util.TimeZone.getTimeZone; +import static java.util.stream.Collectors.toList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.sonar.api.resources.Qualifiers.PROJECT; + +public class IssueIndexTestCommon { + + @Rule + public EsTester es = EsTester.create(); + @Rule + public UserSessionRule userSessionRule = UserSessionRule.standalone(); + protected final System2 system2 = new TestSystem2().setNow(1_500_000_000_000L).setDefaultTimeZone(getTimeZone("GMT-01:00")); + @Rule + public DbTester db = DbTester.create(system2); + + private final AsyncIssueIndexing asyncIssueIndexing = mock(AsyncIssueIndexing.class); + protected final IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()), asyncIssueIndexing); + protected final RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient()); + protected final PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, issueIndexer); + protected final ViewIndexer viewIndexer = new ViewIndexer(db.getDbClient(), es.client()); + + protected final IssueIndex underTest = new IssueIndex(es.client(), system2, userSessionRule, new WebAuthorizationTypeSupport(userSessionRule)); + + /** + * Execute the search request and return the document ids of results. + */ + protected List<String> searchAndReturnKeys(IssueQuery.Builder query) { + return Arrays.stream(underTest.search(query.build(), new SearchOptions()).getHits().getHits()) + .map(SearchHit::getId) + .collect(Collectors.toList()); + } + + protected void assertThatSearchReturnsOnly(IssueQuery.Builder query, String... expectedIssueKeys) { + List<String> keys = searchAndReturnKeys(query); + assertThat(keys).containsExactlyInAnyOrder(expectedIssueKeys); + } + + protected void assertThatSearchReturnsEmpty(IssueQuery.Builder query) { + List<String> keys = searchAndReturnKeys(query); + assertThat(keys).isEmpty(); + } + + protected void indexIssues(IssueDoc... issues) { + issueIndexer.index(asList(issues).iterator()); + authorizationIndexer.allow(stream(issues).map(issue -> new IndexPermissions(issue.projectUuid(), PROJECT).allowAnyone()).collect(toList())); + } + +} |