From: Teryk Bellahsene Date: Wed, 13 Jun 2018 16:49:50 +0000 (+0200) Subject: SONAR-10813 Define project branches in an application X-Git-Tag: 7.5~915 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f94bc6f1b9be3b9180aef88abe1804b4aaaa194a;p=sonarqube.git SONAR-10813 Define project branches in an application --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/branch/ws/DeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/branch/ws/DeleteAction.java index cde6921b059..1da2eb87f33 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/branch/ws/DeleteAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/branch/ws/DeleteAction.java @@ -30,13 +30,16 @@ import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; import org.sonar.server.component.ComponentCleanerService; import org.sonar.server.component.ComponentFinder; +import org.sonar.server.project.ProjectLifeCycleListeners; import org.sonar.server.user.UserSession; +import static java.util.Collections.singleton; import static org.sonar.server.branch.ws.BranchesWs.addBranchParam; import static org.sonar.server.branch.ws.BranchesWs.addProjectParam; import static org.sonar.server.branch.ws.ProjectBranchesParameters.ACTION_DELETE; import static org.sonar.server.branch.ws.ProjectBranchesParameters.PARAM_BRANCH; import static org.sonar.server.branch.ws.ProjectBranchesParameters.PARAM_PROJECT; +import static org.sonar.server.project.Project.from; import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; public class DeleteAction implements BranchWsAction { @@ -44,12 +47,15 @@ public class DeleteAction implements BranchWsAction { private final UserSession userSession; private final ComponentCleanerService componentCleanerService; private final ComponentFinder componentFinder; + private final ProjectLifeCycleListeners projectLifeCycleListeners; - public DeleteAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, ComponentCleanerService componentCleanerService) { + public DeleteAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, ComponentCleanerService componentCleanerService, + ProjectLifeCycleListeners projectLifeCycleListeners) { this.dbClient = dbClient; this.componentFinder = componentFinder; this.userSession = userSession; this.componentCleanerService = componentCleanerService; + this.projectLifeCycleListeners = projectLifeCycleListeners; } @Override @@ -84,6 +90,7 @@ public class DeleteAction implements BranchWsAction { } ComponentDto branchComponent = componentFinder.getByKeyAndBranch(dbSession, projectKey, branchKey); componentCleanerService.deleteBranch(dbSession, branchComponent); + projectLifeCycleListeners.onProjectBranchesDeleted(singleton(from(project))); response.noContent(); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java index ef86ba3c9c7..558ac7d492a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java @@ -67,8 +67,8 @@ import static org.sonar.server.component.ws.ComponentDtoToWsComponent.componentD import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001; -import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; import static org.sonar.server.ws.WsParameterBuilder.createQualifiersParameter; +import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; import static org.sonar.server.ws.WsUtils.checkRequest; import static org.sonar.server.ws.WsUtils.writeProtobuf; import static org.sonarqube.ws.client.component.ComponentsWsParameters.ACTION_TREE; @@ -252,7 +252,7 @@ public class TreeAction implements ComponentsWsAction { ComponentDto referenceComponent = referenceComponentsByUuid.get(component.getCopyResourceUuid()); if (referenceComponent != null) { wsComponent.setRefId(referenceComponent.uuid()); - wsComponent.setRefKey(referenceComponent.getDbKey()); + wsComponent.setRefKey(referenceComponent.getKey()); } return wsComponent; diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java index 29e881db26b..7e5c5c1ca51 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -316,6 +316,7 @@ public class IssueIndex { if (onApplicationBranch) { filters.put("__view", createViewFilter(singletonList(query.branchUuid()))); } else { + filters.put("__is_main_branch", createTermFilter(IssueIndexDefinition.FIELD_ISSUE_IS_MAIN_BRANCH, Boolean.toString(true))); filters.put("__view", createViewFilter(viewUuids)); } } @@ -328,7 +329,7 @@ public class IssueIndex { BoolQueryBuilder viewsFilter = boolQuery(); for (String viewUuid : viewUuids) { - viewsFilter.should(QueryBuilders.termsLookupQuery(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, + viewsFilter.should(QueryBuilders.termsLookupQuery(IssueIndexDefinition.FIELD_ISSUE_BRANCH_UUID, new TermsLookup( ViewIndexDefinition.INDEX_TYPE_VIEW.getIndex(), ViewIndexDefinition.INDEX_TYPE_VIEW.getType(), diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java index 3adddc09965..2f1ffe9ac6e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java @@ -111,8 +111,8 @@ import static org.sonar.server.measure.ws.SnapshotDtoToWsPeriods.snapshotToWsPer import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001; -import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; import static org.sonar.server.ws.WsParameterBuilder.createQualifiersParameter; +import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; import static org.sonar.server.ws.WsUtils.checkRequest; import static org.sonar.server.ws.WsUtils.writeProtobuf; @@ -388,7 +388,7 @@ public class ComponentTreeAction implements MeasuresWsAction { ComponentDto referenceComponent = referenceComponentsByUuid.get(component.getCopyResourceUuid()); if (referenceComponent != null) { wsComponent.setRefId(referenceComponent.uuid()); - wsComponent.setRefKey(referenceComponent.getDbKey()); + wsComponent.setRefKey(referenceComponent.getKey()); } Measures.Measure.Builder measureBuilder = Measures.Measure.newBuilder(); for (Map.Entry entry : measures.entrySet()) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java b/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java index 9b3c092b3db..05630721431 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java +++ b/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListener.java @@ -29,6 +29,11 @@ public interface ProjectLifeCycleListener { */ void onProjectsDeleted(Set projects); + /** + * This method is called after the specified projects have been deleted. + */ + void onProjectBranchesDeleted(Set projects); + /** * This method is called after the specified projects' keys have been modified. */ diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java b/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java index 9b2c7b76d59..86158036742 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java +++ b/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListeners.java @@ -32,6 +32,16 @@ public interface ProjectLifeCycleListeners { */ void onProjectsDeleted(Set projects); + /** + * This method is called after the specified project branches have been deleted and will call method + * {@link ProjectLifeCycleListener#onProjectBranchesDeleted(Set)} of all known + * {@link ProjectLifeCycleListener} implementations. + *

+ * This method ensures all {@link ProjectLifeCycleListener} implementations are called, even if one or more of + * them fail with an exception. + */ + void onProjectBranchesDeleted(Set projects); + /** * This method is called after the specified project's key has been changed and will call method * {@link ProjectLifeCycleListener#onProjectsRekeyed(Set) onProjectsRekeyed(Set)} of all known diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java b/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java index 0ca49891b2e..f2665ea67a5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/project/ProjectLifeCycleListenersImpl.java @@ -57,6 +57,17 @@ public class ProjectLifeCycleListenersImpl implements ProjectLifeCycleListeners .forEach(safelyCallListener(listener -> listener.onProjectsDeleted(projects))); } + @Override + public void onProjectBranchesDeleted(Set projects) { + checkNotNull(projects, "projects can't be null"); + if (projects.isEmpty()) { + return; + } + + Arrays.stream(listeners) + .forEach(safelyCallListener(listener -> listener.onProjectBranchesDeleted(projects))); + } + @Override public void onProjectsRekeyed(Set rekeyedProjects) { checkNotNull(rekeyedProjects, "rekeyedProjects can't be null"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/branch/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/branch/ws/DeleteActionTest.java index 691087c4690..7797be99415 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/branch/ws/DeleteActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/branch/ws/DeleteActionTest.java @@ -34,9 +34,12 @@ import org.sonar.server.component.ComponentFinder; import org.sonar.server.component.TestComponentFinder; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.exceptions.UnauthorizedException; +import org.sonar.server.project.Project; +import org.sonar.server.project.ProjectLifeCycleListeners; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsActionTester; +import static java.util.Collections.singleton; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -51,20 +54,26 @@ public class DeleteActionTest { private ComponentCleanerService componentCleanerService = mock(ComponentCleanerService.class); private ComponentFinder componentFinder = TestComponentFinder.from(db); + private ProjectLifeCycleListeners projectLifeCycleListeners = mock(ProjectLifeCycleListeners.class); @Rule public UserSessionRule userSession = UserSessionRule.standalone(); - public WsActionTester tester = new WsActionTester(new DeleteAction(db.getDbClient(), componentFinder, userSession, componentCleanerService)); + public WsActionTester tester = new WsActionTester(new DeleteAction(db.getDbClient(), componentFinder, userSession, componentCleanerService, projectLifeCycleListeners)); @Test - public void test_definition() { - WebService.Action definition = tester.getDef(); - assertThat(definition.key()).isEqualTo("delete"); - assertThat(definition.isPost()).isTrue(); - assertThat(definition.isInternal()).isFalse(); - assertThat(definition.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("project", "branch"); - assertThat(definition.since()).isEqualTo("6.6"); + public void delete_branch() { + ComponentDto project = db.components().insertMainBranch(); + ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey("branch1")); + userSession.logIn().addProjectPermission(UserRole.ADMIN, project); + + tester.newRequest() + .setParam("project", project.getKey()) + .setParam("branch", "branch1") + .execute(); + + verifyDeletedKey(branch.getDbKey()); + verify(projectLifeCycleListeners).onProjectBranchesDeleted(singleton(Project.from(project))); } @Test @@ -139,16 +148,13 @@ public class DeleteActionTest { } @Test - public void delete_branch() { - ComponentDto project = db.components().insertMainBranch(); - ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey("branch1")); - userSession.logIn().addProjectPermission(UserRole.ADMIN, project); - - tester.newRequest() - .setParam("project", project.getKey()) - .setParam("branch", "branch1") - .execute(); - verifyDeletedKey(branch.getDbKey()); + public void definition() { + WebService.Action definition = tester.getDef(); + assertThat(definition.key()).isEqualTo("delete"); + assertThat(definition.isPost()).isTrue(); + assertThat(definition.isInternal()).isFalse(); + assertThat(definition.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("project", "branch"); + assertThat(definition.since()).isEqualTo("6.6"); } private void verifyDeletedKey(String key) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/TreeActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/TreeActionTest.java index 4452efaa621..d3c21cd19b0 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/TreeActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/TreeActionTest.java @@ -40,7 +40,6 @@ import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbTester; -import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; import org.sonar.db.component.ResourceTypesRule; @@ -53,11 +52,13 @@ import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsActionTester; import org.sonar.test.JsonAssert; import org.sonarqube.ws.Components; +import org.sonarqube.ws.Components.Component; import org.sonarqube.ws.Components.TreeWsResponse; import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; +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; @@ -87,7 +88,6 @@ public class TreeActionTest { private ResourceTypesRule resourceTypes = new ResourceTypesRule() .setRootQualifiers(PROJECT) .setLeavesQualifiers(FILE, UNIT_TEST_FILE); - private ComponentDbTester componentDb = new ComponentDbTester(db); private DbClient dbClient = db.getDbClient(); private WsActionTester ws = new WsActionTester(new TreeAction(dbClient, new ComponentFinder(dbClient, resourceTypes), resourceTypes, userSession, Mockito.mock(I18n.class))); @@ -142,16 +142,16 @@ public class TreeActionTest { @Test public void return_children() { ComponentDto project = newPrivateProjectDto(db.organizations().insert(), "project-uuid"); - componentDb.insertProjectAndSnapshot(project); + db.components().insertProjectAndSnapshot(project); ComponentDto module = newModuleDto("module-uuid-1", project); - componentDb.insertComponent(module); - componentDb.insertComponent(newFileDto(project, 1)); + db.components().insertComponent(module); + db.components().insertComponent(newFileDto(project, 1)); for (int i = 2; i <= 9; i++) { - componentDb.insertComponent(newFileDto(module, i)); + db.components().insertComponent(newFileDto(module, i)); } ComponentDto directory = newDirectory(module, "directory-path-1"); - componentDb.insertComponent(directory); - componentDb.insertComponent(newFileDto(module, directory, 10)); + db.components().insertComponent(directory); + db.components().insertComponent(newFileDto(module, directory, 10)); db.commit(); logInWithBrowsePermission(project); @@ -172,16 +172,16 @@ public class TreeActionTest { @Test public void return_descendants() { ComponentDto project = newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid"); - SnapshotDto projectSnapshot = componentDb.insertProjectAndSnapshot(project); + SnapshotDto projectSnapshot = db.components().insertProjectAndSnapshot(project); ComponentDto module = newModuleDto("module-uuid-1", project); - componentDb.insertComponent(module); - componentDb.insertComponent(newFileDto(project, 10)); + db.components().insertComponent(module); + db.components().insertComponent(newFileDto(project, 10)); for (int i = 2; i <= 9; i++) { - componentDb.insertComponent(newFileDto(module, i)); + db.components().insertComponent(newFileDto(module, i)); } ComponentDto directory = newDirectory(module, "directory-path-1"); - componentDb.insertComponent(directory); - componentDb.insertComponent(newFileDto(module, directory, 1)); + db.components().insertComponent(directory); + db.components().insertComponent(newFileDto(module, directory, 1)); db.commit(); logInWithBrowsePermission(project); @@ -202,10 +202,10 @@ public class TreeActionTest { @Test public void filter_descendants_by_qualifier() { ComponentDto project = newPrivateProjectDto(db.organizations().insert(), "project-uuid"); - componentDb.insertProjectAndSnapshot(project); - componentDb.insertComponent(newFileDto(project, 1)); - componentDb.insertComponent(newFileDto(project, 2)); - componentDb.insertComponent(newModuleDto("module-uuid-1", project)); + db.components().insertProjectAndSnapshot(project); + db.components().insertComponent(newFileDto(project, 1)); + db.components().insertComponent(newFileDto(project, 2)); + db.components().insertComponent(newModuleDto("module-uuid-1", project)); db.commit(); logInWithBrowsePermission(project); @@ -220,14 +220,14 @@ public class TreeActionTest { @Test public void return_leaves() { ComponentDto project = newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid"); - componentDb.insertProjectAndSnapshot(project); + db.components().insertProjectAndSnapshot(project); ComponentDto module = newModuleDto("module-uuid-1", project); - componentDb.insertComponent(module); - componentDb.insertComponent(newFileDto(project, 1)); - componentDb.insertComponent(newFileDto(module, 2)); + db.components().insertComponent(module); + db.components().insertComponent(newFileDto(project, 1)); + db.components().insertComponent(newFileDto(module, 2)); ComponentDto directory = newDirectory(project, "directory-path-1"); - componentDb.insertComponent(directory); - componentDb.insertComponent(newFileDto(module, directory, 3)); + db.components().insertComponent(directory); + db.components().insertComponent(newFileDto(module, directory, 3)); db.commit(); logInWithBrowsePermission(project); @@ -244,12 +244,12 @@ public class TreeActionTest { @Test public void sort_descendants_by_qualifier() { ComponentDto project = newPrivateProjectDto(db.organizations().insert(), "project-uuid"); - componentDb.insertProjectAndSnapshot(project); - componentDb.insertComponent(newFileDto(project, 1)); - componentDb.insertComponent(newFileDto(project, 2)); + db.components().insertProjectAndSnapshot(project); + db.components().insertComponent(newFileDto(project, 1)); + db.components().insertComponent(newFileDto(project, 2)); ComponentDto module = newModuleDto("module-uuid-1", project); - componentDb.insertComponent(module); - componentDb.insertComponent(newDirectory(project, "path/directory/", "directory-uuid-1")); + db.components().insertComponent(module); + db.components().insertComponent(newDirectory(project, "path/directory/", "directory-uuid-1")); db.commit(); logInWithBrowsePermission(project); @@ -262,14 +262,14 @@ public class TreeActionTest { } @Test - public void return_children_of_a_view() { + public void project_reference_from_portfolio() { OrganizationDto organizationDto = db.organizations().insert(); ComponentDto view = newView(organizationDto, "view-uuid"); - componentDb.insertViewAndSnapshot(view); + db.components().insertViewAndSnapshot(view); ComponentDto project = newPrivateProjectDto(organizationDto, "project-uuid-1").setName("project-name").setDbKey("project-key-1"); - componentDb.insertProjectAndSnapshot(project); - componentDb.insertComponent(newProjectCopy("project-uuid-1-copy", project, view)); - componentDb.insertComponent(newSubView(view, "sub-view-uuid", "sub-view-key").setName("sub-view-name")); + db.components().insertProjectAndSnapshot(project); + db.components().insertComponent(newProjectCopy("project-uuid-1-copy", project, view)); + db.components().insertComponent(newSubView(view, "sub-view-uuid", "sub-view-key").setName("sub-view-name")); db.commit(); userSession.logIn() .registerComponents(view, project); @@ -284,9 +284,32 @@ public class TreeActionTest { assertThat(response.getComponentsList()).extracting("refKey").containsExactly("project-key-1", ""); } + @Test + public void project_branch_reference_from_application_branch() { + ComponentDto application = db.components().insertMainBranch(c -> c.setQualifier(APP).setDbKey("app-key")); + ComponentDto applicationBranch = db.components().insertProjectBranch(application, a -> a.setKey("app-branch")); + ComponentDto project = db.components().insertPrivateProject(p -> p.setDbKey("project-key")); + ComponentDto projectBranch = db.components().insertProjectBranch(project, b -> b.setKey("project-branch")); + ComponentDto techProjectBranch = db.components().insertComponent(newProjectCopy(projectBranch, applicationBranch) + .setDbKey(applicationBranch.getKey() + applicationBranch.getBranch() + projectBranch.getDbKey())); + logInWithBrowsePermission(application); + + TreeWsResponse result = ws.newRequest() + .setParam(MeasuresWsParameters.PARAM_COMPONENT, applicationBranch.getKey()) + .setParam(MeasuresWsParameters.PARAM_BRANCH, applicationBranch.getBranch()) + .executeProtobuf(TreeWsResponse.class); + + assertThat(result.getBaseComponent()) + .extracting(Component::getKey, Component::getBranch) + .containsExactlyInAnyOrder(applicationBranch.getKey(), applicationBranch.getBranch()); + assertThat(result.getComponentsList()) + .extracting(Component::getKey, Component::getBranch, Component::getRefId, Component::getRefKey) + .containsExactlyInAnyOrder(tuple(techProjectBranch.getKey(), projectBranch.getBranch(), projectBranch.uuid(), project.getKey())); + } + @Test public void response_is_empty_on_provisioned_projects() { - ComponentDto project = componentDb.insertComponent(newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid")); + ComponentDto project = db.components().insertComponent(newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid")); logInWithBrowsePermission(project); TreeWsResponse response = ws.newRequest() @@ -302,10 +325,10 @@ public class TreeActionTest { @Test public void return_projects_composing_a_view() { ComponentDto project = newPrivateProjectDto(db.organizations().insert(), "project-uuid"); - componentDb.insertProjectAndSnapshot(project); + db.components().insertProjectAndSnapshot(project); ComponentDto view = newView(db.getDefaultOrganization(), "view-uuid"); - componentDb.insertViewAndSnapshot(view); - componentDb.insertComponent(newProjectCopy("project-copy-uuid", project, view)); + db.components().insertViewAndSnapshot(view); + db.components().insertComponent(newProjectCopy("project-copy-uuid", project, view)); userSession.logIn() .registerComponents(project, view); @@ -332,9 +355,9 @@ public class TreeActionTest { .setParam(PARAM_BRANCH, branchKey) .executeProtobuf(TreeWsResponse.class); - assertThat(response.getBaseComponent()).extracting(Components.Component::getKey, Components.Component::getBranch) + assertThat(response.getBaseComponent()).extracting(Component::getKey, Component::getBranch) .containsExactlyInAnyOrder(module.getKey(), branchKey); - assertThat(response.getComponentsList()).extracting(Components.Component::getKey, Components.Component::getBranch) + assertThat(response.getComponentsList()).extracting(Component::getKey, Component::getBranch) .containsExactlyInAnyOrder( tuple(directory.getKey(), branchKey), tuple(file.getKey(), branchKey)); @@ -355,9 +378,9 @@ public class TreeActionTest { .setParam(PARAM_PULL_REQUEST, pullRequestId) .executeProtobuf(TreeWsResponse.class); - assertThat(response.getBaseComponent()).extracting(Components.Component::getKey, Components.Component::getPullRequest) + assertThat(response.getBaseComponent()).extracting(Component::getKey, Component::getPullRequest) .containsExactlyInAnyOrder(module.getKey(), pullRequestId); - assertThat(response.getComponentsList()).extracting(Components.Component::getKey, Components.Component::getPullRequest) + assertThat(response.getComponentsList()).extracting(Component::getKey, Component::getPullRequest) .containsExactlyInAnyOrder( tuple(directory.getKey(), pullRequestId), tuple(file.getKey(), pullRequestId)); @@ -393,7 +416,7 @@ public class TreeActionTest { @Test public void fail_when_not_enough_privileges() { - ComponentDto project = componentDb.insertComponent(newPrivateProjectDto(db.organizations().insert(), "project-uuid")); + ComponentDto project = db.components().insertComponent(newPrivateProjectDto(db.organizations().insert(), "project-uuid")); userSession.logIn() .addProjectPermission(UserRole.CODEVIEWER, project); db.commit(); @@ -409,7 +432,7 @@ public class TreeActionTest { public void fail_when_page_size_above_500() { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("'ps' value (501) must be less than 500"); - componentDb.insertComponent(newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid")); + db.components().insertComponent(newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid")); db.commit(); ws.newRequest() @@ -422,7 +445,7 @@ public class TreeActionTest { public void fail_when_search_query_has_less_than_3_characters() { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("'q' length (2) is shorter than the minimum authorized (3)"); - componentDb.insertComponent(newPrivateProjectDto(db.organizations().insert(), "project-uuid")); + db.components().insertComponent(newPrivateProjectDto(db.organizations().insert(), "project-uuid")); db.commit(); ws.newRequest() @@ -434,7 +457,7 @@ public class TreeActionTest { @Test public void fail_when_sort_is_unknown() { expectedException.expect(IllegalArgumentException.class); - componentDb.insertComponent(newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid")); + db.components().insertComponent(newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid")); db.commit(); ws.newRequest() @@ -446,7 +469,7 @@ public class TreeActionTest { @Test public void fail_when_strategy_is_unknown() { expectedException.expect(IllegalArgumentException.class); - componentDb.insertComponent(newPrivateProjectDto(db.organizations().insert(), "project-uuid")); + db.components().insertComponent(newPrivateProjectDto(db.organizations().insert(), "project-uuid")); db.commit(); ws.newRequest() @@ -466,8 +489,8 @@ public class TreeActionTest { @Test public void fail_when_base_component_is_removed() { - ComponentDto project = componentDb.insertComponent(newPrivateProjectDto(db.getDefaultOrganization())); - componentDb.insertComponent(ComponentTesting.newFileDto(project).setDbKey("file-key").setEnabled(false)); + ComponentDto project = db.components().insertComponent(newPrivateProjectDto(db.getDefaultOrganization())); + db.components().insertComponent(ComponentTesting.newFileDto(project).setDbKey("file-key").setEnabled(false)); logInWithBrowsePermission(project); expectedException.expect(NotFoundException.class); @@ -532,7 +555,7 @@ public class TreeActionTest { ComponentDto project = newPrivateProjectDto(organizationDto, "MY_PROJECT_ID") .setDbKey("MY_PROJECT_KEY") .setName("Project Name"); - componentDb.insertProjectAndSnapshot(project); + db.components().insertProjectAndSnapshot(project); Date now = new Date(); JsonParser jsonParser = new JsonParser(); JsonElement jsonTree = jsonParser.parse(IOUtils.toString(getClass().getResource("tree-example.json"), UTF_8)); @@ -540,7 +563,7 @@ public class TreeActionTest { for (JsonElement componentAsJsonElement : components) { JsonObject componentAsJsonObject = componentAsJsonElement.getAsJsonObject(); String uuid = getJsonField(componentAsJsonObject, "id"); - componentDb.insertComponent(newChildComponent(uuid, project, project) + db.components().insertComponent(newChildComponent(uuid, project, project) .setDbKey(getJsonField(componentAsJsonObject, "key")) .setName(getJsonField(componentAsJsonObject, "name")) .setLanguage(getJsonField(componentAsJsonObject, "language")) diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java index b02ac50d17d..db95f8711dc 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java @@ -306,6 +306,25 @@ public class IssueIndexTest { assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(view1))); } + @Test + public void do_not_return_issues_from_project_branch_when_filtering_by_portfolios() { + ComponentDto portfolio = db.components().insertPrivateApplication(db.getDefaultOrganization()); + ComponentDto project = db.components().insertMainBranch(); + ComponentDto projectBranch = db.components().insertProjectBranch(project); + ComponentDto fileOnProjectBranch = db.components().insertComponent(newFileDto(projectBranch)); + indexView(portfolio.uuid(), singletonList(project.uuid())); + + IssueDoc issueOnProject = newDoc(project); + IssueDoc issueOnProjectBranch = newDoc(projectBranch); + IssueDoc issueOnFileOnProjectBranch = newDoc(fileOnProjectBranch); + indexIssues(issueOnProject, issueOnFileOnProjectBranch, issueOnProjectBranch); + + assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(portfolio.uuid())), issueOnProject.key()); + assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(portfolio.uuid())).projectUuids(singletonList(project.uuid())), + issueOnProject.key()); + assertThatSearchReturnsEmpty(IssueQuery.builder().viewUuids(singletonList(portfolio.uuid())).projectUuids(singletonList(projectBranch.uuid()))); + } + @Test public void filter_one_issue_by_project_and_branch() { ComponentDto project = db.components().insertPrivateProject(); @@ -379,20 +398,19 @@ public class IssueIndexTest { } @Test - public void filter_by_application() { + public void filter_by_main_application() { ComponentDto application1 = db.components().insertPrivateApplication(db.getDefaultOrganization()); ComponentDto application2 = db.components().insertPrivateApplication(db.getDefaultOrganization()); ComponentDto project1 = db.components().insertPrivateProject(); ComponentDto file = db.components().insertComponent(newFileDto(project1)); ComponentDto project2 = db.components().insertPrivateProject(); + indexView(application1.uuid(), singletonList(project1.uuid())); + indexView(application2.uuid(), singletonList(project2.uuid())); IssueDoc issueOnProject1 = newDoc(project1); IssueDoc issueOnFile = newDoc(file); IssueDoc issueOnProject2 = newDoc(project2); - indexIssues(issueOnProject1, issueOnFile, issueOnProject2); - indexView(application1.uuid(), singletonList(project1.uuid())); - indexView(application2.uuid(), singletonList(project2.uuid())); assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(application1.uuid())), issueOnProject1.key(), issueOnFile.key()); assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(application2.uuid())), issueOnProject2.key()); @@ -404,24 +422,23 @@ public class IssueIndexTest { } @Test - public void filter_by_application_and_branch() { + public void filter_by_application_branch() { ComponentDto application = db.components().insertMainBranch(c -> c.setQualifier(APP)); ComponentDto branch1 = db.components().insertProjectBranch(application); ComponentDto branch2 = db.components().insertProjectBranch(application); ComponentDto project1 = db.components().insertPrivateProject(); ComponentDto file = db.components().insertComponent(newFileDto(project1)); ComponentDto project2 = db.components().insertPrivateProject(); + indexView(branch1.uuid(), singletonList(project1.uuid())); + indexView(branch2.uuid(), singletonList(project2.uuid())); IssueDoc issueOnProject1 = newDoc(project1); IssueDoc issueOnFile = newDoc(file); IssueDoc issueOnProject2 = newDoc(project2); indexIssues(issueOnProject1, issueOnFile, issueOnProject2); - indexView(branch1.uuid(), singletonList(project1.uuid())); - indexView(branch2.uuid(), singletonList(project2.uuid())); - - assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(branch1.uuid())).branchUuid(branch1.uuid()).mainBranch(false), issueOnProject1.key(), - issueOnFile.key()); + assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(branch1.uuid())).branchUuid(branch1.uuid()).mainBranch(false), + issueOnProject1.key(), issueOnFile.key()); assertThatSearchReturnsOnly( IssueQuery.builder().viewUuids(singletonList(branch1.uuid())).projectUuids(singletonList(project1.uuid())).branchUuid(branch1.uuid()).mainBranch(false), issueOnProject1.key(), issueOnFile.key()); @@ -430,6 +447,39 @@ public class IssueIndexTest { assertThatSearchReturnsEmpty(IssueQuery.builder().branchUuid("unknown")); } + @Test + public void filter_by_application_branch_having_project_branches() { + ComponentDto application = db.components().insertMainBranch(c -> c.setQualifier(APP).setDbKey("app")); + ComponentDto applicationBranch1 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch1")); + ComponentDto applicationBranch2 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch2")); + ComponentDto project1 = db.components().insertPrivateProject(p -> p.setDbKey("prj1")); + ComponentDto project1Branch1 = db.components().insertProjectBranch(project1); + ComponentDto fileOnProject1Branch1 = db.components().insertComponent(newFileDto(project1Branch1)); + ComponentDto project1Branch2 = db.components().insertProjectBranch(project1); + ComponentDto project2 = db.components().insertPrivateProject(p -> p.setDbKey("prj2")); + indexView(applicationBranch1.uuid(), asList(project1Branch1.uuid(), project2.uuid())); + indexView(applicationBranch2.uuid(), singletonList(project1Branch2.uuid())); + + IssueDoc issueOnProject1 = newDoc(project1); + IssueDoc issueOnProject1Branch1 = newDoc(project1Branch1); + IssueDoc issueOnFileOnProject1Branch1 = newDoc(fileOnProject1Branch1); + IssueDoc issueOnProject1Branch2 = newDoc(project1Branch2); + IssueDoc issueOnProject2 = newDoc(project2); + indexIssues(issueOnProject1, issueOnProject1Branch1, issueOnFileOnProject1Branch1, issueOnProject1Branch2, issueOnProject2); + + assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(applicationBranch1.uuid())).branchUuid(applicationBranch1.uuid()).mainBranch(false), + issueOnProject1Branch1.key(), issueOnFileOnProject1Branch1.key(), issueOnProject2.key()); + assertThatSearchReturnsOnly( + IssueQuery.builder().viewUuids(singletonList(applicationBranch1.uuid())).projectUuids(singletonList(project1.uuid())).branchUuid(applicationBranch1.uuid()).mainBranch(false), + issueOnProject1Branch1.key(), issueOnFileOnProject1Branch1.key()); + assertThatSearchReturnsOnly( + IssueQuery.builder().viewUuids(singletonList(applicationBranch1.uuid())).fileUuids(singletonList(fileOnProject1Branch1.uuid())).branchUuid(applicationBranch1.uuid()) + .mainBranch(false), + issueOnFileOnProject1Branch1.key()); + assertThatSearchReturnsEmpty( + IssueQuery.builder().viewUuids(singletonList(applicationBranch1.uuid())).projectUuids(singletonList("unknown")).branchUuid(applicationBranch1.uuid()).mainBranch(false)); + } + @Test public void filter_by_created_after_by_projects() { Date now = new Date(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java index d5298d24369..2a601ec3767 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java @@ -78,6 +78,7 @@ import static org.sonar.db.issue.IssueTesting.newIssue; import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BRANCH; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECT_KEYS; +import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECT_UUIDS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PULL_REQUEST; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SINCE_LEAK_PERIOD; @@ -688,26 +689,49 @@ public class SearchActionComponentsTest { @Test public void search_by_application_key_and_branch() { - ComponentDto application = db.components().insertMainBranch(c -> c.setQualifier(APP)); - ComponentDto applicationBranch = db.components().insertProjectBranch(application); - ComponentDto project1 = db.components().insertPrivateProject(); - ComponentDto project2 = db.components().insertPrivateProject(); - db.components().insertComponents(newProjectCopy(project1, applicationBranch)); - db.components().insertComponents(newProjectCopy(project2, applicationBranch)); + ComponentDto application = db.components().insertMainBranch(c -> c.setQualifier(APP).setDbKey("app")); + ComponentDto applicationBranch1 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch1")); + ComponentDto applicationBranch2 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch2")); + ComponentDto project1 = db.components().insertPrivateProject(p -> p.setDbKey("prj1")); + ComponentDto project1Branch1 = db.components().insertProjectBranch(project1); + ComponentDto fileOnProject1Branch1 = db.components().insertComponent(newFileDto(project1Branch1)); + ComponentDto project1Branch2 = db.components().insertProjectBranch(project1); + ComponentDto project2 = db.components().insertPrivateProject(p -> p.setDbKey("prj2")); + db.components().insertComponents(newProjectCopy(project1Branch1, applicationBranch1)); + db.components().insertComponents(newProjectCopy(project2, applicationBranch1)); + db.components().insertComponents(newProjectCopy(project1Branch2, applicationBranch2)); + RuleDefinitionDto rule = db.rules().insert(); - IssueDto issue1 = db.issues().insert(rule, project1, project1); - IssueDto issue2 = db.issues().insert(rule, project2, project2); + IssueDto issueOnProject1 = db.issues().insert(rule, project1, project1); + IssueDto issueOnProject1Branch1 = db.issues().insert(rule, project1Branch1, project1Branch1); + IssueDto issueOnFileOnProject1Branch1 = db.issues().insert(rule, project1Branch1, fileOnProject1Branch1); + IssueDto issueOnProject1Branch2 = db.issues().insert(rule, project1Branch2, project1Branch2); + IssueDto issueOnProject2 = db.issues().insert(rule, project2, project2); allowAnyoneOnProjects(project1, project2, application); userSession.addProjectPermission(USER, application); indexIssuesAndViews(); - SearchWsResponse result = ws.newRequest() - .setParam(PARAM_COMPONENT_KEYS, applicationBranch.getKey()) - .setParam(PARAM_BRANCH, applicationBranch.getBranch()) - .executeProtobuf(SearchWsResponse.class); - - assertThat(result.getIssuesList()).extracting(Issue::getKey) - .containsExactlyInAnyOrder(issue1.getKey(), issue2.getKey()); + // All issues on applicationBranch1 + assertThat(ws.newRequest() + .setParam(PARAM_COMPONENT_KEYS, applicationBranch1.getKey()) + .setParam(PARAM_BRANCH, applicationBranch1.getBranch()) + .executeProtobuf(SearchWsResponse.class).getIssuesList()) + .extracting(Issue::getKey, Issue::getComponent, Issue::getProject, Issue::getBranch, Issue::hasBranch) + .containsExactlyInAnyOrder( + tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true), + tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true), + tuple(issueOnProject2.getKey(), project2.getKey(), project2.getKey(), "", false)); + + // Issues on project1Branch1 + assertThat(ws.newRequest() + .setParam(PARAM_COMPONENT_KEYS, applicationBranch1.getKey()) + .setParam(PARAM_PROJECT_UUIDS, project1.uuid()) + .setParam(PARAM_BRANCH, applicationBranch1.getBranch()) + .executeProtobuf(SearchWsResponse.class).getIssuesList()) + .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch) + .containsExactlyInAnyOrder( + tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch()), + tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getBranch())); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java index 424c2607084..49af088982e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java @@ -33,7 +33,6 @@ import org.sonar.core.util.stream.MoreCollectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; -import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ResourceTypesRule; import org.sonar.db.component.SnapshotDto; @@ -49,7 +48,6 @@ import org.sonar.server.i18n.I18nRule; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsActionTester; import org.sonarqube.ws.Common; -import org.sonarqube.ws.Measures; import org.sonarqube.ws.Measures.ComponentTreeWsResponse; import org.sonarqube.ws.Measures.PeriodValue; @@ -63,6 +61,7 @@ import static org.sonar.api.measures.Metric.ValueType.DISTRIB; import static org.sonar.api.measures.Metric.ValueType.FLOAT; import static org.sonar.api.measures.Metric.ValueType.INT; 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; @@ -94,6 +93,8 @@ import static org.sonar.server.measure.ws.ComponentTreeAction.METRIC_SORT; import static org.sonar.server.measure.ws.ComponentTreeAction.NAME_SORT; import static org.sonar.server.measure.ws.ComponentTreeAction.WITH_MEASURES_ONLY_METRIC_SORT_FILTER; import static org.sonar.test.JsonAssert.assertJson; +import static org.sonarqube.ws.Measures.Component; +import static org.sonarqube.ws.Measures.Measure; public class ComponentTreeActionTest { @Rule @@ -107,7 +108,6 @@ public class ComponentTreeActionTest { private ResourceTypesRule resourceTypes = new ResourceTypesRule() .setRootQualifiers(PROJECT) .setLeavesQualifiers(FILE, UNIT_TEST_FILE); - private ComponentDbTester componentDb = new ComponentDbTester(db); private DbClient dbClient = db.getDbClient(); private DbSession dbSession = db.getSession(); @@ -123,21 +123,21 @@ public class ComponentTreeActionTest { SnapshotDto analysis = db.components().insertSnapshot(project, s -> s.setPeriodDate(parseDateTime("2016-01-11T10:49:50+0100").getTime()) .setPeriodMode("previous_version") .setPeriodParam("1.0-SNAPSHOT")); - ComponentDto file1 = componentDb.insertComponent(newFileDto(project, null) + ComponentDto file1 = db.components().insertComponent(newFileDto(project, null) .setUuid("AVIwDXE-bJbJqrw6wFv5") .setDbKey("com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl/ElementImpl.java") .setName("ElementImpl.java") .setLanguage("java") .setQualifier(FILE) .setPath("src/main/java/com/sonarsource/markdown/impl/ElementImpl.java")); - ComponentDto file2 = componentDb.insertComponent(newFileDto(project, null) + ComponentDto file2 = db.components().insertComponent(newFileDto(project, null) .setUuid("AVIwDXE_bJbJqrw6wFwJ") .setDbKey("com.sonarsource:java-markdown:src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java") .setName("ElementImplTest.java") .setLanguage("java") .setQualifier(UNIT_TEST_FILE) .setPath("src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java")); - ComponentDto dir = componentDb.insertComponent(newDirectory(project, "src/main/java/com/sonarsource/markdown/impl") + ComponentDto dir = db.components().insertComponent(newDirectory(project, "src/main/java/com/sonarsource/markdown/impl") .setUuid("AVIwDXE-bJbJqrw6wFv8") .setDbKey("com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl") .setQualifier(DIRECTORY)); @@ -194,9 +194,9 @@ public class ComponentTreeActionTest { .setPeriodDate(System.currentTimeMillis())); userSession.anonymous().addProjectPermission(UserRole.USER, project); ComponentDto directory = newDirectory(project, "directory-uuid", "path/to/directory").setName("directory-1"); - componentDb.insertComponent(directory); + db.components().insertComponent(directory); ComponentDto file = newFileDto(directory, null, "file-uuid").setName("file-1"); - componentDb.insertComponent(file); + db.components().insertComponent(file); MetricDto ncloc = insertNclocMetric(); MetricDto coverage = insertCoverageMetric(); db.commit(); @@ -212,7 +212,7 @@ public class ComponentTreeActionTest { assertThat(response.getComponentsList().get(0).getMeasuresList()).extracting("metric").containsOnly("coverage"); // file measures - List fileMeasures = response.getComponentsList().get(1).getMeasuresList(); + List fileMeasures = response.getComponentsList().get(1).getMeasuresList(); assertThat(fileMeasures).extracting("metric").containsOnly("ncloc", "coverage"); assertThat(fileMeasures).extracting("value").containsOnly("5", "15.5"); assertThat(response.getPeriods().getPeriodsList()).extracting("mode").containsOnly("last_version"); @@ -224,9 +224,9 @@ public class ComponentTreeActionTest { SnapshotDto projectSnapshot = db.components().insertSnapshot(project); userSession.anonymous().addProjectPermission(UserRole.USER, project); ComponentDto directory = newDirectory(project, "directory-uuid", "path/to/directory").setName("directory-1"); - componentDb.insertComponent(directory); + db.components().insertComponent(directory); ComponentDto file = newFileDto(directory, null, "file-uuid").setName("file-1"); - componentDb.insertComponent(file); + db.components().insertComponent(file); MetricDto coverage = insertCoverageMetric(); dbClient.metricDao().insert(dbSession, MetricTesting.newMetricDto() .setKey("ncloc") @@ -252,9 +252,9 @@ public class ComponentTreeActionTest { // directory measures assertThat(response.getComponentsList().get(0).getMeasuresList()).extracting("metric").containsOnly("coverage"); // file measures - List fileMeasures = response.getComponentsList().get(1).getMeasuresList(); + List fileMeasures = response.getComponentsList().get(1).getMeasuresList(); assertThat(fileMeasures) - .extracting(Measures.Measure::getMetric, Measures.Measure::getValue, Measures.Measure::getBestValue, Measures.Measure::hasBestValue) + .extracting(Measure::getMetric, Measure::getValue, Measure::getBestValue, Measure::hasBestValue) .containsExactlyInAnyOrder(tuple("ncloc", "100", true, true), tuple("coverage", "15.5", false, false), tuple("new_violations", "", false, false)); @@ -294,9 +294,9 @@ public class ComponentTreeActionTest { .executeProtobuf(ComponentTreeWsResponse.class); // file measures - List fileMeasures = response.getComponentsList().get(0).getMeasuresList(); + List fileMeasures = response.getComponentsList().get(0).getMeasuresList(); assertThat(fileMeasures) - .extracting(Measures.Measure::getMetric, m -> m.getPeriods().getPeriodsValueList()) + .extracting(Measure::getMetric, m -> m.getPeriods().getPeriodsValueList()) .containsExactlyInAnyOrder( tuple(matchingBestValue.getKey(), singletonList(PeriodValue.newBuilder().setIndex(1).setValue("100").setBestValue(true).build())), tuple(doesNotMatchBestValue.getKey(), singletonList(PeriodValue.newBuilder().setIndex(1).setValue("10").setBestValue(false).build())), @@ -312,9 +312,9 @@ public class ComponentTreeActionTest { .setPeriodMode("previous_version") .setPeriodParam("1.0-SNAPSHOT")); ComponentDto directory = newDirectory(project, "directory-uuid", "path/to/directory").setName("directory-1"); - componentDb.insertComponent(directory); + db.components().insertComponent(directory); ComponentDto file = newFileDto(directory, null, "file-uuid").setName("file-1"); - componentDb.insertComponent(file); + db.components().insertComponent(file); MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDto() .setKey(NEW_SECURITY_RATING_KEY) .setOptimizedBestValue(true) @@ -339,15 +339,15 @@ public class ComponentTreeActionTest { public void load_measures_multi_sort_with_metric_key_and_paginated() { ComponentDto project = db.components().insertPrivateProject(); SnapshotDto projectSnapshot = db.components().insertSnapshot(project); - ComponentDto file9 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-9").setName("file-1")); - ComponentDto file8 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-8").setName("file-1")); - ComponentDto file7 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-7").setName("file-1")); - ComponentDto file6 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-6").setName("file-1")); - ComponentDto file5 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-5").setName("file-1")); - ComponentDto file4 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-4").setName("file-1")); - ComponentDto file3 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-3").setName("file-1")); - ComponentDto file2 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-2").setName("file-1")); - ComponentDto file1 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-1").setName("file-1")); + ComponentDto file9 = db.components().insertComponent(newFileDto(project, null, "file-uuid-9").setName("file-1")); + ComponentDto file8 = db.components().insertComponent(newFileDto(project, null, "file-uuid-8").setName("file-1")); + ComponentDto file7 = db.components().insertComponent(newFileDto(project, null, "file-uuid-7").setName("file-1")); + ComponentDto file6 = db.components().insertComponent(newFileDto(project, null, "file-uuid-6").setName("file-1")); + ComponentDto file5 = db.components().insertComponent(newFileDto(project, null, "file-uuid-5").setName("file-1")); + ComponentDto file4 = db.components().insertComponent(newFileDto(project, null, "file-uuid-4").setName("file-1")); + ComponentDto file3 = db.components().insertComponent(newFileDto(project, null, "file-uuid-3").setName("file-1")); + ComponentDto file2 = db.components().insertComponent(newFileDto(project, null, "file-uuid-2").setName("file-1")); + ComponentDto file1 = db.components().insertComponent(newFileDto(project, null, "file-uuid-1").setName("file-1")); MetricDto coverage = insertCoverageMetric(); db.commit(); db.measures().insertLiveMeasure(file1, coverage, m -> m.setValue(1.0d)); @@ -381,10 +381,10 @@ public class ComponentTreeActionTest { public void sort_by_metric_value() { ComponentDto project = db.components().insertPrivateProject(); SnapshotDto projectSnapshot = db.components().insertSnapshot(project); - ComponentDto file4 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-4")); - ComponentDto file3 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-3")); - ComponentDto file1 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-1")); - ComponentDto file2 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-2")); + ComponentDto file4 = db.components().insertComponent(newFileDto(project, null, "file-uuid-4")); + ComponentDto file3 = db.components().insertComponent(newFileDto(project, null, "file-uuid-3")); + ComponentDto file1 = db.components().insertComponent(newFileDto(project, null, "file-uuid-1")); + ComponentDto file2 = db.components().insertComponent(newFileDto(project, null, "file-uuid-2")); MetricDto ncloc = newMetricDto().setKey("ncloc").setValueType(INT.name()).setDirection(1); dbClient.metricDao().insert(dbSession, ncloc); db.commit(); @@ -411,10 +411,10 @@ public class ComponentTreeActionTest { ComponentDto file2 = newFileDto(project, null, "file-uuid-2"); ComponentDto file3 = newFileDto(project, null, "file-uuid-3"); ComponentDto file4 = newFileDto(project, null, "file-uuid-4"); - componentDb.insertComponent(file1); - componentDb.insertComponent(file2); - componentDb.insertComponent(file3); - componentDb.insertComponent(file4); + db.components().insertComponent(file1); + db.components().insertComponent(file2); + db.components().insertComponent(file3); + db.components().insertComponent(file4); MetricDto ncloc = newMetricDto().setKey("ncloc").setValueType(INT.name()).setDirection(1); dbClient.metricDao().insert(dbSession, ncloc); db.measures().insertLiveMeasure(file1, ncloc, m -> m.setData((String) null).setValue(1.0d).setVariation(null)); @@ -442,9 +442,9 @@ public class ComponentTreeActionTest { public void sort_by_metric_period() { ComponentDto project = db.components().insertPrivateProject(); SnapshotDto projectSnapshot = db.components().insertSnapshot(project); - ComponentDto file3 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-3")); - ComponentDto file1 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-1")); - ComponentDto file2 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-2")); + ComponentDto file3 = db.components().insertComponent(newFileDto(project, null, "file-uuid-3")); + ComponentDto file1 = db.components().insertComponent(newFileDto(project, null, "file-uuid-1")); + ComponentDto file2 = db.components().insertComponent(newFileDto(project, null, "file-uuid-2")); MetricDto ncloc = newMetricDto().setKey("ncloc").setValueType(INT.name()).setDirection(1); dbClient.metricDao().insert(dbSession, ncloc); db.commit(); @@ -467,10 +467,10 @@ public class ComponentTreeActionTest { public void remove_components_without_measure_on_the_metric_period_sort() { ComponentDto project = db.components().insertPrivateProject(); SnapshotDto projectSnapshot = db.components().insertSnapshot(project); - ComponentDto file4 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-4")); - ComponentDto file3 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-3")); - ComponentDto file2 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-2")); - ComponentDto file1 = componentDb.insertComponent(newFileDto(project, null, "file-uuid-1")); + ComponentDto file4 = db.components().insertComponent(newFileDto(project, null, "file-uuid-4")); + ComponentDto file3 = db.components().insertComponent(newFileDto(project, null, "file-uuid-3")); + ComponentDto file2 = db.components().insertComponent(newFileDto(project, null, "file-uuid-2")); + ComponentDto file1 = db.components().insertComponent(newFileDto(project, null, "file-uuid-1")); MetricDto ncloc = newMetricDto().setKey("new_ncloc").setValueType(INT.name()).setDirection(1); dbClient.metricDao().insert(dbSession, ncloc); db.measures().insertLiveMeasure(file1, ncloc, m -> m.setData((String) null).setValue(null).setVariation(1.0d)); @@ -499,7 +499,7 @@ public class ComponentTreeActionTest { resourceTypes.setLeavesQualifiers(); ComponentDto project = db.components().insertPrivateProject(); db.components().insertSnapshot(project); - componentDb.insertComponent(newFileDto(project, null)); + db.components().insertComponent(newFileDto(project, null)); insertNclocMetric(); ComponentTreeWsResponse result = ws.newRequest() @@ -526,12 +526,12 @@ public class ComponentTreeActionTest { .setParam(PARAM_COMPONENT, file.getKey()) .setParam(PARAM_BRANCH, file.getBranch()) .setParam(PARAM_METRIC_KEYS, complexity.getKey()) - .executeProtobuf(Measures.ComponentTreeWsResponse.class); + .executeProtobuf(ComponentTreeWsResponse.class); - assertThat(response.getBaseComponent()).extracting(Measures.Component::getKey, Measures.Component::getBranch) + assertThat(response.getBaseComponent()).extracting(Component::getKey, Component::getBranch) .containsExactlyInAnyOrder(file.getKey(), file.getBranch()); assertThat(response.getBaseComponent().getMeasuresList()) - .extracting(Measures.Measure::getMetric, m -> parseDouble(m.getValue())) + .extracting(Measure::getMetric, m -> parseDouble(m.getValue())) .containsExactlyInAnyOrder(tuple(complexity.getKey(), measure.getValue())); } @@ -549,12 +549,12 @@ public class ComponentTreeActionTest { .setParam(PARAM_COMPONENT, file.getKey()) .setParam(PARAM_PULL_REQUEST, "pr-123") .setParam(PARAM_METRIC_KEYS, complexity.getKey()) - .executeProtobuf(Measures.ComponentTreeWsResponse.class); + .executeProtobuf(ComponentTreeWsResponse.class); - assertThat(response.getBaseComponent()).extracting(Measures.Component::getKey, Measures.Component::getPullRequest) + assertThat(response.getBaseComponent()).extracting(Component::getKey, Component::getPullRequest) .containsExactlyInAnyOrder(file.getKey(), "pr-123"); assertThat(response.getBaseComponent().getMeasuresList()) - .extracting(Measures.Measure::getMetric, m -> parseDouble(m.getValue())) + .extracting(Measure::getMetric, m -> parseDouble(m.getValue())) .containsExactlyInAnyOrder(tuple(complexity.getKey(), measure.getValue())); } @@ -562,7 +562,7 @@ public class ComponentTreeActionTest { public void return_deprecated_id_in_the_response() { ComponentDto project = db.components().insertPrivateProject(); SnapshotDto analysis = db.components().insertSnapshot(project); - ComponentDto file = componentDb.insertComponent(newFileDto(project)); + ComponentDto file = db.components().insertComponent(newFileDto(project)); MetricDto ncloc = insertNclocMetric(); db.measures().insertLiveMeasure(file, ncloc, m -> m.setValue(2d)); @@ -572,7 +572,7 @@ public class ComponentTreeActionTest { .executeProtobuf(ComponentTreeWsResponse.class); assertThat(response.getBaseComponent().getId()).isEqualTo(project.uuid()); - assertThat(response.getComponentsList()).extracting(Measures.Component::getId) + assertThat(response.getComponentsList()).extracting(Component::getId) .containsExactlyInAnyOrder(file.uuid()); } @@ -626,7 +626,7 @@ public class ComponentTreeActionTest { } @Test - public void reference_component() { + public void project_reference_from_portfolio() { ComponentDto project = db.components().insertPrivateProject(); ComponentDto view = db.components().insertPrivatePortfolio(db.getDefaultOrganization()); SnapshotDto viewAnalysis = db.components().insertSnapshot(view); @@ -640,10 +640,37 @@ public class ComponentTreeActionTest { .executeProtobuf(ComponentTreeWsResponse.class); assertThat(result.getComponentsList()) - .extracting(Measures.Component::getKey, Measures.Component::getRefId, Measures.Component::getRefKey) + .extracting(Component::getKey, Component::getRefId, Component::getRefKey) .containsExactlyInAnyOrder(tuple(projectCopy.getKey(), project.uuid(), project.getKey())); } + @Test + public void project_branch_reference_from_application_branch() { + MetricDto ncloc = insertNclocMetric(); + ComponentDto application = db.components().insertMainBranch(c -> c.setQualifier(APP).setDbKey("app-key")); + ComponentDto applicationBranch = db.components().insertProjectBranch(application, a -> a.setKey("app-branch")); + ComponentDto project = db.components().insertPrivateProject(p -> p.setDbKey("project-key")); + ComponentDto projectBranch = db.components().insertProjectBranch(project, b -> b.setKey("project-branch")); + ComponentDto techProjectBranch = db.components().insertComponent(newProjectCopy(projectBranch, applicationBranch) + .setDbKey(applicationBranch.getKey() + applicationBranch.getBranch() + projectBranch.getDbKey())); + SnapshotDto applicationBranchAnalysis = db.components().insertSnapshot(applicationBranch); + db.measures().insertLiveMeasure(applicationBranch, ncloc, m -> m.setValue(5d)); + db.measures().insertLiveMeasure(techProjectBranch, ncloc, m -> m.setValue(1d)); + + ComponentTreeWsResponse result = ws.newRequest() + .setParam(PARAM_COMPONENT, applicationBranch.getKey()) + .setParam(PARAM_BRANCH, applicationBranch.getBranch()) + .setParam(PARAM_METRIC_KEYS, ncloc.getKey()) + .executeProtobuf(ComponentTreeWsResponse.class); + + assertThat(result.getBaseComponent()) + .extracting(Component::getKey, Component::getBranch) + .containsExactlyInAnyOrder(applicationBranch.getKey(), applicationBranch.getBranch()); + assertThat(result.getComponentsList()) + .extracting(Component::getKey, Component::getBranch, Component::getRefId, Component::getRefKey) + .containsExactlyInAnyOrder(tuple(techProjectBranch.getKey(), projectBranch.getBranch(), projectBranch.uuid(), project.getKey())); + } + @Test public void fail_when_metric_keys_parameter_is_empty() { ComponentDto project = db.components().insertPrivateProject(); @@ -854,7 +881,7 @@ public class ComponentTreeActionTest { public void fail_when_component_is_removed() { ComponentDto project = db.components().insertPrivateProject(); db.components().insertSnapshot(project); - ComponentDto file = componentDb.insertComponent(newFileDto(project).setDbKey("file-key").setEnabled(false)); + ComponentDto file = db.components().insertComponent(newFileDto(project).setDbKey("file-key").setEnabled(false)); userSession.anonymous().addProjectPermission(UserRole.USER, project); insertNclocMetric(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java index 933e9a3ddc1..c1bf5acf7fa 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/project/ProjectLifeCycleListenersImplTest.java @@ -128,6 +128,82 @@ public class ProjectLifeCycleListenersImplTest { inOrder.verifyNoMoreInteractions(); } + @Test + public void onProjectBranchesDeleted_throws_NPE_if_set_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("projects can't be null"); + + underTestWithListeners.onProjectBranchesDeleted(null); + } + + @Test + public void onProjectBranchesDeleted_throws_NPE_if_set_is_null_even_if_no_listeners() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("projects can't be null"); + + underTestNoListeners.onProjectBranchesDeleted(null); + } + + @Test + public void onProjectBranchesDeleted_has_no_effect_if_set_is_empty() { + underTestNoListeners.onProjectBranchesDeleted(Collections.emptySet()); + + underTestWithListeners.onProjectBranchesDeleted(Collections.emptySet()); + verifyZeroInteractions(listener1, listener2, listener3); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectBranchesDeleted_does_not_fail_if_there_is_no_listener(Set projects) { + underTestNoListeners.onProjectBranchesDeleted(projects); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectBranchesDeleted_calls_all_listeners_in_order_of_addition_to_constructor(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + + underTestWithListeners.onProjectBranchesDeleted(projects); + + inOrder.verify(listener1).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener2).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener3).onProjectBranchesDeleted(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectBranchesDeleted_calls_all_listeners_even_if_one_throws_an_Exception(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + doThrow(new RuntimeException("Faking listener2 throwing an exception")) + .when(listener2) + .onProjectBranchesDeleted(any()); + + underTestWithListeners.onProjectBranchesDeleted(projects); + + inOrder.verify(listener1).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener2).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener3).onProjectBranchesDeleted(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @Test + @UseDataProvider("oneOrManyProjects") + public void onProjectBranchesDeleted_calls_all_listeners_even_if_one_throws_an_Error(Set projects) { + InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); + doThrow(new Error("Faking listener2 throwing an Error")) + .when(listener2) + .onProjectBranchesDeleted(any()); + + underTestWithListeners.onProjectBranchesDeleted(projects); + + inOrder.verify(listener1).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener2).onProjectBranchesDeleted(same(projects)); + inOrder.verify(listener3).onProjectBranchesDeleted(same(projects)); + inOrder.verifyNoMoreInteractions(); + } + + @DataProvider public static Object[][] oneOrManyProjects() { return new Object[][] { diff --git a/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java index 4b5b12b437d..a36042baf76 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/view/index/ViewIndexerTest.java @@ -56,6 +56,8 @@ import static com.google.common.collect.Lists.newArrayList; import static java.util.Arrays.asList; import static java.util.Collections.emptySet; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static org.sonar.api.resources.Qualifiers.APP; import static org.sonar.db.component.ComponentTesting.newProjectCopy; import static org.sonar.server.view.index.ViewIndexDefinition.INDEX_TYPE_VIEW; @@ -65,18 +67,15 @@ public class ViewIndexerTest { @Rule public TestRule safeguardTimeout = new DisableOnDebug(Timeout.seconds(60)); - @Rule - public DbTester dbTester = DbTester.create(system2); - + public DbTester db = DbTester.create(); @Rule public EsTester es = EsTester.create(); - @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone(); - private DbClient dbClient = dbTester.getDbClient(); - private DbSession dbSession = dbTester.getSession(); + private DbClient dbClient = db.getDbClient(); + private DbSession dbSession = db.getSession(); private IssueIndexer issueIndexer = new IssueIndexer(es.client(), dbClient, new IssueIteratorFactory(dbClient)); private PermissionIndexer permissionIndexer = new PermissionIndexer(dbClient, es.client(), issueIndexer); private ViewIndexer underTest = new ViewIndexer(dbClient, es.client()); @@ -89,7 +88,7 @@ public class ViewIndexerTest { @Test public void index_on_startup() { - dbTester.prepareDbUnit(getClass(), "index.xml"); + db.prepareDbUnit(getClass(), "index.xml"); underTest.indexOnStartup(emptySet()); @@ -106,7 +105,7 @@ public class ViewIndexerTest { @Test public void index_root_view() { - dbTester.prepareDbUnit(getClass(), "index.xml"); + db.prepareDbUnit(getClass(), "index.xml"); underTest.index("EFGH"); @@ -133,9 +132,9 @@ public class ViewIndexerTest { @Test public void index_application() { - ComponentDto application = dbTester.components().insertApplication(dbTester.getDefaultOrganization()); - ComponentDto project = dbTester.components().insertPrivateProject(); - dbTester.components().insertComponent(newProjectCopy("PC1", project, application)); + ComponentDto application = db.components().insertApplication(db.getDefaultOrganization()); + ComponentDto project = db.components().insertPrivateProject(); + db.components().insertComponent(newProjectCopy("PC1", project, application)); underTest.index(application.uuid()); List result = es.getDocuments(ViewIndexDefinition.INDEX_TYPE_VIEW, ViewDoc.class); @@ -148,9 +147,9 @@ public class ViewIndexerTest { @Test public void index_application_on_startup() { - ComponentDto application = dbTester.components().insertApplication(dbTester.getDefaultOrganization()); - ComponentDto project = dbTester.components().insertPrivateProject(); - dbTester.components().insertComponent(newProjectCopy("PC1", project, application)); + ComponentDto application = db.components().insertApplication(db.getDefaultOrganization()); + ComponentDto project = db.components().insertPrivateProject(); + db.components().insertComponent(newProjectCopy("PC1", project, application)); underTest.indexOnStartup(emptySet()); List result = es.getDocuments(ViewIndexDefinition.INDEX_TYPE_VIEW, ViewDoc.class); @@ -161,6 +160,31 @@ public class ViewIndexerTest { assertThat(resultApp.projects()).containsExactlyInAnyOrder(project.uuid()); } + @Test + public void index_application_branch() { + ComponentDto application = db.components().insertMainBranch(c -> c.setQualifier(APP).setDbKey("app")); + ComponentDto applicationBranch1 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch1")); + ComponentDto applicationBranch2 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch2")); + ComponentDto project1 = db.components().insertPrivateProject(p -> p.setDbKey("prj1")); + ComponentDto project1Branch = db.components().insertProjectBranch(project1); + ComponentDto project2 = db.components().insertPrivateProject(p -> p.setDbKey("prj2")); + ComponentDto project2Branch = db.components().insertProjectBranch(project2); + ComponentDto project3 = db.components().insertPrivateProject(p -> p.setDbKey("prj3")); + ComponentDto project3Branch = db.components().insertProjectBranch(project3); + db.components().insertComponent(newProjectCopy(project1Branch, applicationBranch1)); + db.components().insertComponent(newProjectCopy(project2Branch, applicationBranch1)); + // Technical project of applicationBranch2 should be ignored + db.components().insertComponent(newProjectCopy(project3Branch, applicationBranch2)); + + underTest.index(applicationBranch1.uuid()); + + List result = es.getDocuments(ViewIndexDefinition.INDEX_TYPE_VIEW, ViewDoc.class); + assertThat(result) + .extracting(ViewDoc::uuid, ViewDoc::projects) + .containsExactlyInAnyOrder( + tuple(applicationBranch1.uuid(), asList(project1Branch.uuid(), project2Branch.uuid()))); + } + @Test public void clear_views_lookup_cache_on_index_view_uuid() { IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSessionRule, new AuthorizationTypeSupport(userSessionRule)); @@ -170,11 +194,11 @@ public class ViewIndexerTest { RuleDto rule = RuleTesting.newXooX1(); dbClient.ruleDao().insert(dbSession, rule.getDefinition()); - ComponentDto project1 = addProjectWithIssue(rule, dbTester.organizations().insert()); + ComponentDto project1 = addProjectWithIssue(rule, db.organizations().insert()); issueIndexer.indexOnStartup(issueIndexer.getIndexTypes()); permissionIndexer.indexOnStartup(permissionIndexer.getIndexTypes()); - OrganizationDto organizationDto = dbTester.organizations().insert(); + OrganizationDto organizationDto = db.organizations().insert(); ComponentDto view = ComponentTesting.newView(organizationDto, "ABCD"); ComponentDto techProject1 = newProjectCopy("CDEF", project1, view); dbClient.componentDao().insert(dbSession, view, techProject1); @@ -250,7 +274,7 @@ public class ViewIndexerTest { private ComponentDto addProjectWithIssue(RuleDto rule, OrganizationDto org) { ComponentDto project = ComponentTesting.newPublicProjectDto(org); ComponentDto file = ComponentTesting.newFileDto(project, null); - dbTester.components().insertComponents(project, file); + db.components().insertComponents(project, file); IssueDto issue = IssueTesting.newDto(rule, file, project); dbClient.issueDao().insert(dbSession, issue); diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseRequest.java index 8f76a4f1ecb..c0a308c3578 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseRequest.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseRequest.java @@ -115,7 +115,6 @@ abstract class BaseRequest implements WsRequest { parameters.setValues(key, values.stream() .filter(Objects::nonNull) .map(Object::toString) - .filter(value -> !value.isEmpty()) .collect(Collectors.toList())); return (SELF) this; diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/BaseRequestTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/BaseRequestTest.java index 6c0b67735e8..87e09cfd7e0 100644 --- a/sonar-ws/src/test/java/org/sonarqube/ws/client/BaseRequestTest.java +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/BaseRequestTest.java @@ -29,6 +29,7 @@ import org.junit.rules.ExpectedException; import org.sonarqube.ws.MediaTypes; import static com.google.common.collect.Lists.newArrayList; +import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.data.MapEntry.entry; @@ -79,8 +80,9 @@ public class BaseRequestTest { @Test public void skip_null_value_in_multi_param() { - underTest.setParam("key", newArrayList("v1", null, "v3")); + underTest.setParam("key", newArrayList("v1", null, "", "v3")); + assertMultiValueParameters(entry("key", asList("v1", "", "v3"))); } @Test