From 3df9f54c48861976d48a6a9559d7c9fc3953dfec Mon Sep 17 00:00:00 2001 From: =?utf8?q?L=C3=A9o=20Geoffroy?= Date: Wed, 3 May 2023 11:57:57 +0200 Subject: [PATCH] SONAR-18742 Remove usage of 'BRC' in component/search and component/tree --- .../sonar/db/component/ResourceTypesRule.java | 19 ++++++--- .../server/component/ws/SearchActionIT.java | 2 +- .../server/component/ws/TreeActionIT.java | 40 ++++++++++++++----- .../measure/ws/ComponentTreeActionIT.java | 28 ++++++++++++- .../server/component/ws/SearchAction.java | 2 +- .../sonar/server/component/ws/TreeAction.java | 3 +- .../measure/ws/ComponentTreeAction.java | 2 + .../sonar/server/ws/WsParameterBuilder.java | 1 + .../server/ws/WsParameterBuilderTest.java | 27 +++++++++++++ .../core/component/DefaultResourceTypes.java | 2 + 10 files changed, 104 insertions(+), 22 deletions(-) diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ResourceTypesRule.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ResourceTypesRule.java index 75bd9076f38..54a3500574d 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ResourceTypesRule.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ResourceTypesRule.java @@ -19,8 +19,7 @@ */ package org.sonar.db.component; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; @@ -53,18 +52,23 @@ public class ResourceTypesRule extends ResourceTypes { return rootResourceTypes; } + public ResourceTypesRule setRootQualifiers(Collection qualifiers) { + rootResourceTypes = Set.copyOf(qualifiers); + return this; + } + public ResourceTypesRule setRootQualifiers(String... qualifiers) { Set resourceTypes = new LinkedHashSet<>(); for (String qualifier : qualifiers) { resourceTypes.add(ResourceType.builder(qualifier).setProperty("deletable", true).build()); } - rootResourceTypes = ImmutableSet.copyOf(resourceTypes); + rootResourceTypes = Set.copyOf(resourceTypes); return this; } public ResourceTypesRule setLeavesQualifiers(String... qualifiers) { - leavesQualifiers = ImmutableList.copyOf(qualifiers); + leavesQualifiers = List.copyOf(Arrays.asList(qualifiers)); return this; } @@ -73,8 +77,13 @@ public class ResourceTypesRule extends ResourceTypes { for (String qualifier : qualifiers) { resourceTypes.add(ResourceType.builder(qualifier).setProperty("deletable", true).build()); } - allResourceTypes = ImmutableSet.copyOf(resourceTypes); + allResourceTypes = Set.copyOf(resourceTypes); + + return this; + } + public ResourceTypesRule setAllQualifiers(Collection qualifiers) { + allResourceTypes = Set.copyOf(qualifiers); return this; } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchActionIT.java index ba1046dc567..cee0b778bfb 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchActionIT.java @@ -101,7 +101,7 @@ public class SearchActionIT { .extracting(Change::getVersion, Change::getDescription) .containsExactlyInAnyOrder( tuple("8.4", "Param 'language' has been removed"), - tuple("8.4", "The use of 'DIR','FIL','UTS' as values for parameter 'qualifiers' is no longer supported"), + tuple("8.4", "The use of 'DIR','FIL','UTS' and 'BRC' as values for parameter 'qualifiers' is no longer supported"), tuple("8.0", "Field 'id' from response has been removed"), tuple("7.6", "The use of 'BRC' as value for parameter 'qualifiers' is deprecated")); assertThat(action.responseExampleAsString()).isNotEmpty(); diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/TreeActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/TreeActionIT.java index 53464931db8..6b02526188a 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/TreeActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/TreeActionIT.java @@ -30,11 +30,14 @@ import javax.annotation.Nullable; import org.apache.commons.io.IOUtils; import org.junit.Rule; import org.junit.Test; +import org.sonar.api.resources.ResourceTypeTree; +import org.sonar.api.resources.ResourceTypes; import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; +import org.sonar.core.component.DefaultResourceTypes; import org.sonar.core.i18n.I18n; import org.sonar.db.DbClient; import org.sonar.db.DbTester; @@ -59,7 +62,6 @@ import static org.assertj.core.api.Assertions.tuple; import static org.mockito.Mockito.mock; import static org.sonar.api.resources.Qualifiers.APP; import static org.sonar.api.resources.Qualifiers.FILE; -import static org.sonar.api.resources.Qualifiers.PROJECT; import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE; import static org.sonar.db.component.BranchDto.DEFAULT_MAIN_BRANCH_NAME; import static org.sonar.db.component.BranchType.PULL_REQUEST; @@ -80,13 +82,13 @@ public class TreeActionIT { public UserSessionRule userSession = UserSessionRule.standalone(); @Rule public DbTester db = DbTester.create(System2.INSTANCE); - - private ResourceTypesRule resourceTypes = new ResourceTypesRule() - .setRootQualifiers(PROJECT) + private final DbClient dbClient = db.getDbClient(); + private final ResourceTypes defaultResourceTypes = new ResourceTypes(new ResourceTypeTree[]{DefaultResourceTypes.get()}); + private final ResourceTypesRule resourceTypes = new ResourceTypesRule() + .setRootQualifiers(defaultResourceTypes.getRoots()) + .setAllQualifiers(defaultResourceTypes.getAll()) .setLeavesQualifiers(FILE, UNIT_TEST_FILE); - private DbClient dbClient = db.getDbClient(); - - private WsActionTester ws = new WsActionTester(new TreeAction(dbClient, new ComponentFinder(dbClient, resourceTypes), resourceTypes, userSession, + private final WsActionTester ws = new WsActionTester(new TreeAction(dbClient, new ComponentFinder(dbClient, resourceTypes), resourceTypes, userSession, mock(I18n.class))); @Test @@ -97,6 +99,7 @@ public class TreeActionIT { assertThat(action.description()).isNotNull(); assertThat(action.responseExample()).isNotNull(); assertThat(action.changelog()).extracting(Change::getVersion, Change::getDescription).containsExactlyInAnyOrder( + tuple("10.1", "The use of 'BRC' as value for parameter 'qualifiers' is removed"), tuple("7.6", "The use of 'BRC' as value for parameter 'qualifiers' is deprecated"), tuple("7.6", "The use of module keys in parameter 'component' is deprecated")); assertThat(action.params()).extracting(Param::key).containsExactlyInAnyOrder("component", "branch", "pullRequest", "qualifiers", "strategy", @@ -533,10 +536,10 @@ public class TreeActionIT { private ComponentDto initJsonExampleComponents() throws IOException { ComponentDto project = db.components().insertPrivateProject(c -> c.setUuid("MY_PROJECT_ID") - .setDescription("MY_PROJECT_DESCRIPTION") - .setKey("MY_PROJECT_KEY") - .setName("Project Name") - .setBranchUuid("MY_PROJECT_ID"), + .setDescription("MY_PROJECT_DESCRIPTION") + .setKey("MY_PROJECT_KEY") + .setName("Project Name") + .setBranchUuid("MY_PROJECT_ID"), p -> p.setTagsString("abc,def")); db.components().insertSnapshot(project); @@ -571,4 +574,19 @@ public class TreeActionIT { private void logInWithBrowsePermission(ComponentDto project) { userSession.logIn().addProjectPermission(UserRole.USER, project); } + + @Test + public void doHandle_whenPassingUnsupportedQualifier_ShouldThrowIllegalArgumentException() { + ComponentDto project = newPrivateProjectDto("project-uuid"); + db.components().insertProjectAndSnapshot(project); + db.commit(); + logInWithBrowsePermission(project); + + TestRequest testRequest = ws.newRequest() + .setParam(PARAM_QUALIFIERS, "BRC") + .setParam(PARAM_COMPONENT, project.getKey()); + + assertThatThrownBy(testRequest::execute).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Value of parameter 'qualifiers' (BRC) must be one of: [UTS, FIL, DIR, TRK]"); + } } diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentTreeActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentTreeActionIT.java index a03feacb19d..7b0c0e6db2d 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentTreeActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentTreeActionIT.java @@ -26,8 +26,11 @@ import org.junit.Rule; import org.junit.Test; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; +import org.sonar.api.resources.ResourceTypeTree; +import org.sonar.api.resources.ResourceTypes; import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.System2; +import org.sonar.core.component.DefaultResourceTypes; import org.sonar.core.util.stream.MoreCollectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; @@ -46,6 +49,7 @@ import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.l18n.I18nRule; import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.WsActionTester; import org.sonarqube.ws.Common; import org.sonarqube.ws.Measures.ComponentTreeWsResponse; @@ -64,7 +68,6 @@ import static org.sonar.api.measures.Metric.ValueType.RATING; import static org.sonar.api.resources.Qualifiers.APP; import static org.sonar.api.resources.Qualifiers.DIRECTORY; import static org.sonar.api.resources.Qualifiers.FILE; -import static org.sonar.api.resources.Qualifiers.PROJECT; import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE; import static org.sonar.api.server.ws.WebService.Param.SORT; import static org.sonar.api.utils.DateUtils.parseDateTime; @@ -102,9 +105,13 @@ public class ComponentTreeActionIT { public DbTester db = DbTester.create(System2.INSTANCE); private final I18nRule i18n = new I18nRule(); + + private final ResourceTypes defaultResourceTypes = new ResourceTypes(new ResourceTypeTree[]{DefaultResourceTypes.get()}); private final ResourceTypesRule resourceTypes = new ResourceTypesRule() - .setRootQualifiers(PROJECT) + .setRootQualifiers(defaultResourceTypes.getRoots()) + .setAllQualifiers(defaultResourceTypes.getAll()) .setLeavesQualifiers(FILE, UNIT_TEST_FILE); + private final DbClient dbClient = db.getDbClient(); private final DbSession dbSession = db.getSession(); @@ -1059,6 +1066,23 @@ public class ComponentTreeActionIT { .hasMessage(String.format("Component '%s' on branch '%s' not found", file.getKey(), "another_branch")); } + @Test + public void doHandle_whenPassingUnexpectedQualifier_shouldThrowException(){ + ComponentDto project = db.components().insertPrivateProject(); + userSession.addProjectPermission(USER, project); + ComponentDto file = db.components().insertComponent(newFileDto(project)); + MetricDto complexity = db.measures().insertMetric(m -> m.setValueType(INT.name())); + + TestRequest testRequest = ws.newRequest() + .setParam(PARAM_COMPONENT, file.getKey()) + .setParam(PARAM_BRANCH, BranchDto.DEFAULT_MAIN_BRANCH_NAME) + .setParam(PARAM_QUALIFIERS, "BRC") + .setParam(PARAM_METRIC_KEYS, complexity.getKey()); + + assertThatThrownBy(()->testRequest.execute()).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Value of parameter 'qualifiers' (BRC) must be one of: [UTS, FIL, DIR, TRK]"); + } + private static MetricDto newMetricDto() { return MetricTesting.newMetricDto() .setWorstValue(null) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchAction.java index 289e3a5ea72..325bdfb9c16 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchAction.java @@ -81,7 +81,7 @@ public class SearchAction implements ComponentsWsAction { .addPagingParams(100, MAX_PAGE_SIZE) .setChangelog( new Change("8.4", "Param 'language' has been removed"), - new Change("8.4", String.format("The use of 'DIR','FIL','UTS' as values for parameter '%s' is no longer supported", PARAM_QUALIFIERS)), + new Change("8.4", String.format("The use of 'DIR','FIL','UTS' and 'BRC' as values for parameter '%s' is no longer supported", PARAM_QUALIFIERS)), new Change("8.0", "Field 'id' from response has been removed"), new Change("7.6", String.format("The use of 'BRC' as value for parameter '%s' is deprecated", PARAM_QUALIFIERS))) .setResponseExample(getClass().getResource("search-components-example.json")) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/TreeAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/TreeAction.java index 1f786a346cb..5b8b1aa8343 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/TreeAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/TreeAction.java @@ -29,7 +29,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import javax.annotation.CheckForNull; @@ -59,7 +58,6 @@ import org.sonarqube.ws.Components.TreeWsResponse; import static java.lang.String.CASE_INSENSITIVE_ORDER; import static java.lang.String.format; import static java.util.Collections.emptyMap; -import static java.util.Optional.ofNullable; import static org.sonar.api.utils.Paging.offset; import static org.sonar.core.util.stream.MoreCollectors.toList; import static org.sonar.db.component.ComponentTreeQuery.Strategy.CHILDREN; @@ -121,6 +119,7 @@ public class TreeAction implements ComponentsWsAction { .setSince("5.4") .setResponseExample(getClass().getResource("tree-example.json")) .setChangelog( + new Change("10.1", String.format("The use of 'BRC' as value for parameter '%s' is removed", PARAM_QUALIFIERS)), new Change("7.6", String.format("The use of 'BRC' as value for parameter '%s' is deprecated", PARAM_QUALIFIERS)), new Change("7.6", String.format("The use of module keys in parameter '%s' is deprecated", PARAM_COMPONENT))) .setHandler(this) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java index 35dfde3e2f1..61c1007b0d9 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java @@ -71,6 +71,7 @@ import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.user.UserSession; import org.sonarqube.ws.Measures; import org.sonarqube.ws.Measures.ComponentTreeWsResponse; +import org.sonarqube.ws.client.component.ComponentsWsParameters; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; @@ -178,6 +179,7 @@ public class ComponentTreeAction implements MeasuresWsAction { .setHandler(this) .addPagingParams(100, MAX_SIZE) .setChangelog( + new Change("10.1", String.format("The use of 'BRC' as value for parameter '%s' is removed", ComponentsWsParameters.PARAM_QUALIFIERS)), new Change("10.0", format("The use of the following metrics in 'metricKeys' parameter is not deprecated anymore: %s", MeasuresWsModule.getDeprecatedMetrics())), new Change("10.0", "the response field periods under measures field is removed."), diff --git a/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WsParameterBuilder.java b/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WsParameterBuilder.java index c22b170106a..7cee9dc1473 100644 --- a/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WsParameterBuilder.java +++ b/server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/WsParameterBuilder.java @@ -85,6 +85,7 @@ public class WsParameterBuilder { private static Set getAllQualifiers(ResourceTypes resourceTypes) { return resourceTypes.getAll().stream() + .filter(r -> !r.getBooleanProperty("ignored")) .map(ResourceType::getQualifier) .collect(Collectors.toCollection(TreeSet::new)); } diff --git a/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WsParameterBuilderTest.java b/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WsParameterBuilderTest.java index d766ab2afd8..0694fea6e0e 100644 --- a/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WsParameterBuilderTest.java +++ b/server/sonar-webserver-ws/src/test/java/org/sonar/server/ws/WsParameterBuilderTest.java @@ -33,6 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.startsWith; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS; @@ -122,4 +123,30 @@ public class WsParameterBuilderTest { assertThat(newParam).isNotNull(); } + + @Test + public void createQualifiersParameter_whenIgnoreIsSetToTrue_shouldNotReturnQualifier(){ + when(resourceTypes.getAll()).thenReturn(asList(Q1, Q2,ResourceType.builder("Q3").setProperty("ignored", true).build())); + when(newAction.createParam(PARAM_QUALIFIERS)).thenReturn(newParam); + when(newParam.setPossibleValues(any(Collection.class))).thenReturn(newParam); + when(newParam.setDescription(any())).thenReturn(newParam); + NewParam newParam = WsParameterBuilder + .createQualifiersParameter(newAction, newQualifierParameterContext(i18n, resourceTypes)); + + verify(newParam).setPossibleValues(Sets.newHashSet(Q1.getQualifier(), Q2.getQualifier())); + } + + @Test + public void createQualifiersParameter_whenIgnoreIsSetToFalse_shouldReturnQualifier(){ + ResourceType q3Qualifier = ResourceType.builder("Q3").setProperty("ignored", false).build(); + when(resourceTypes.getAll()).thenReturn(asList(Q1, Q2, q3Qualifier)); + when(newAction.createParam(PARAM_QUALIFIERS)).thenReturn(newParam); + when(newParam.setPossibleValues(any(Collection.class))).thenReturn(newParam); + when(newParam.setDescription(any())).thenReturn(newParam); + NewParam newParam = WsParameterBuilder + .createQualifiersParameter(newAction, newQualifierParameterContext(i18n, resourceTypes)); + + verify(newParam).setPossibleValues(Sets.newHashSet(Q1.getQualifier(), Q2.getQualifier(), q3Qualifier.getQualifier())); + } + } diff --git a/sonar-core/src/main/java/org/sonar/core/component/DefaultResourceTypes.java b/sonar-core/src/main/java/org/sonar/core/component/DefaultResourceTypes.java index 22ddb56748c..72c6aa4635b 100644 --- a/sonar-core/src/main/java/org/sonar/core/component/DefaultResourceTypes.java +++ b/sonar-core/src/main/java/org/sonar/core/component/DefaultResourceTypes.java @@ -33,6 +33,7 @@ public final class DefaultResourceTypes { private static final String CONFIGURABLE = "configurable"; private static final String UPDATABLE_KEY = "updatable_key"; + public static final String IGNORED = "ignored"; private DefaultResourceTypes() { // only static methods @@ -51,6 +52,7 @@ public final class DefaultResourceTypes { .addType(ResourceType.builder(Qualifiers.MODULE) .setProperty(UPDATABLE_KEY, true) .setProperty(CONFIGURABLE, true) + .setProperty(IGNORED, true) .build()) .addType(ResourceType.builder(Qualifiers.DIRECTORY) .build()) -- 2.39.5