diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2018-09-26 08:58:59 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-10-04 20:20:56 +0200 |
commit | 2c540713f9289d8cfd14a65f3b4c3c33a4696e20 (patch) | |
tree | 6f880db9407f37ccaf479cc79a8bf1c777a92b15 /server/sonar-ce-task-projectanalysis | |
parent | e80c0f3d1e5cd459f88b7e0c41a2d9a7519e260f (diff) | |
download | sonarqube-2c540713f9289d8cfd14a65f3b4c3c33a4696e20.tar.gz sonarqube-2c540713f9289d8cfd14a65f3b4c3c33a4696e20.zip |
SONAR-11310 add temporary columns to CE tables
- add main_component_uuid temporary columns to CE_QUEUE
- add main_last_key and main_component_uuid columns to CE_ACTIVITY
- back to initial paradigm in Compute Engine: even for branches/PRs, the row in table PROJECTS a task belongs to is created in api/ce/submit
- add main component concept to CeTask
- improved consistency check when processing a report task to account for row in PROJECTS now being the one of the branche/PR
- stronger validation of characteristics passed to api/ce/submit
- add api/system/migrate_data for SonarCloud online data migration
Diffstat (limited to 'server/sonar-ce-task-projectanalysis')
9 files changed, 214 insertions, 99 deletions
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java index 3c6f89c7c85..fbd3db946d2 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java @@ -148,10 +148,12 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor } private static Project createProject(org.sonar.ce.task.CeTask ceTask) { - return new ProjectImpl( - ceTask.getComponentUuid(), - ceTask.getComponentKey(), - ceTask.getComponentName()); + return ceTask.getMainComponent() + .map(c -> new ProjectImpl( + c.getUuid(), + c.getKey().orElseThrow(() -> new IllegalStateException("Missing project key")), + c.getName().orElseThrow(() -> new IllegalStateException("Missing project name")))) + .orElseThrow(() -> new IllegalStateException("Report processed for a task of a deleted component")); } @CheckForNull diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchLoader.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchLoader.java index 9341e29a09d..e6629463e6c 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchLoader.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchLoader.java @@ -21,10 +21,11 @@ package org.sonar.ce.task.projectanalysis.component; import javax.annotation.Nullable; import org.sonar.api.utils.MessageException; -import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.ce.task.projectanalysis.analysis.MutableAnalysisMetadataHolder; +import org.sonar.scanner.protocol.output.ScannerReport; import static org.apache.commons.lang.StringUtils.trimToNull; +import static org.sonar.scanner.protocol.output.ScannerReport.Metadata.BranchType.UNSET; public class BranchLoader { private final MutableAnalysisMetadataHolder metadataHolder; @@ -47,10 +48,22 @@ public class BranchLoader { throw MessageException.of("Properties sonar.branch and sonar.branch.name can't be set together"); } + if (delegate == null && hasBranchProperties(metadata)) { + throw MessageException.of("Current edition does not support branch feature"); + } + if (delegate != null && deprecatedBranch == null) { delegate.load(metadata); } else { metadataHolder.setBranch(new DefaultBranchImpl(deprecatedBranch)); } } + + private static boolean hasBranchProperties(ScannerReport.Metadata metadata) { + return !metadata.getBranchName().isEmpty() + || !metadata.getPullRequestKey().isEmpty() + || !metadata.getMergeBranchName().isEmpty() + || metadata.getBranchType() != UNSET; + } + } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImpl.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImpl.java index 8af513738c0..6efa7d0d9a1 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImpl.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImpl.java @@ -19,10 +19,7 @@ */ package org.sonar.ce.task.projectanalysis.component; -import java.util.Date; -import java.util.Optional; import javax.annotation.Nullable; -import org.sonar.api.utils.System2; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; import org.sonar.ce.task.projectanalysis.analysis.Branch; import org.sonar.db.DbClient; @@ -32,18 +29,16 @@ import org.sonar.db.component.BranchType; import org.sonar.db.component.ComponentDto; import org.sonar.db.protobuf.DbProjectBranches; -import static org.sonar.db.component.ComponentDto.UUID_PATH_OF_ROOT; -import static org.sonar.db.component.ComponentDto.UUID_PATH_SEPARATOR; - +/** + * Creates or updates the data in table {@code PROJECT_BRANCHES} for the current root. + */ public class BranchPersisterImpl implements BranchPersister { private final DbClient dbClient; - private final System2 system2; private final TreeRootHolder treeRootHolder; private final AnalysisMetadataHolder analysisMetadataHolder; - public BranchPersisterImpl(DbClient dbClient, System2 system2, TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder) { + public BranchPersisterImpl(DbClient dbClient, TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder) { this.dbClient = dbClient; - this.system2 = system2; this.treeRootHolder = treeRootHolder; this.analysisMetadataHolder = analysisMetadataHolder; } @@ -52,32 +47,14 @@ public class BranchPersisterImpl implements BranchPersister { Branch branch = analysisMetadataHolder.getBranch(); String branchUuid = treeRootHolder.getRoot().getUuid(); - Optional<ComponentDto> branchComponentDtoOpt = dbClient.componentDao().selectByUuid(dbSession, branchUuid); - - ComponentDto branchComponentDto; - if (branch.isMain()) { - checkState(branchComponentDtoOpt.isPresent(), "Project has been deleted by end-user during analysis"); - branchComponentDto = branchComponentDtoOpt.get(); - } else { - // inserts new row in table projects if it's the first time branch is analyzed - branchComponentDto = branchComponentDtoOpt.orElseGet(() -> insertIntoProjectsTable(dbSession, branchUuid)); - } + ComponentDto branchComponentDto = dbClient.componentDao().selectByUuid(dbSession, branchUuid) + .orElseThrow(() -> new IllegalStateException("Component has been deleted by end-user during analysis")); // insert or update in table project_branches dbClient.branchDao().upsert(dbSession, toBranchDto(branchComponentDto, branch)); } - private static void checkState(boolean condition, String msg) { - if (!condition) { - throw new IllegalStateException(msg); - } - } - - private static <T> T firstNonNull(@Nullable T first, T second) { - return (first != null) ? first : second; - } - - private BranchDto toBranchDto(ComponentDto componentDto, Branch branch) { + protected BranchDto toBranchDto(ComponentDto componentDto, Branch branch) { BranchDto dto = new BranchDto(); dto.setUuid(componentDto.uuid()); @@ -103,19 +80,8 @@ public class BranchPersisterImpl implements BranchPersister { return dto; } - private ComponentDto insertIntoProjectsTable(DbSession dbSession, String branchUuid) { - String mainBranchProjectUuid = analysisMetadataHolder.getProject().getUuid(); - ComponentDto project = dbClient.componentDao().selectOrFailByUuid(dbSession, mainBranchProjectUuid); - ComponentDto branchDto = project.copy(); - branchDto.setUuid(branchUuid); - branchDto.setProjectUuid(branchUuid); - branchDto.setRootUuid(branchUuid); - branchDto.setUuidPath(UUID_PATH_OF_ROOT); - branchDto.setModuleUuidPath(UUID_PATH_SEPARATOR + branchUuid + UUID_PATH_SEPARATOR); - branchDto.setMainBranchProjectUuid(mainBranchProjectUuid); - branchDto.setDbKey(treeRootHolder.getRoot().getDbKey()); - branchDto.setCreatedAt(new Date(system2.now())); - dbClient.componentDao().insert(dbSession, branchDto); - return branchDto; + private static <T> T firstNonNull(@Nullable T first, T second) { + return (first != null) ? first : second; } + } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCount.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCount.java index 6de4c30557a..80963133fc5 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCount.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCount.java @@ -41,18 +41,19 @@ public class PopulateFileSourceLineCount extends DataChange implements ProjectAn @Override protected void execute(Context context) throws SQLException { + String componentUuid = ceTask.getComponent().get().getUuid(); Long unInitializedFileSources = context.prepareSelect("select count(1) from file_sources where line_count = ? and project_uuid = ?") .setInt(1, LINE_COUNT_NOT_POPULATED) - .setString(2, ceTask.getComponentUuid()) + .setString(2, componentUuid) .get(row -> row.getLong(1)); if (unInitializedFileSources != null && unInitializedFileSources > 0) { MassUpdate massUpdate = context.prepareMassUpdate(); massUpdate.select("select id,line_hashes from file_sources where line_count = ? and project_uuid = ?") .setInt(1, LINE_COUNT_NOT_POPULATED) - .setString(2, ceTask.getComponentUuid()); + .setString(2, componentUuid); massUpdate.update("update file_sources set line_count = ? where id = ?"); - massUpdate.rowPluralName("line counts of sources of project " + ceTask.getComponentUuid()); + massUpdate.rowPluralName("line counts of sources of project " + componentUuid); massUpdate.execute(PopulateFileSourceLineCount::handle); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java index 9a0c3b1592e..99709304ebd 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java @@ -104,30 +104,40 @@ public class LoadReportAnalysisMetadataHolderStep implements ComputationStep { */ private Runnable loadProject(ScannerReport.Metadata reportMetadata, Organization organization) { String reportProjectKey = projectKeyFromReport(reportMetadata); - String componentKey = ceTask.getComponentKey(); - if (componentKey == null) { - throw MessageException.of(format( + CeTask.Component mainComponent = mandatoryComponent(ceTask.getMainComponent()); + String mainComponentKey = mainComponent.getKey() + .orElseThrow(() -> MessageException.of(format( + "Compute Engine task main component key is null. Project with UUID %s must have been deleted since report was uploaded. Can not proceed.", + mainComponent.getUuid()))); + CeTask.Component component = mandatoryComponent(ceTask.getComponent()); + String componentKey = component.getKey() + .orElseThrow(() -> MessageException.of(format( "Compute Engine task component key is null. Project with UUID %s must have been deleted since report was uploaded. Can not proceed.", - ceTask.getComponentUuid())); - } + component.getUuid()))); ComponentDto dto = toProject(reportProjectKey); + analysisMetadata.setProject(Project.from(dto)); return () -> { - if (!componentKey.equals(reportProjectKey)) { + if (!mainComponentKey.equals(reportProjectKey)) { throw MessageException.of(format( "ProjectKey in report (%s) is not consistent with projectKey under which the report has been submitted (%s)", reportProjectKey, - componentKey)); + mainComponentKey)); } if (!dto.getOrganizationUuid().equals(organization.getUuid())) { throw MessageException.of(format("Project is not in the expected organization: %s", organization.getKey())); } - if (dto.getMainBranchProjectUuid() != null) { - throw MessageException.of("Project should not reference a branch"); + if (componentKey.equals(mainComponentKey) && dto.getMainBranchProjectUuid() != null) { + throw MessageException.of("Component should not reference a branch"); } }; } + private static CeTask.Component mandatoryComponent(Optional<CeTask.Component> mainComponent) { + return mainComponent + .orElseThrow(() -> new IllegalStateException("component missing on ce task")); + } + private Organization loadOrganization(ScannerReport.Metadata reportMetadata) { try (DbSession dbSession = dbClient.openSession(false)) { Organization organization = toOrganization(dbSession, ceTask.getOrganizationUuid()); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java index fabd35b9dbc..af0eafd471e 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java @@ -87,13 +87,13 @@ public class PostProjectAnalysisTasksExecutorTest { private String organizationName = organizationUuid + "_name"; private System2 system2 = mock(System2.class); private ArgumentCaptor<PostProjectAnalysisTask.ProjectAnalysis> projectAnalysisArgumentCaptor = ArgumentCaptor.forClass(PostProjectAnalysisTask.ProjectAnalysis.class); + private CeTask.Component component = new CeTask.Component("component uuid", "component key", "component name"); private CeTask ceTask = new CeTask.Builder() .setOrganizationUuid(organizationUuid) .setType("type") .setUuid("uuid") - .setComponentKey("component key") - .setComponentName("component name") - .setComponentUuid("component uuid") + .setComponent(component) + .setMainComponent(component) .build(); private PostProjectAnalysisTask postProjectAnalysisTask = mock(PostProjectAnalysisTask.class); private PostProjectAnalysisTasksExecutor underTest = new PostProjectAnalysisTasksExecutor( @@ -203,9 +203,9 @@ public class PostProjectAnalysisTasksExecutorTest { verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture()); Project project = projectAnalysisArgumentCaptor.getValue().getProject(); - assertThat(project.getUuid()).isEqualTo(ceTask.getComponentUuid()); - assertThat(project.getKey()).isEqualTo(ceTask.getComponentKey()); - assertThat(project.getName()).isEqualTo(ceTask.getComponentName()); + assertThat(project.getUuid()).isEqualTo(ceTask.getComponent().get().getUuid()); + assertThat(project.getKey()).isEqualTo(ceTask.getComponent().get().getKey().get()); + assertThat(project.getName()).isEqualTo(ceTask.getComponent().get().getName().get()); } @Test diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImplTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImplTest.java index 237b7b3efc1..7cfcbd5c116 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImplTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImplTest.java @@ -19,25 +19,36 @@ */ package org.sonar.ce.task.projectanalysis.component; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.util.Optional; +import javax.annotation.Nullable; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; import org.sonar.api.utils.System2; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule; import org.sonar.ce.task.projectanalysis.analysis.Branch; import org.sonar.db.DbTester; +import org.sonar.db.component.BranchDto; import org.sonar.db.component.BranchType; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; +import org.sonar.db.protobuf.DbProjectBranches; import org.sonar.server.project.Project; +import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT; import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder; +import static org.sonar.db.component.BranchType.LONG; +import static org.sonar.db.component.BranchType.PULL_REQUEST; +@RunWith(DataProviderRunner.class) public class BranchPersisterImplTest { private final static Component MAIN = builder(PROJECT, 1).setUuid("PROJECT_UUID").setKey("PROJECT_KEY").build(); private final static Component BRANCH = builder(PROJECT, 1).setUuid("BRANCH_UUID").setKey("BRANCH_KEY").build(); @@ -51,66 +62,133 @@ public class BranchPersisterImplTest { @Rule public ExpectedException exception = ExpectedException.none(); - BranchPersister underTest = new BranchPersisterImpl(dbTester.getDbClient(), System2.INSTANCE, treeRootHolder, analysisMetadataHolder); + BranchPersister underTest = new BranchPersisterImpl(dbTester.getDbClient(), treeRootHolder, analysisMetadataHolder); @Test - public void fail_if_no_component_for_main_branches() { - analysisMetadataHolder.setBranch(createBranch(BranchType.LONG, true, "master")); + public void persist_fails_with_ISE_if_no_component_for_main_branches() { + analysisMetadataHolder.setBranch(createBranch(LONG, true, "master")); treeRootHolder.setRoot(MAIN); - exception.expect(IllegalStateException.class); - exception.expectMessage("Project has been deleted by end-user during analysis"); + expectMissingComponentISE(); + + underTest.persist(dbTester.getSession()); + } + + @Test + public void persist_fails_with_ISE_if_no_component_for_long_branches() { + analysisMetadataHolder.setBranch(createBranch(LONG, false, "foo")); + treeRootHolder.setRoot(BRANCH); + + expectMissingComponentISE(); underTest.persist(dbTester.getSession()); } @Test - public void persist_secondary_branch() { - analysisMetadataHolder.setBranch(createBranch(BranchType.LONG, false, "branch")); + public void persist_fails_with_ISE_if_no_component_for_short_branches() { + analysisMetadataHolder.setBranch(createBranch(BranchType.SHORT, false, "foo")); treeRootHolder.setRoot(BRANCH); - // add main branch in project table and in metadata - ComponentDto dto = ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert(), MAIN.getUuid()).setDbKey(MAIN.getDbKey()); - analysisMetadataHolder.setProject(Project.from(dto)); - dbTester.getDbClient().componentDao().insert(dbTester.getSession(), dto); + expectMissingComponentISE(); + + underTest.persist(dbTester.getSession()); + } + + @Test + public void persist_fails_with_ISE_if_no_component_for_pull_request() { + analysisMetadataHolder.setBranch(createBranch(BranchType.PULL_REQUEST, false, "12")); + treeRootHolder.setRoot(BRANCH); + + expectMissingComponentISE(); + + underTest.persist(dbTester.getSession()); + } + + @Test + @UseDataProvider("nullOrNotNullString") + public void persist_creates_row_in_PROJECTS_BRANCHES_for_long_branch(@Nullable String mergeBranchUuid) { + String branchName = "branch"; + + // add project and branch in table PROJECTS + ComponentDto mainComponent = ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert(), MAIN.getUuid()).setDbKey(MAIN.getKey()); + ComponentDto component = ComponentTesting.newProjectBranch(mainComponent, new BranchDto().setUuid(BRANCH.getUuid()).setKey(BRANCH.getKey()).setBranchType(LONG)); + dbTester.getDbClient().componentDao().insert(dbTester.getSession(), mainComponent, component); + dbTester.commit(); + // set project in metadata + treeRootHolder.setRoot(BRANCH); + analysisMetadataHolder.setBranch(createBranch(LONG, false, branchName, mergeBranchUuid)); + analysisMetadataHolder.setProject(Project.from(mainComponent)); - // this should add new columns in project and project_branches underTest.persist(dbTester.getSession()); dbTester.getSession().commit(); assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(2); - assertThat(dbTester.countRowsOfTable("project_branches")).isEqualTo(1); + Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), BRANCH.getUuid()); + assertThat(branchDto).isPresent(); + assertThat(branchDto.get().getBranchType()).isEqualTo(LONG); + assertThat(branchDto.get().getKey()).isEqualTo(branchName); + assertThat(branchDto.get().getMergeBranchUuid()).isEqualTo(mergeBranchUuid); + assertThat(branchDto.get().getProjectUuid()).isEqualTo(MAIN.getUuid()); + assertThat(branchDto.get().getPullRequestData()).isNull(); + } + + @DataProvider + public static Object[][] nullOrNotNullString() { + return new Object[][] { + {null}, + {randomAlphabetic(12)} + }; } @Test - public void persist_pull_request_data() { + @UseDataProvider("nullOrNotNullString") + public void persist_creates_row_in_PROJECTS_BRANCHES_for_pull_request(@Nullable String mergeBranchUuid) { String pullRequestId = "pr-123"; - analysisMetadataHolder.setBranch(createBranch(BranchType.PULL_REQUEST, false, pullRequestId)); - analysisMetadataHolder.setPullRequestKey(pullRequestId); - treeRootHolder.setRoot(BRANCH); - // add main branch in project table and in metadata - ComponentDto dto = ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert(), MAIN.getUuid()).setDbKey(MAIN.getDbKey()); - analysisMetadataHolder.setProject(Project.from(dto)); - dbTester.getDbClient().componentDao().insert(dbTester.getSession(), dto); + // add project and branch in table PROJECTS + ComponentDto mainComponent = ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert(), MAIN.getUuid()).setDbKey(MAIN.getKey()); + ComponentDto component = ComponentTesting.newProjectBranch(mainComponent, new BranchDto().setUuid(BRANCH.getUuid()).setKey(BRANCH.getKey()).setBranchType(PULL_REQUEST)); + dbTester.getDbClient().componentDao().insert(dbTester.getSession(), mainComponent, component); + dbTester.commit(); + // set project in metadata + treeRootHolder.setRoot(BRANCH); + analysisMetadataHolder.setBranch(createBranch(PULL_REQUEST, false, pullRequestId, mergeBranchUuid)); + analysisMetadataHolder.setProject(Project.from(mainComponent)); + analysisMetadataHolder.setPullRequestKey(pullRequestId); - // this should add new columns in project and project_branches underTest.persist(dbTester.getSession()); dbTester.getSession().commit(); assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(2); - assertThat(dbTester.countRowsOfTable("project_branches")).isEqualTo(1); - assertThat(dbTester.countSql("select count(*) from project_branches where pull_request_binary is not null")).isEqualTo(1); + Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), BRANCH.getUuid()); + assertThat(branchDto).isPresent(); + assertThat(branchDto.get().getBranchType()).isEqualTo(PULL_REQUEST); + assertThat(branchDto.get().getKey()).isEqualTo(pullRequestId); + assertThat(branchDto.get().getMergeBranchUuid()).isEqualTo(mergeBranchUuid); + assertThat(branchDto.get().getProjectUuid()).isEqualTo(MAIN.getUuid()); + assertThat(branchDto.get().getPullRequestData()).isEqualTo(DbProjectBranches.PullRequestData.newBuilder() + .setBranch(pullRequestId) + .setTitle(pullRequestId) + .build()); } private static Branch createBranch(BranchType type, boolean isMain, String name) { + return createBranch(type, isMain, name, null); + } + + private static Branch createBranch(BranchType type, boolean isMain, String name, @Nullable String mergeBranchUuid) { Branch branch = mock(Branch.class); when(branch.getType()).thenReturn(type); when(branch.getName()).thenReturn(name); when(branch.isMain()).thenReturn(isMain); - when(branch.getMergeBranchUuid()).thenReturn(Optional.empty()); + when(branch.getMergeBranchUuid()).thenReturn(Optional.ofNullable(mergeBranchUuid)); return branch; } + + private void expectMissingComponentISE() { + exception.expect(IllegalStateException.class); + exception.expectMessage("Component has been deleted by end-user during analysis"); + } } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCountTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCountTest.java index 2b103c4b3a9..502d6aa0e0f 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCountTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCountTest.java @@ -23,6 +23,7 @@ import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.sql.SQLException; +import java.util.Optional; import java.util.Random; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -57,6 +58,9 @@ public class PopulateFileSourceLineCountTest { @Test public void execute_has_no_effect_on_empty_table() throws SQLException { + String projectUuid = randomAlphanumeric(4); + when(ceTask.getComponent()).thenReturn(newComponent(projectUuid)); + underTest.execute(); } @@ -65,7 +69,7 @@ public class PopulateFileSourceLineCountTest { public void execute_populates_line_count_of_any_type(String type) throws SQLException { String projectUuid = randomAlphanumeric(4); String fileUuid = randomAlphanumeric(5); - when(ceTask.getComponentUuid()).thenReturn(projectUuid); + when(ceTask.getComponent()).thenReturn(newComponent(projectUuid)); int lineCount = 1 + random.nextInt(15); insertUnpopulatedFileSource(projectUuid, fileUuid, type, lineCount); assertThat(getLineCountByFileUuid(fileUuid)).isEqualTo(LINE_COUNT_NOT_POPULATED); @@ -86,7 +90,7 @@ public class PopulateFileSourceLineCountTest { int lineCountFile2 = 50 + random.nextInt(15); int lineCountFile3 = 150 + random.nextInt(15); - when(ceTask.getComponentUuid()).thenReturn(projectUuid); + when(ceTask.getComponent()).thenReturn(newComponent(projectUuid)); insertPopulatedFileSource(projectUuid, fileUuid1, type, lineCountFile1); int badLineCountFile2 = insertInconsistentPopulatedFileSource(projectUuid, fileUuid2, type, lineCountFile2); insertUnpopulatedFileSource(projectUuid, fileUuid3, type, lineCountFile3); @@ -111,7 +115,7 @@ public class PopulateFileSourceLineCountTest { int lineCountFile1 = 100 + random.nextInt(15); int lineCountFile2 = 30 + random.nextInt(15); - when(ceTask.getComponentUuid()).thenReturn(projectUuid1); + when(ceTask.getComponent()).thenReturn(newComponent(projectUuid1)); insertUnpopulatedFileSource(projectUuid1, fileUuid1, type, lineCountFile1); insertUnpopulatedFileSource(projectUuid2, fileUuid2, type, lineCountFile2); @@ -127,7 +131,7 @@ public class PopulateFileSourceLineCountTest { String projectUuid = randomAlphanumeric(4); String fileUuid1 = randomAlphanumeric(5); - when(ceTask.getComponentUuid()).thenReturn(projectUuid); + when(ceTask.getComponent()).thenReturn(newComponent(projectUuid)); insertFileSource(projectUuid, fileUuid1, type, null, LINE_COUNT_NOT_POPULATED); underTest.execute(); @@ -141,7 +145,7 @@ public class PopulateFileSourceLineCountTest { String projectUuid = randomAlphanumeric(4); String fileUuid1 = randomAlphanumeric(5); - when(ceTask.getComponentUuid()).thenReturn(projectUuid); + when(ceTask.getComponent()).thenReturn(newComponent(projectUuid)); insertFileSource(projectUuid, fileUuid1, type, "", LINE_COUNT_NOT_POPULATED); underTest.execute(); @@ -204,4 +208,8 @@ public class PopulateFileSourceLineCountTest { "UPDATED_AT", 1_222_333L); db.commit(); } + + private static Optional<CeTask.Component> newComponent(String projectUuid) { + return Optional.of(new CeTask.Component(projectUuid, "key_" + projectUuid, "name_" + projectUuid)); + } } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java index 41e3a4f8b73..3bf4c6fa7fe 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java @@ -25,6 +25,7 @@ import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import org.assertj.core.api.Assertions; import org.junit.Before; import org.junit.Rule; @@ -166,9 +167,43 @@ public class LoadReportAnalysisMetadataHolderStepTest { } @Test + public void execute_fails_with_ISE_if_component_is_null_in_CE_task() { + CeTask res = mock(CeTask.class); + when(res.getComponent()).thenReturn(Optional.empty()); + when(res.getOrganizationUuid()).thenReturn(defaultOrganizationProvider.get().getUuid()); + reportReader.setMetadata(ScannerReport.Metadata.newBuilder().build()); + + ComputationStep underTest = createStep(res); + + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("component missing on ce task"); + + underTest.execute(new TestComputationStepContext()); + } + + @Test + public void execute_fails_with_MessageException_if_main_projectKey_is_null_in_CE_task() { + CeTask res = mock(CeTask.class); + Optional<CeTask.Component> component = Optional.of(new CeTask.Component("main_prj_uuid", null, null)); + when(res.getComponent()).thenReturn(component); + when(res.getMainComponent()).thenReturn(component); + when(res.getOrganizationUuid()).thenReturn(defaultOrganizationProvider.get().getUuid()); + reportReader.setMetadata(ScannerReport.Metadata.newBuilder().build()); + + ComputationStep underTest = createStep(res); + + expectedException.expect(MessageException.class); + expectedException.expectMessage("Compute Engine task main component key is null. Project with UUID main_prj_uuid must have been deleted since report was uploaded. Can not proceed."); + + underTest.execute(new TestComputationStepContext()); + } + + @Test public void execute_fails_with_MessageException_if_projectKey_is_null_in_CE_task() { CeTask res = mock(CeTask.class); - when(res.getComponentUuid()).thenReturn("prj_uuid"); + Optional<CeTask.Component> component = Optional.of(new CeTask.Component("prj_uuid", null, null)); + when(res.getComponent()).thenReturn(component); + when(res.getMainComponent()).thenReturn(Optional.of(new CeTask.Component("main_prj_uuid", "main_prj_key", null))); when(res.getOrganizationUuid()).thenReturn(defaultOrganizationProvider.get().getUuid()); reportReader.setMetadata(ScannerReport.Metadata.newBuilder().build()); @@ -407,8 +442,10 @@ public class LoadReportAnalysisMetadataHolderStepTest { private CeTask createCeTask(String projectKey, String organizationUuid) { CeTask res = mock(CeTask.class); + Optional<CeTask.Component> component = Optional.of(new CeTask.Component(projectKey + "_uuid", projectKey, projectKey + "_name")); when(res.getOrganizationUuid()).thenReturn(organizationUuid); - when(res.getComponentKey()).thenReturn(projectKey); + when(res.getComponent()).thenReturn(component); + when(res.getMainComponent()).thenReturn(component); return res; } |