From 990247c12ce69eab699a5368e2e610ce7d0ff956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lesaint?= Date: Thu, 25 Aug 2016 18:43:57 +0200 Subject: [PATCH] SONAR-7861 support unset name of project in scanner report --- .../component/ComponentImpl.java | 91 ++-- .../component/ComponentRootBuilder.java | 147 +++++++ .../step/BuildComponentTreeStep.java | 108 ++--- .../component/ComponentImplTest.java | 103 +++-- .../component/ComponentRootBuilderTest.java | 396 ++++++++++++++++++ .../step/BuildComponentTreeStepTest.java | 2 +- 6 files changed, 659 insertions(+), 188 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentRootBuilder.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentRootBuilderTest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImpl.java index 8339fa1e5a28..8179270bc0c4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImpl.java @@ -19,20 +19,17 @@ */ package org.sonar.server.computation.task.projectanalysis.component; -import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.List; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; -import org.sonar.scanner.protocol.output.ScannerReport; -import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static java.util.Arrays.asList; +import static java.util.Objects.requireNonNull; import static org.apache.commons.lang.StringUtils.trimToNull; @Immutable @@ -53,7 +50,7 @@ public class ComponentImpl implements Component { private ComponentImpl(Builder builder) { this.type = builder.type; this.key = builder.key; - this.name = builder.name == null ? String.valueOf(builder.key) : builder.name; + this.name = builder.name; this.description = builder.description; this.uuid = builder.uuid; this.reportAttributes = builder.reportAttributes; @@ -108,14 +105,19 @@ public ProjectViewAttributes getProjectViewAttributes() { throw new IllegalStateException("Only component of type PROJECT_VIEW have a FileAttributes object"); } - public static Builder builder(ScannerReport.Component component) { - return new Builder(component); + public static Builder builder(Type type) { + return new Builder(type); } public static final class Builder { + private static final String KEY_CANNOT_BE_NULL = "key can't be null"; + private static final String UUID_CANNOT_BE_NULL = "uuid can't be null"; + private static final String REPORT_ATTRIBUTES_CANNOT_BE_NULL = "reportAttributes can't be null"; + private static final String NAME_CANNOT_BE_NULL = "name can't be null"; + private final Type type; - private final ReportAttributes reportAttributes; + private ReportAttributes reportAttributes; private String uuid; private String key; private String name; @@ -123,71 +125,54 @@ public static final class Builder { private FileAttributes fileAttributes; private final List children = new ArrayList<>(); - private Builder(ScannerReport.Component component) { - checkNotNull(component); - this.type = convertType(component.getType()); - this.name = component.getName(); - this.description = trimToNull(component.getDescription()); - this.reportAttributes = createBatchAttributes(component); - this.fileAttributes = createFileAttributes(component); + private Builder(Type type){ + this.type = requireNonNull(type, "type can't be null"); + } + + public Builder setReportAttributes(ReportAttributes reportAttributes) { + this.reportAttributes = requireNonNull(reportAttributes, REPORT_ATTRIBUTES_CANNOT_BE_NULL); + return this; } public Builder setUuid(String s) { - this.uuid = checkNotNull(s); + this.uuid = requireNonNull(s, UUID_CANNOT_BE_NULL); return this; } public Builder setKey(String s) { - this.key = checkNotNull(s); + this.key = requireNonNull(s, KEY_CANNOT_BE_NULL); return this; } - public Builder addChildren(Component... c) { - for (Component component : c) { - checkArgument(component.getType().isReportType()); - } - this.children.addAll(asList(c)); + public Builder setName(String name) { + this.name = requireNonNull(name, NAME_CANNOT_BE_NULL); return this; } - public ComponentImpl build() { - checkNotNull(key); - checkNotNull(uuid); - return new ComponentImpl(this); + public Builder setDescription(@Nullable String description) { + this.description = trimToNull(description); + return this; } - private static ReportAttributes createBatchAttributes(ScannerReport.Component component) { - return ReportAttributes.newBuilder(component.getRef()) - .setVersion(trimToNull(component.getVersion())) - .setPath(trimToNull(component.getPath())) - .build(); + public Builder setFileAttributes(@Nullable FileAttributes fileAttributes) { + this.fileAttributes = fileAttributes; + return this; } - @CheckForNull - private static FileAttributes createFileAttributes(ScannerReport.Component component) { - if (component.getType() != ComponentType.FILE) { - return null; + public Builder addChildren(Component... c) { + for (Component component : c) { + checkArgument(component.getType().isReportType()); } - - return new FileAttributes( - component.getIsTest(), - trimToNull(component.getLanguage())); + this.children.addAll(asList(c)); + return this; } - @VisibleForTesting - static Type convertType(ComponentType type) { - switch (type) { - case PROJECT: - return Type.PROJECT; - case MODULE: - return Type.MODULE; - case DIRECTORY: - return Type.DIRECTORY; - case FILE: - return Type.FILE; - default: - throw new IllegalArgumentException("Unsupported ComponentType value " + type); - } + public ComponentImpl build() { + requireNonNull(reportAttributes, REPORT_ATTRIBUTES_CANNOT_BE_NULL); + requireNonNull(uuid, UUID_CANNOT_BE_NULL); + requireNonNull(key, KEY_CANNOT_BE_NULL); + requireNonNull(name, NAME_CANNOT_BE_NULL); + return new ComponentImpl(this); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentRootBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentRootBuilder.java new file mode 100644 index 000000000000..e072e3eae4f2 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentRootBuilder.java @@ -0,0 +1,147 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.task.projectanalysis.component; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.base.Supplier; +import java.util.function.Function; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.db.component.ComponentDto; +import org.sonar.scanner.protocol.output.ScannerReport; + +import static com.google.common.collect.Iterables.toArray; +import static java.lang.String.format; +import static org.apache.commons.lang.StringUtils.trimToNull; +import static org.sonar.core.component.ComponentKeys.createEffectiveKey; +import static org.sonar.core.component.ComponentKeys.createKey; +import static org.sonar.core.util.stream.Collectors.toList; + +public class ComponentRootBuilder { + private final Function uuidSupplier; + private final Function scannerComponentSupplier; + private final Supplier> projectDtoSupplier; + @CheckForNull + private final String branch; + + public ComponentRootBuilder(@Nullable String branch, + Function uuidSupplier, + Function scannerComponentSupplier, + Supplier> projectDtoSupplier) { + this.uuidSupplier = uuidSupplier; + this.scannerComponentSupplier = scannerComponentSupplier; + this.projectDtoSupplier = projectDtoSupplier; + this.branch = branch; + } + + public Component build(ScannerReport.Component reportProject, String projectKey) { + return buildComponent(reportProject, projectKey); + } + + private ComponentImpl buildComponent(ScannerReport.Component reportComponent, String latestModuleKey) { + switch (reportComponent.getType()) { + case PROJECT: + return createCommonBuilder(reportComponent, latestModuleKey, latestModuleKey) + .setName(nameOfProject(reportComponent, latestModuleKey, projectDtoSupplier)) + .build(); + case MODULE: + String moduleKey = createKey(reportComponent.getKey(), branch); + return buildOtherComponent(reportComponent, moduleKey, moduleKey); + case DIRECTORY: + case FILE: + return buildOtherComponent(reportComponent, createEffectiveKey(latestModuleKey, reportComponent.getPath()), latestModuleKey); + default: + throw new IllegalArgumentException(format("Unsupported component type '%s'", reportComponent.getType())); + } + } + + private ComponentImpl buildOtherComponent(ScannerReport.Component reportComponent, String componentKey, String latestModuleKey) { + return createCommonBuilder(reportComponent, componentKey, latestModuleKey) + .setName(nameOfOthers(reportComponent, componentKey)) + .build(); + } + + private ComponentImpl.Builder createCommonBuilder(ScannerReport.Component reportComponent, String componentKey, String latestModuleKey) { + return ComponentImpl.builder(convertType(reportComponent.getType())) + .setUuid(uuidSupplier.apply(componentKey)) + .setKey(componentKey) + .setDescription(trimToNull(reportComponent.getDescription())) + .setFileAttributes(createFileAttributes(reportComponent)) + .setReportAttributes(createReportAttributes(reportComponent)) + .addChildren(toArray(buildChildren(reportComponent, latestModuleKey), Component.class)); + } + + private Iterable buildChildren(ScannerReport.Component component, String latestModuleKey) { + return component.getChildRefList() + .stream() + .map(componentRef -> buildComponent(scannerComponentSupplier.apply(componentRef), latestModuleKey)) + .collect(toList(component.getChildRefList().size())); + } + + private static String nameOfProject(ScannerReport.Component project, String projectKey, Supplier> projectDtoSupplier) { + String name = trimToNull(project.getName()); + if (name == null) { + return projectDtoSupplier.get().transform(ComponentDto::name).or(projectKey); + } + return name; + } + + private static String nameOfOthers(ScannerReport.Component reportComponent, String componentKey) { + String name = trimToNull(reportComponent.getName()); + return name == null ? componentKey : name; + } + + @VisibleForTesting + static ReportAttributes createReportAttributes(ScannerReport.Component component) { + return ReportAttributes.newBuilder(component.getRef()) + .setPath(trimToNull(component.getPath())) + .setVersion(trimToNull(component.getVersion())) + .build(); + } + + @VisibleForTesting + @CheckForNull + static FileAttributes createFileAttributes(ScannerReport.Component component) { + if (component.getType() != ScannerReport.Component.ComponentType.FILE) { + return null; + } + + return new FileAttributes( + component.getIsTest(), + trimToNull(component.getLanguage())); + } + + @VisibleForTesting + static Component.Type convertType(ScannerReport.Component.ComponentType type) { + switch (type) { + case PROJECT: + return Component.Type.PROJECT; + case MODULE: + return Component.Type.MODULE; + case DIRECTORY: + return Component.Type.DIRECTORY; + case FILE: + return Component.Type.FILE; + default: + throw new IllegalArgumentException("Unsupported ComponentType value " + type); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStep.java index 0b322adf7491..c97670c2f1dd 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStep.java @@ -19,26 +19,23 @@ */ package org.sonar.server.computation.task.projectanalysis.step; -import com.google.common.collect.Iterables; import javax.annotation.CheckForNull; import javax.annotation.Nullable; -import org.sonar.core.component.ComponentKeys; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.SnapshotDto; import org.sonar.db.component.SnapshotQuery; import org.sonar.scanner.protocol.output.ScannerReport; +import org.sonar.server.computation.task.projectanalysis.analysis.Analysis; import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolder; import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader; import org.sonar.server.computation.task.projectanalysis.component.Component; -import org.sonar.server.computation.task.projectanalysis.component.ComponentImpl; +import org.sonar.server.computation.task.projectanalysis.component.ComponentRootBuilder; import org.sonar.server.computation.task.projectanalysis.component.MutableTreeRootHolder; import org.sonar.server.computation.task.projectanalysis.component.UuidFactory; -import org.sonar.server.computation.task.projectanalysis.analysis.Analysis; import org.sonar.server.computation.task.step.ComputationStep; -import static com.google.common.collect.Iterables.toArray; -import static org.sonar.server.computation.task.projectanalysis.component.ComponentImpl.builder; +import static org.sonar.core.component.ComponentKeys.createKey; /** * Populates the {@link MutableTreeRootHolder} and {@link MutableAnalysisMetadataHolder} from the {@link BatchReportReader} @@ -57,92 +54,47 @@ public BuildComponentTreeStep(DbClient dbClient, BatchReportReader reportReader, this.analysisMetadataHolder = analysisMetadataHolder; } + @Override + public String getDescription() { + return "Build tree of components"; + } + @Override public void execute() { String branch = analysisMetadataHolder.getBranch(); ScannerReport.Component reportProject = reportReader.readComponent(analysisMetadataHolder.getRootComponentRef()); - UuidFactory uuidFactory = new UuidFactory(dbClient, moduleKey(reportProject, branch)); - Component project = new ComponentRootBuilder(reportProject, uuidFactory, branch).build(); - treeRootHolder.setRoot(project); - setBaseAnalysis(project.getUuid()); + String projectKey = createKey(reportProject.getKey(), branch); + UuidFactory uuidFactory = new UuidFactory(dbClient, projectKey); + + try (DbSession dbSession = dbClient.openSession(false)) { + ComponentRootBuilder rootBuilder = new ComponentRootBuilder(branch, + uuidFactory::getOrCreateForKey, + reportReader::readComponent, + () -> dbClient.componentDao().selectByKey(dbSession, projectKey)); + Component project = rootBuilder.build(reportProject, projectKey); + treeRootHolder.setRoot(project); + setBaseAnalysis(dbSession, project.getUuid()); + } } - private void setBaseAnalysis(String projectUuid) { - DbSession dbSession = dbClient.openSession(false); - try { - SnapshotDto snapshotDto = dbClient.snapshotDao().selectAnalysisByQuery(dbSession, - new SnapshotQuery() - .setComponentUuid(projectUuid) - .setIsLast(true)); - analysisMetadataHolder.setBaseAnalysis(toAnalysis(snapshotDto)); - } finally { - dbClient.closeSession(dbSession); - } + private void setBaseAnalysis(DbSession dbSession, String projectUuid) { + SnapshotDto snapshotDto = dbClient.snapshotDao().selectAnalysisByQuery(dbSession, + new SnapshotQuery() + .setComponentUuid(projectUuid) + .setIsLast(true)); + analysisMetadataHolder.setBaseAnalysis(toAnalysis(snapshotDto)); } @CheckForNull private static Analysis toAnalysis(@Nullable SnapshotDto snapshotDto) { - return snapshotDto == null ? null : new Analysis.Builder() + if (snapshotDto == null) { + return null; + } + return new Analysis.Builder() .setId(snapshotDto.getId()) .setUuid(snapshotDto.getUuid()) .setCreatedAt(snapshotDto.getCreatedAt()) .build(); } - private class ComponentRootBuilder { - - private final ScannerReport.Component reportProject; - - private final UuidFactory uuidFactory; - - @CheckForNull - private final String branch; - - public ComponentRootBuilder(ScannerReport.Component reportProject, UuidFactory uuidFactory, @Nullable String branch) { - this.reportProject = reportProject; - this.uuidFactory = uuidFactory; - this.branch = branch; - } - - private Component build() { - return buildComponent(reportProject, moduleKey(reportProject, branch)); - } - - private ComponentImpl buildComponent(ScannerReport.Component reportComponent, String latestModuleKey) { - switch (reportComponent.getType()) { - case PROJECT: - case MODULE: - String moduleKey = moduleKey(reportComponent, branch); - return buildComponent(reportComponent, moduleKey, moduleKey); - case DIRECTORY: - case FILE: - return buildComponent(reportComponent, ComponentKeys.createEffectiveKey(latestModuleKey, reportComponent.getPath()), latestModuleKey); - default: - throw new IllegalStateException(String.format("Unsupported component type '%s'", reportComponent.getType())); - } - } - - private ComponentImpl buildComponent(ScannerReport.Component reportComponent, String componentKey, String latestModuleKey) { - return builder(reportComponent) - .addChildren(toArray(buildChildren(reportComponent, latestModuleKey), Component.class)) - .setKey(componentKey) - .setUuid(uuidFactory.getOrCreateForKey(componentKey)) - .build(); - } - - private Iterable buildChildren(ScannerReport.Component component, final String latestModuleKey) { - return Iterables.transform( - component.getChildRefList(), - componentRef -> buildComponent(reportReader.readComponent(componentRef), latestModuleKey)); - } - } - - private static String moduleKey(ScannerReport.Component reportComponent, @Nullable String branch) { - return ComponentKeys.createKey(reportComponent.getKey(), branch); - } - - @Override - public String getDescription() { - return "Build tree of components"; - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImplTest.java index 90ffa33a9e31..1d8c00655195 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImplTest.java @@ -19,22 +19,14 @@ */ package org.sonar.server.computation.task.projectanalysis.component; +import java.util.Arrays; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.scanner.protocol.output.ScannerReport; -import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType; -import static com.google.common.base.Predicates.in; -import static com.google.common.base.Predicates.not; -import static com.google.common.collect.FluentIterable.from; -import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; -import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.DIRECTORY; -import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.FILE; -import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.UNRECOGNIZED; -import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.UNSET; +import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE; import static org.sonar.server.computation.task.projectanalysis.component.ComponentImpl.builder; public class ComponentImplTest { @@ -46,11 +38,12 @@ public class ComponentImplTest { public ExpectedException thrown = ExpectedException.none(); @Test - public void verify_key_and_uuid() throws Exception { - ComponentImpl component = builder(ScannerReport.Component.newBuilder().setType(FILE).build()).setKey(KEY).setUuid(UUID).build(); + public void verify_key_uuid_and_name() throws Exception { + ComponentImpl component = buildSimpleComponent(FILE, KEY).setUuid(UUID).setName("name").build(); assertThat(component.getKey()).isEqualTo(KEY); assertThat(component.getUuid()).isEqualTo(UUID); + assertThat(component.getName()).isEqualTo("name"); } @Test @@ -64,60 +57,55 @@ public void builder_throws_NPE_if_component_arg_is_Null() { public void set_key_throws_NPE_if_component_arg_is_Null() { thrown.expect(NullPointerException.class); - builder(ScannerReport.Component.newBuilder().setType(FILE).build()).setUuid(null); + builder(FILE).setUuid(null); } @Test public void set_uuid_throws_NPE_if_component_arg_is_Null() { thrown.expect(NullPointerException.class); - builder(ScannerReport.Component.newBuilder().setType(FILE).build()).setKey(null); + builder(FILE).setKey(null); } @Test public void build_without_key_throws_NPE_if_component_arg_is_Null() { thrown.expect(NullPointerException.class); - builder(ScannerReport.Component.newBuilder().setType(FILE).build()).setUuid("ABCD").build(); + builder(FILE).setUuid("ABCD").build(); } @Test public void build_without_uuid_throws_NPE_if_component_arg_is_Null() { thrown.expect(NullPointerException.class); - builder(ScannerReport.Component.newBuilder().setType(FILE).build()).setKey(KEY).build(); + builder(FILE).setKey(KEY).build(); } @Test public void get_name_from_batch_component() { String name = "project"; - ComponentImpl component = buildSimpleComponent(ScannerReport.Component.newBuilder().setType(FILE).setName(name).build()); + ComponentImpl component = buildSimpleComponent(FILE, "file").setName(name).build(); assertThat(component.getName()).isEqualTo(name); } - @Test - public void get_version_from_batch_component() { - String version = "1.0"; - ComponentImpl component = buildSimpleComponent(ScannerReport.Component.newBuilder().setType(FILE).setVersion(version).build()); - assertThat(component.getReportAttributes().getVersion()).isEqualTo(version); - } - @Test public void getFileAttributes_throws_ISE_if_BatchComponent_does_not_have_type_FILE() { - for (ComponentType componentType : from(asList(ComponentType.values())).filter(not(in(asList(FILE, UNSET, UNRECOGNIZED))))) { - ComponentImpl component = buildSimpleComponent(ScannerReport.Component.newBuilder().setType(componentType).build()); - try { - component.getFileAttributes(); - fail("A IllegalStateException should have been raised"); - } catch (IllegalStateException e) { - assertThat(e).hasMessage("Only component of type FILE have a FileAttributes object"); - } - } + Arrays.stream(Component.Type.values()) + .filter(type -> type != FILE) + .forEach((componentType) -> { + ComponentImpl component = buildSimpleComponent(componentType, componentType.name()).build(); + try { + component.getFileAttributes(); + fail("A IllegalStateException should have been raised"); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("Only component of type FILE have a FileAttributes object"); + } + }); } @Test public void isUnitTest_returns_true_if_IsTest_is_set_in_BatchComponent() { - ComponentImpl component = buildSimpleComponent(ScannerReport.Component.newBuilder().setType(FILE).setIsTest(true).build()); + ComponentImpl component = buildSimpleComponent(FILE, "file").setFileAttributes(new FileAttributes(true, null)).build(); assertThat(component.getFileAttributes().isUnitTest()).isTrue(); } @@ -125,20 +113,24 @@ public void isUnitTest_returns_true_if_IsTest_is_set_in_BatchComponent() { @Test public void isUnitTest_returns_value_of_language_of_BatchComponent() { String languageKey = "some language key"; - ComponentImpl component = buildSimpleComponent(ScannerReport.Component.newBuilder().setType(FILE).setLanguage(languageKey).build()); + ComponentImpl component = buildSimpleComponent(FILE, "file").setFileAttributes(new FileAttributes(false, languageKey)).build(); assertThat(component.getFileAttributes().getLanguageKey()).isEqualTo(languageKey); } @Test public void build_with_child() throws Exception { - ComponentImpl child = builder(ScannerReport.Component.newBuilder().setType(FILE).build()) + ComponentImpl child = builder(FILE) + .setName("CHILD_NAME") .setKey("CHILD_KEY") .setUuid("CHILD_UUID") + .setReportAttributes(ReportAttributes.newBuilder(2).build()) .build(); - ComponentImpl componentImpl = builder(ScannerReport.Component.newBuilder().setType(DIRECTORY).build()) + ComponentImpl componentImpl = builder(Component.Type.DIRECTORY) + .setName("DIR") .setKey(KEY) .setUuid(UUID) + .setReportAttributes(ReportAttributes.newBuilder(1).build()) .addChildren(child) .build(); @@ -146,34 +138,33 @@ public void build_with_child() throws Exception { Component childReloaded = componentImpl.getChildren().iterator().next(); assertThat(childReloaded.getKey()).isEqualTo("CHILD_KEY"); assertThat(childReloaded.getUuid()).isEqualTo("CHILD_UUID"); - assertThat(childReloaded.getType()).isEqualTo(Component.Type.FILE); - } - - @Test - public void convertType() { - for (ComponentType componentType : from(asList(ComponentType.values())).filter(not(in(asList(UNSET, UNRECOGNIZED))))) { - assertThat(ComponentImpl.Builder.convertType(componentType)).isEqualTo(Component.Type.valueOf(componentType.name())); - } - } - - private static ComponentImpl buildSimpleComponent(ScannerReport.Component reportComponent) { - return builder(reportComponent).setKey(KEY).setUuid(UUID).build(); + assertThat(childReloaded.getType()).isEqualTo(FILE); } @Test public void equals_compares_on_uuid_only() { - ComponentImpl.Builder builder = builder(ScannerReport.Component.newBuilder().setType(FILE).build()).setUuid(UUID); + ComponentImpl.Builder builder = buildSimpleComponent(FILE, "1").setUuid(UUID); - assertThat(builder.setKey("1").build()).isEqualTo(builder.setKey("1").build()); - assertThat(builder.setKey("1").build()).isEqualTo(builder.setKey("2").build()); + assertThat(builder.build()).isEqualTo(builder.build()); + assertThat(builder.build()).isEqualTo(buildSimpleComponent(FILE, "2").setUuid(UUID).build()); + assertThat(builder.build()).isNotEqualTo(buildSimpleComponent(FILE, "1").setUuid("otherUUid").build()); } @Test public void hashCode_is_hashcode_of_uuid() { - ComponentImpl.Builder builder = builder(ScannerReport.Component.newBuilder().setType(FILE).build()).setUuid(UUID); + ComponentImpl.Builder builder = buildSimpleComponent(FILE, "1").setUuid(UUID); + + assertThat(builder.build().hashCode()).isEqualTo(builder.build().hashCode()); + assertThat(builder.build().hashCode()).isEqualTo(buildSimpleComponent(FILE, "2").setUuid(UUID).build().hashCode()); + assertThat(builder.build().hashCode()).isEqualTo(UUID.hashCode()); + } - assertThat(builder.setKey("1").build().hashCode()).isEqualTo(builder.setKey("1").build().hashCode()); - assertThat(builder.setKey("1").build().hashCode()).isEqualTo(builder.setKey("2").build().hashCode()); - assertThat(builder.setKey("1").build().hashCode()).isEqualTo(UUID.hashCode()); + private static ComponentImpl.Builder buildSimpleComponent(Component.Type type, String key) { + return builder(type) + .setName("name_" + key) + .setKey(key) + .setUuid("uuid_" + key) + .setReportAttributes(ReportAttributes.newBuilder(key.hashCode()) + .build()); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentRootBuilderTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentRootBuilderTest.java new file mode 100644 index 000000000000..3fa1c144f114 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentRootBuilderTest.java @@ -0,0 +1,396 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.task.projectanalysis.component; + +import com.google.common.base.Optional; +import com.google.common.base.Supplier; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExternalResource; +import org.sonar.db.component.ComponentDto; +import org.sonar.scanner.protocol.output.ScannerReport; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; +import static org.sonar.scanner.protocol.output.ScannerReport.Component.newBuilder; +import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.DIRECTORY; +import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.FILE; +import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.MODULE; +import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.PROJECT; +import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.UNRECOGNIZED; +import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.UNSET; +import static org.sonar.server.computation.task.projectanalysis.component.ComponentRootBuilder.createFileAttributes; +import static org.sonar.server.computation.task.projectanalysis.component.ComponentRootBuilder.createReportAttributes; +import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER; + +public class ComponentRootBuilderTest { + + private static final Function SIMPLE_UUID_GENERATOR = (componentKey) -> componentKey + "_uuid"; + private static final String NO_BRANCH = null; + private static final String PROJECT_KEY = "this is the key"; + private static final String MODULE_KEY = "module key"; + private static final String DIRECTORY_PATH = "directory path"; + private static final String DIRECTORY_KEY = MODULE_KEY + ":" + DIRECTORY_PATH; + private static final String FILE_PATH = "file path"; + private static final String FILE_KEY = MODULE_KEY + ":" + FILE_PATH; + private static final ComponentDto PROJECT_DTO = new ComponentDto().setName("name in db"); + private static final Supplier> NO_COMPONENT_DTO_FOR_PROJECT = Optional::absent; + private static final Supplier> COMPONENT_DTO_FOR_PROJECT = () -> Optional.of(PROJECT_DTO); + private static final EnumSet REPORT_TYPES = EnumSet.of( + PROJECT, MODULE, DIRECTORY, FILE); + + @Rule + public ScannerComponentProvider scannerComponentProvider = new ScannerComponentProvider(); + + private ComponentRootBuilder underTest = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, NO_COMPONENT_DTO_FOR_PROJECT); + + @Test + public void build_throws_IAE_for_all_types_but_PROJECT_MODULE_DIRECTORY_FILE() { + Arrays.stream(ScannerReport.Component.ComponentType.values()) + .filter((type) -> type != UNRECOGNIZED) + .filter((type) -> !REPORT_TYPES.contains(type)) + .forEach( + (type) -> { + ScannerReport.Component component = newBuilder().setType(type).build(); + try { + underTest.build(component, "don't care"); + fail("Should have thrown a IllegalArgumentException"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Unsupported component type '" + type + "'"); + } + }); + } + + @Test + public void name_of_project_is_name_in_Scanner_Component_when_set() { + String expected = "the name"; + Component root = underTest.build(newBuilder().setType(PROJECT).setName(expected).build(), PROJECT_KEY); + assertThat(root.getName()).isEqualTo(expected); + } + + @Test + public void name_of_project_is_name_in_Scanner_Component_when_set_even_if_there_is_a_ComponentDto() { + String expected = "the name"; + Component root = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, COMPONENT_DTO_FOR_PROJECT) + .build(newBuilder().setType(PROJECT).setName(expected).build(), PROJECT_KEY); + assertThat(root.getName()).isEqualTo(expected); + } + + @Test + public void name_of_project_is_specified_key_when_name_is_unset_in_Scanner_Component_and_there_is_no_ComponentDto() { + Component root = underTest.build(newBuilder().setType(PROJECT).build(), PROJECT_KEY); + assertThat(root.getName()).isEqualTo(PROJECT_KEY); + } + + @Test + public void name_of_project_is_specified_key_when_name_is_empty_in_Scanner_Component_and_there_is_no_ComponentDto() { + Component root = underTest.build(newBuilder().setType(PROJECT).setName("").build(), PROJECT_KEY); + + assertThat(root.getName()).isEqualTo(PROJECT_KEY); + } + + @Test + public void name_of_project_is_name_of_ComponentDto_when_name_is_unset_in_Scanner_Component_and_there_is_a_ComponentDto() { + Component root = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, COMPONENT_DTO_FOR_PROJECT) + .build(newBuilder().setType(PROJECT).build(), PROJECT_KEY); + + assertThat(root.getName()).isEqualTo(PROJECT_DTO.name()); + } + + @Test + public void name_of_project_is_name_of_ComponentDto_when_name_is_empty_in_Scanner_Component_and_there_is_a_ComponentDto() { + Component root = new ComponentRootBuilder(NO_BRANCH, SIMPLE_UUID_GENERATOR, scannerComponentProvider, COMPONENT_DTO_FOR_PROJECT) + .build(newBuilder().setType(PROJECT).setName("").build(), PROJECT_KEY); + + assertThat(root.getName()).isEqualTo(PROJECT_DTO.name()); + } + + @Test + public void name_of_module_directory_and_file_contains_branch_when_non_empty() { + ScannerReport.Component project = newBuilder().setType(PROJECT).setRef(1).addChildRef(2).build(); + scannerComponentProvider.add(newBuilder().setRef(2).setType(MODULE).setKey(MODULE_KEY).addChildRef(3)); + scannerComponentProvider.add(newBuilder().setRef(3).setType(DIRECTORY).setPath(DIRECTORY_PATH).addChildRef(4)); + scannerComponentProvider.add(newBuilder().setRef(4).setType(FILE).setPath(FILE_PATH)); + + String branch = "BRANCH"; + ComponentRootBuilder builder = new ComponentRootBuilder(branch, SIMPLE_UUID_GENERATOR, scannerComponentProvider, NO_COMPONENT_DTO_FOR_PROJECT); + + Component root = builder.build(project, PROJECT_KEY); + assertThat(root.getKey()).isEqualTo(PROJECT_KEY); + assertThat(root.getChildren()).hasSize(1); + Component module = root.getChildren().iterator().next(); + assertThat(module.getKey()).isEqualTo(MODULE_KEY + ":" + branch); + assertThat(module.getChildren()).hasSize(1); + Component directory = module.getChildren().iterator().next(); + assertThat(directory.getKey()).isEqualTo(module.getKey() + ":" + DIRECTORY_PATH); + assertThat(directory.getChildren()).hasSize(1); + Component file = directory.getChildren().iterator().next(); + assertThat(file.getKey()).isEqualTo(module.getKey() + ":" + FILE_PATH); + assertThat(file.getChildren()).isEmpty(); + } + + @Test + public void name_of_module_directory_and_file_is_key_of_Scanner_Component_when_name_is_unset() { + ScannerReport.Component project = newBuilder().setType(PROJECT).setRef(1).addChildRef(2).build(); + scannerComponentProvider.add(newBuilder().setRef(2).setType(MODULE).setKey(MODULE_KEY).addChildRef(3)); + scannerComponentProvider.add(newBuilder().setRef(3).setType(DIRECTORY).setPath(DIRECTORY_PATH).addChildRef(4)); + scannerComponentProvider.add(newBuilder().setRef(4).setType(FILE).setPath(FILE_PATH)); + + Component root = underTest.build(project, PROJECT_KEY); + assertThat(root.getKey()).isEqualTo(PROJECT_KEY); + Component module = root.getChildren().iterator().next(); + assertThat(module.getName()).isEqualTo(MODULE_KEY); + Component directory = module.getChildren().iterator().next(); + assertThat(directory.getName()).isEqualTo(module.getKey() + ":" + DIRECTORY_PATH); + Component file = directory.getChildren().iterator().next(); + assertThat(file.getName()).isEqualTo(module.getKey() + ":" + FILE_PATH); + } + + @Test + public void name_of_module_directory_and_file_is_key_of_Scanner_Component_when_name_is_empty() { + ScannerReport.Component project = newBuilder().setType(PROJECT).setRef(1).setName("").addChildRef(2).build(); + scannerComponentProvider.add(newBuilder().setRef(2).setType(MODULE).setKey(MODULE_KEY).setName("").addChildRef(3)); + scannerComponentProvider.add(newBuilder().setRef(3).setType(DIRECTORY).setPath(DIRECTORY_PATH).setName("").addChildRef(4)); + scannerComponentProvider.add(newBuilder().setRef(4).setType(FILE).setPath(FILE_PATH).setName("")); + + Component root = underTest.build(project, PROJECT_KEY); + assertThat(root.getKey()).isEqualTo(PROJECT_KEY); + Component module = root.getChildren().iterator().next(); + assertThat(module.getName()).isEqualTo(MODULE_KEY); + Component directory = module.getChildren().iterator().next(); + assertThat(directory.getName()).isEqualTo(module.getKey() + ":" + DIRECTORY_PATH); + Component file = directory.getChildren().iterator().next(); + assertThat(file.getName()).isEqualTo(module.getKey() + ":" + FILE_PATH); + } + + @Test + public void name_of_module_directory_and_files_includes_name_of_closest_module() { + ScannerReport.Component project = newBuilder().setType(PROJECT).setRef(1).addChildRef(11).addChildRef(21).addChildRef(31).build(); + scannerComponentProvider.add(newBuilder().setRef(11).setType(MODULE).setKey("module 1").addChildRef(12).addChildRef(22).addChildRef(32)); + scannerComponentProvider.add(newBuilder().setRef(12).setType(MODULE).setKey("module 2").addChildRef(13).addChildRef(23).addChildRef(33)); + scannerComponentProvider.add(newBuilder().setRef(13).setType(MODULE).setKey("module 3").addChildRef(24).addChildRef(34)); + scannerComponentProvider.add(newBuilder().setRef(21).setType(DIRECTORY).setPath("directory in project").addChildRef(35)); + scannerComponentProvider.add(newBuilder().setRef(22).setType(DIRECTORY).setPath("directory in module 1").addChildRef(36)); + scannerComponentProvider.add(newBuilder().setRef(23).setType(DIRECTORY).setPath("directory in module 2").addChildRef(37)); + scannerComponentProvider.add(newBuilder().setRef(24).setType(DIRECTORY).setPath("directory in module 3").addChildRef(38)); + scannerComponentProvider.add(newBuilder().setRef(31).setType(FILE).setPath("file in project")); + scannerComponentProvider.add(newBuilder().setRef(32).setType(FILE).setPath("file in module 1")); + scannerComponentProvider.add(newBuilder().setRef(33).setType(FILE).setPath("file in module 2")); + scannerComponentProvider.add(newBuilder().setRef(34).setType(FILE).setPath("file in module 3")); + scannerComponentProvider.add(newBuilder().setRef(35).setType(FILE).setPath("file in directory in project")); + scannerComponentProvider.add(newBuilder().setRef(36).setType(FILE).setPath("file in directory in module 1")); + scannerComponentProvider.add(newBuilder().setRef(37).setType(FILE).setPath("file in directory in module 2")); + scannerComponentProvider.add(newBuilder().setRef(38).setType(FILE).setPath("file in directory in module 3")); + + Component root = underTest.build(project, PROJECT_KEY); + Map componentsByRef = indexComponentByRef(root); + assertThat(componentsByRef.get(11).getKey()).isEqualTo("module 1"); + assertThat(componentsByRef.get(12).getKey()).isEqualTo("module 2"); + assertThat(componentsByRef.get(13).getKey()).isEqualTo("module 3"); + assertThat(componentsByRef.get(21).getKey()).startsWith(PROJECT_KEY + ":"); + assertThat(componentsByRef.get(22).getKey()).startsWith("module 1" + ":"); + assertThat(componentsByRef.get(23).getKey()).startsWith("module 2" + ":"); + assertThat(componentsByRef.get(24).getKey()).startsWith("module 3" + ":"); + assertThat(componentsByRef.get(31).getKey()).startsWith(PROJECT_KEY + ":"); + assertThat(componentsByRef.get(32).getKey()).startsWith("module 1" + ":"); + assertThat(componentsByRef.get(33).getKey()).startsWith("module 2" + ":"); + assertThat(componentsByRef.get(34).getKey()).startsWith("module 3" + ":"); + assertThat(componentsByRef.get(35).getKey()).startsWith(PROJECT_KEY + ":"); + assertThat(componentsByRef.get(36).getKey()).startsWith("module 1" + ":"); + assertThat(componentsByRef.get(37).getKey()).startsWith("module 2" + ":"); + assertThat(componentsByRef.get(38).getKey()).startsWith("module 3" + ":"); + } + + @Test + public void uuid_is_value_from_uuid_supplier_for_project_module_directory_and_file() { + ScannerReport.Component project = newBuilder().setType(PROJECT).setRef(1).addChildRef(2).build(); + scannerComponentProvider.add(newBuilder().setRef(2).setType(MODULE).setKey(MODULE_KEY).addChildRef(3)); + scannerComponentProvider.add(newBuilder().setRef(3).setType(DIRECTORY).setPath(DIRECTORY_PATH).addChildRef(4)); + scannerComponentProvider.add(newBuilder().setRef(4).setType(FILE).setPath(FILE_PATH)); + + Component root = underTest.build(project, PROJECT_KEY); + Map componentByRef = indexComponentByRef(root); + assertThat(componentByRef.get(1).getUuid()).isEqualTo(SIMPLE_UUID_GENERATOR.apply(PROJECT_KEY)); + assertThat(componentByRef.get(2).getUuid()).isEqualTo(SIMPLE_UUID_GENERATOR.apply(MODULE_KEY)); + assertThat(componentByRef.get(3).getUuid()).isEqualTo(SIMPLE_UUID_GENERATOR.apply(DIRECTORY_KEY)); + assertThat(componentByRef.get(4).getUuid()).isEqualTo(SIMPLE_UUID_GENERATOR.apply(FILE_KEY)); + + } + + @Test + public void description_of_project_module_directory_and_file_is_null_when_unset_in_Scanner_Component() { + ScannerReport.Component project = newBuilder().setType(PROJECT).setRef(1).addChildRef(2).build(); + scannerComponentProvider.add(newBuilder().setRef(2).setType(MODULE).addChildRef(3)); + scannerComponentProvider.add(newBuilder().setRef(3).setType(DIRECTORY).addChildRef(4)); + scannerComponentProvider.add(newBuilder().setRef(4).setType(FILE)); + + Component root = underTest.build(project, PROJECT_KEY); + Map componentByRef = indexComponentByRef(root); + assertThat(componentByRef.get(1).getDescription()).isNull(); + assertThat(componentByRef.get(2).getDescription()).isNull(); + assertThat(componentByRef.get(3).getDescription()).isNull(); + assertThat(componentByRef.get(4).getDescription()).isNull(); + } + + @Test + public void description_of_project_module_directory_and_file_is_null_when_empty_in_Scanner_Component() { + ScannerReport.Component project = newBuilder().setType(PROJECT).setRef(1).setDescription("").addChildRef(2).build(); + scannerComponentProvider.add(newBuilder().setRef(2).setType(MODULE).setDescription("").addChildRef(3)); + scannerComponentProvider.add(newBuilder().setRef(3).setType(DIRECTORY).setDescription("").addChildRef(4)); + scannerComponentProvider.add(newBuilder().setRef(4).setType(FILE).setDescription("")); + + Component root = underTest.build(project, PROJECT_KEY); + Map componentByRef = indexComponentByRef(root); + assertThat(componentByRef.get(1).getDescription()).isNull(); + assertThat(componentByRef.get(2).getDescription()).isNull(); + assertThat(componentByRef.get(3).getDescription()).isNull(); + assertThat(componentByRef.get(4).getDescription()).isNull(); + } + + @Test + public void description_of_project_module_directory_and_file_is_description_of_Scanner_Component_when_set() { + ScannerReport.Component project = newBuilder().setType(PROJECT).setRef(1).setDescription("desc of project").addChildRef(2).build(); + scannerComponentProvider.add(newBuilder().setRef(2).setType(MODULE).setDescription("desc of module").addChildRef(3)); + scannerComponentProvider.add(newBuilder().setRef(3).setType(DIRECTORY).setDescription("desc of directory").addChildRef(4)); + scannerComponentProvider.add(newBuilder().setRef(4).setType(FILE).setDescription("desc of file")); + + Component root = underTest.build(project, PROJECT_KEY); + Map componentByRef = indexComponentByRef(root); + assertThat(componentByRef.get(1).getDescription()).isEqualTo("desc of project"); + assertThat(componentByRef.get(2).getDescription()).isEqualTo("desc of module"); + assertThat(componentByRef.get(3).getDescription()).isEqualTo("desc of directory"); + assertThat(componentByRef.get(4).getDescription()).isEqualTo("desc of file"); + } + + @Test + public void all_types_but_UNSET_and_UNRECOGNIZED_are_converted() { + Arrays.stream(ScannerReport.Component.ComponentType.values()) + .filter((type) -> type != UNRECOGNIZED) + .filter((type) -> type != UNSET) + .forEach((type) -> assertThat(ComponentRootBuilder.convertType(type)).isEqualTo(Component.Type.valueOf(type.name()))); + } + + @Test + public void createReportAttributes_takes_ref_version_and_path_from_Scanner_Component() { + int ref = 123; + String version = "1.0"; + String path = "some path"; + + ReportAttributes reportAttributes = createReportAttributes(newBuilder() + .setRef(ref) + .setVersion(version) + .setPath(path) + .build()); + assertThat(reportAttributes.getRef()).isEqualTo(ref); + assertThat(reportAttributes.getPath()).isEqualTo(path); + assertThat(reportAttributes.getVersion()).isEqualTo(version); + } + + @Test + public void createReportAttributes_sets_null_version_when_unset_in_Scanner_Component() { + ReportAttributes reportAttributes = createReportAttributes(newBuilder().build()); + assertThat(reportAttributes.getVersion()).isNull(); + } + + @Test + public void createReportAttributes_sets_null_path_when_unset_in_Scanner_Component() { + ReportAttributes reportAttributes = createReportAttributes(newBuilder().build()); + assertThat(reportAttributes.getPath()).isNull(); + } + + @Test + public void createReportAttributes_sets_null_version_when_empty_in_Scanner_Component() { + ReportAttributes reportAttributes = createReportAttributes(newBuilder().setVersion("").build()); + assertThat(reportAttributes.getVersion()).isNull(); + } + + @Test + public void createReportAttributes_sets_null_path_when_empty_in_Scanner_Component() { + ReportAttributes reportAttributes = createReportAttributes(newBuilder().setPath("").build()); + assertThat(reportAttributes.getPath()).isNull(); + } + + @Test + public void createFileAttributes_returns_null_when_type_is_not_FILE() { + Arrays.stream(ScannerReport.Component.ComponentType.values()) + .filter((type) -> type != UNRECOGNIZED) + .filter((type) -> type != FILE) + .map( + (type) -> newBuilder().setType(type).build()) + .forEach( + (component) -> assertThat(createFileAttributes(component)).isNull()); + } + + @Test + public void createFileAttributes_sets_language_to_null_when_unset_in_Scanner_Component() { + assertThat(createFileAttributes(newBuilder().setType(FILE).build()).getLanguageKey()).isNull(); + } + + @Test + public void createFileAttributes_sets_language_to_null_when_empty_in_Scanner_Component() { + assertThat(createFileAttributes(newBuilder().setType(FILE).setLanguage("").build()).getLanguageKey()).isNull(); + } + + @Test + public void createFileAttributes_sets_unitTest_from_Scanner_Component() { + assertThat(createFileAttributes(newBuilder().setType(FILE).build()).isUnitTest()).isFalse(); + assertThat(createFileAttributes(newBuilder().setType(FILE).setIsTest(true).build()).isUnitTest()).isTrue(); + } + + private static class ScannerComponentProvider extends ExternalResource implements Function { + private final Map components = new HashMap<>(); + + @Override + protected void before() throws Throwable { + components.clear(); + } + + @Override + public ScannerReport.Component apply(Integer componentRef) { + return checkNotNull(components.get(componentRef), "No Component for componentRef %s", componentRef); + } + + public ScannerReport.Component add(ScannerReport.Component.Builder builder) { + ScannerReport.Component component = builder.build(); + ScannerReport.Component existing = components.put(component.getRef(), component); + checkArgument(existing == null, "Component %s already set for ref %s", existing, component.getRef()); + return component; + } + } + + private static Map indexComponentByRef(Component root) { + Map componentsByRef = new HashMap<>(); + new DepthTraversalTypeAwareCrawler( + new TypeAwareVisitorAdapter(CrawlerDepthLimit.FILE, PRE_ORDER) { + @Override + public void visitAny(Component any) { + componentsByRef.put(any.getReportAttributes().getRef(), any); + } + }).visit(root); + return componentsByRef; + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStepTest.java index 4f67ac3b60c4..9f681bc0a10f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/BuildComponentTreeStepTest.java @@ -254,7 +254,7 @@ public void return_existing_uuids_when_components_were_removed() { ComponentDto project = insertComponent(newProjectDto("ABCD").setKey(REPORT_PROJECT_KEY)); ComponentDto removedModule = insertComponent(newModuleDto("BCDE", project).setKey(REPORT_MODULE_KEY).setEnabled(false)); ComponentDto removedDirectory = insertComponent(newDirectory(removedModule, "CDEF", REPORT_DIR_KEY_1).setKey(REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1).setEnabled(false)); - insertComponent(newFileDto(removedModule, removedModule, "DEFG").setKey(REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1).setEnabled(false)); + insertComponent(newFileDto(removedModule, removedDirectory, "DEFG").setKey(REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1).setEnabled(false)); reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF)); reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));