From: Sébastien Lesaint Date: Thu, 29 Aug 2019 13:27:53 +0000 (+0200) Subject: use testFixtures instead of test configuration of ce-task-projectanalysis X-Git-Tag: 8.0~172 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7a1b1d1728ae111910f2fc3eee6f6857f9bf526b;p=sonarqube.git use testFixtures instead of test configuration of ce-task-projectanalysis --- diff --git a/server/sonar-ce-task-projectanalysis/build.gradle b/server/sonar-ce-task-projectanalysis/build.gradle index 99971d84553..b801b25a684 100644 --- a/server/sonar-ce-task-projectanalysis/build.gradle +++ b/server/sonar-ce-task-projectanalysis/build.gradle @@ -14,11 +14,6 @@ sourceSets { } } -configurations { - tests - testCompile.extendsFrom compileOnly -} - dependencies { // please keep the list grouped by configuration and ordered by name @@ -54,18 +49,14 @@ dependencies { testCompile 'org.apache.logging.log4j:log4j-core' testCompile 'org.assertj:assertj-core' testCompile 'org.assertj:assertj-guava' - testCompile 'org.mockito:mockito-core' testCompile 'org.reflections:reflections' testCompile project(':sonar-testing-harness') - testCompile testFixtures(project(':server:sonar-ce-task')) testCompile testFixtures(project(':server:sonar-server-common')) -} -task testJar(type: Jar) { - classifier = 'tests' - from sourceSets.test.output -} + testFixturesApi 'junit:junit' + testFixturesApi 'org.assertj:assertj-core' + testFixturesApi 'org.mockito:mockito-core' + testFixturesApi testFixtures(project(':server:sonar-ce-task')) -artifacts { - tests testJar + testFixturesCompileOnly 'com.google.code.findbugs:jsr305' } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/analysis/AnalysisMetadataHolderRule.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/analysis/AnalysisMetadataHolderRule.java deleted file mode 100644 index 34a2e0f3657..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/analysis/AnalysisMetadataHolderRule.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.analysis; - -import java.util.Date; -import java.util.Map; -import java.util.Optional; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import org.junit.rules.ExternalResource; -import org.sonar.ce.task.util.InitializedProperty; -import org.sonar.db.component.BranchType; -import org.sonar.db.organization.OrganizationDto; -import org.sonar.server.project.Project; -import org.sonar.server.qualityprofile.QualityProfile; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static java.util.Objects.requireNonNull; -import static org.apache.commons.lang.StringUtils.defaultIfBlank; - -public class AnalysisMetadataHolderRule extends ExternalResource implements MutableAnalysisMetadataHolder { - - private final InitializedProperty organizationsEnabled = new InitializedProperty<>(); - - private final InitializedProperty organization = new InitializedProperty<>(); - - private final InitializedProperty uuid = new InitializedProperty<>(); - - private final InitializedProperty analysisDate = new InitializedProperty<>(); - - private final InitializedProperty baseAnalysis = new InitializedProperty<>(); - - private final InitializedProperty crossProjectDuplicationEnabled = new InitializedProperty<>(); - - private final InitializedProperty branch = new InitializedProperty<>(); - - private final InitializedProperty pullRequestId = new InitializedProperty<>(); - - private final InitializedProperty project = new InitializedProperty<>(); - - private final InitializedProperty rootComponentRef = new InitializedProperty<>(); - - private final InitializedProperty> qProfilesPerLanguage = new InitializedProperty<>(); - - private final InitializedProperty> pluginsByKey = new InitializedProperty<>(); - - private final InitializedProperty scmRevision = new InitializedProperty<>(); - - @Override - public AnalysisMetadataHolderRule setOrganizationsEnabled(boolean isOrganizationsEnabled) { - this.organizationsEnabled.setProperty(isOrganizationsEnabled); - return this; - } - - @Override - public boolean isOrganizationsEnabled() { - checkState(organizationsEnabled.isInitialized(), "Organizations enabled flag has not been set"); - return organizationsEnabled.getProperty(); - } - - @Override - public AnalysisMetadataHolderRule setOrganization(Organization organization) { - requireNonNull(organization, "organization can't be null"); - this.organization.setProperty(organization); - return this; - } - - public AnalysisMetadataHolderRule setOrganizationUuid(String uuid, String defaultQualityGateUuid) { - requireNonNull(uuid, "organization uuid can't be null"); - this.organization - .setProperty(Organization.from(new OrganizationDto().setUuid(uuid).setKey("key_" + uuid).setName("name_" + uuid).setDefaultQualityGateUuid(defaultQualityGateUuid))); - return this; - } - - @Override - public Organization getOrganization() { - checkState(organization.isInitialized(), "Organization has not been set"); - return this.organization.getProperty(); - } - - @Override - public AnalysisMetadataHolderRule setUuid(String s) { - checkNotNull(s, "UUID must not be null"); - this.uuid.setProperty(s); - return this; - } - - @Override - public String getUuid() { - checkState(uuid.isInitialized(), "Analysis UUID has not been set"); - return this.uuid.getProperty(); - } - - public AnalysisMetadataHolderRule setAnalysisDate(Date date) { - checkNotNull(date, "Date must not be null"); - this.analysisDate.setProperty(date.getTime()); - return this; - } - - @Override - public AnalysisMetadataHolderRule setAnalysisDate(long date) { - checkNotNull(date, "Date must not be null"); - this.analysisDate.setProperty(date); - return this; - } - - @Override - public long getAnalysisDate() { - checkState(analysisDate.isInitialized(), "Analysis date has not been set"); - return this.analysisDate.getProperty(); - } - - @Override - public boolean hasAnalysisDateBeenSet() { - return analysisDate.isInitialized(); - } - - @Override - public boolean isFirstAnalysis() { - return getBaseAnalysis() == null; - } - - @Override - public AnalysisMetadataHolderRule setBaseAnalysis(@Nullable Analysis baseAnalysis) { - this.baseAnalysis.setProperty(baseAnalysis); - return this; - } - - @Override - @CheckForNull - public Analysis getBaseAnalysis() { - checkState(baseAnalysis.isInitialized(), "Base analysis has not been set"); - return baseAnalysis.getProperty(); - } - - @Override - public AnalysisMetadataHolderRule setCrossProjectDuplicationEnabled(boolean isCrossProjectDuplicationEnabled) { - this.crossProjectDuplicationEnabled.setProperty(isCrossProjectDuplicationEnabled); - return this; - } - - @Override - public boolean isCrossProjectDuplicationEnabled() { - checkState(crossProjectDuplicationEnabled.isInitialized(), "Cross project duplication flag has not been set"); - return crossProjectDuplicationEnabled.getProperty(); - } - - @Override - public AnalysisMetadataHolderRule setBranch(Branch branch) { - this.branch.setProperty(branch); - return this; - } - - @Override - public Branch getBranch() { - checkState(branch.isInitialized(), "Branch has not been set"); - return branch.getProperty(); - } - - @Override - public MutableAnalysisMetadataHolder setPullRequestKey(String pullRequestKey) { - this.pullRequestId.setProperty(pullRequestKey); - return this; - } - - @Override - public String getPullRequestKey() { - checkState(pullRequestId.isInitialized(), "Pull request id has not been set"); - return pullRequestId.getProperty(); - } - - @Override - public AnalysisMetadataHolderRule setProject(Project p) { - this.project.setProperty(p); - return this; - } - - @Override - public Project getProject() { - checkState(project.isInitialized(), "Project has not been set"); - return project.getProperty(); - } - - @Override - public AnalysisMetadataHolderRule setRootComponentRef(int rootComponentRef) { - this.rootComponentRef.setProperty(rootComponentRef); - return this; - } - - @Override - public int getRootComponentRef() { - checkState(rootComponentRef.isInitialized(), "Root component ref has not been set"); - return rootComponentRef.getProperty(); - } - - @Override - public AnalysisMetadataHolderRule setQProfilesByLanguage(Map qProfilesPerLanguage) { - this.qProfilesPerLanguage.setProperty(qProfilesPerLanguage); - return this; - } - - @Override - public Map getQProfilesByLanguage() { - checkState(qProfilesPerLanguage.isInitialized(), "QProfile per language has not been set"); - return qProfilesPerLanguage.getProperty(); - } - - @Override - public AnalysisMetadataHolderRule setScannerPluginsByKey(Map plugins) { - this.pluginsByKey.setProperty(plugins); - return this; - } - - @Override - public Map getScannerPluginsByKey() { - checkState(pluginsByKey.isInitialized(), "Plugins per key has not been set"); - return pluginsByKey.getProperty(); - } - - @Override - public MutableAnalysisMetadataHolder setScmRevision(@Nullable String s) { - checkState(!this.scmRevision.isInitialized(), "ScmRevisionId has already been set"); - this.scmRevision.setProperty(defaultIfBlank(s, null)); - return this; - } - - @Override - public Optional getScmRevision() { - if (!scmRevision.isInitialized()) { - return Optional.empty(); - } - return Optional.ofNullable(scmRevision.getProperty()); - } - - @Override - public boolean isShortLivingBranch() { - Branch property = this.branch.getProperty(); - return property != null && property.getType() == BranchType.SHORT; - } - - @Override - public boolean isLongLivingBranch() { - Branch property = this.branch.getProperty(); - return property != null && property.getType() == BranchType.LONG; - } - - @Override - public boolean isPullRequest() { - Branch property = this.branch.getProperty(); - return property != null && property.getType() == BranchType.PULL_REQUEST; - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/analysis/MutableAnalysisMetadataHolderRule.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/analysis/MutableAnalysisMetadataHolderRule.java deleted file mode 100644 index a622ff7cdb5..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/analysis/MutableAnalysisMetadataHolderRule.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.analysis; - -import java.util.Map; -import java.util.Optional; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import org.junit.rules.ExternalResource; -import org.sonar.core.platform.PlatformEditionProvider; -import org.sonar.server.project.Project; -import org.sonar.server.qualityprofile.QualityProfile; - -import static org.mockito.Mockito.mock; - -public class MutableAnalysisMetadataHolderRule extends ExternalResource implements MutableAnalysisMetadataHolder { - - private PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class); - private AnalysisMetadataHolderImpl delegate = new AnalysisMetadataHolderImpl(editionProvider); - - @Override - protected void after() { - delegate = new AnalysisMetadataHolderImpl(editionProvider); - } - - @Override - public boolean isOrganizationsEnabled() { - return delegate.isOrganizationsEnabled(); - } - - @Override - public MutableAnalysisMetadataHolderRule setOrganizationsEnabled(boolean isOrganizationsEnabled) { - delegate.setOrganizationsEnabled(isOrganizationsEnabled); - return this; - } - - @Override - public MutableAnalysisMetadataHolderRule setOrganization(Organization organization) { - delegate.setOrganization(organization); - return this; - } - - @Override - public Organization getOrganization() { - return delegate.getOrganization(); - } - - public MutableAnalysisMetadataHolderRule setUuid(String s) { - delegate.setUuid(s); - return this; - } - - @Override - public String getUuid() { - return delegate.getUuid(); - } - - public MutableAnalysisMetadataHolderRule setAnalysisDate(long date) { - delegate.setAnalysisDate(date); - return this; - } - - @Override - public long getAnalysisDate() { - return delegate.getAnalysisDate(); - } - - @Override - public boolean hasAnalysisDateBeenSet() { - return delegate.hasAnalysisDateBeenSet(); - } - - @Override - public boolean isFirstAnalysis() { - return delegate.isFirstAnalysis(); - } - - @Override - public MutableAnalysisMetadataHolderRule setBaseAnalysis(@Nullable Analysis baseAnalysis) { - delegate.setBaseAnalysis(baseAnalysis); - return this; - } - - @Override - @CheckForNull - public Analysis getBaseAnalysis() { - return delegate.getBaseAnalysis(); - } - - @Override - public boolean isCrossProjectDuplicationEnabled() { - return delegate.isCrossProjectDuplicationEnabled(); - } - - @Override - public MutableAnalysisMetadataHolderRule setCrossProjectDuplicationEnabled(boolean isCrossProjectDuplicationEnabled) { - delegate.setCrossProjectDuplicationEnabled(isCrossProjectDuplicationEnabled); - return this; - } - - @Override - public Branch getBranch() { - return delegate.getBranch(); - } - - @Override - public MutableAnalysisMetadataHolderRule setBranch(Branch branch) { - delegate.setBranch(branch); - return this; - } - - @Override - public String getPullRequestKey() { - return delegate.getPullRequestKey(); - } - - @Override - public MutableAnalysisMetadataHolder setPullRequestKey(String pullRequestKey) { - delegate.setPullRequestKey(pullRequestKey); - return this; - } - - @Override - public MutableAnalysisMetadataHolderRule setProject(@Nullable Project project) { - delegate.setProject(project); - return this; - } - - @Override - public Project getProject() { - return delegate.getProject(); - } - - @Override - public MutableAnalysisMetadataHolderRule setRootComponentRef(int rootComponentRef) { - delegate.setRootComponentRef(rootComponentRef); - return this; - } - - @Override - public int getRootComponentRef() { - return delegate.getRootComponentRef(); - } - - @Override - public MutableAnalysisMetadataHolder setQProfilesByLanguage(Map qprofilesByLanguage) { - delegate.setQProfilesByLanguage(qprofilesByLanguage); - return this; - } - - @Override - public Map getQProfilesByLanguage() { - return delegate.getQProfilesByLanguage(); - } - - @Override - public MutableAnalysisMetadataHolder setScannerPluginsByKey(Map plugins) { - delegate.setScannerPluginsByKey(plugins); - return this; - } - - @Override - public Map getScannerPluginsByKey() { - return delegate.getScannerPluginsByKey(); - } - - - - @Override - public MutableAnalysisMetadataHolder setScmRevision(String scmRevisionId) { - delegate.setScmRevision(scmRevisionId); - return this; - } - - @Override - public Optional getScmRevision() { - return delegate.getScmRevision(); - } - - @Override - public boolean isShortLivingBranch() { - return delegate.isShortLivingBranch(); - } - - @Override - public boolean isLongLivingBranch() { - return delegate.isLongLivingBranch(); - } - - @Override - public boolean isPullRequest() { - return delegate.isPullRequest(); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/AbstractComponentProvider.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/AbstractComponentProvider.java deleted file mode 100644 index b45de74bc26..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/AbstractComponentProvider.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.component; - -import static com.google.common.base.Preconditions.checkState; - -abstract class AbstractComponentProvider implements ComponentProvider { - private boolean initialized = false; - - @Override - public void ensureInitialized() { - if (!this.initialized) { - ensureInitializedImpl(); - this.initialized = true; - } - } - - protected abstract void ensureInitializedImpl(); - - @Override - public void reset() { - resetImpl(); - this.initialized = false; - } - - protected abstract void resetImpl(); - - @Override - public Component getByRef(int componentRef) { - checkState(this.initialized, "%s has not been initialized", getClass().getSimpleName()); - return getByRefImpl(componentRef); - } - - protected abstract Component getByRefImpl(int componentRef); -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ComponentProvider.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ComponentProvider.java deleted file mode 100644 index 7d042647b07..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ComponentProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.component; - -public interface ComponentProvider { - /** - * does nothing if already initialized - */ - void ensureInitialized(); - - void reset(); - - /** - * @throws IllegalStateException if no component is found for the specified ref - * @throws IllegalStateException if provider has not been initialized - */ - Component getByRef(int componentRef); -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MutableTreeRootHolderRule.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MutableTreeRootHolderRule.java deleted file mode 100644 index 506a4e2ee2e..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/MutableTreeRootHolderRule.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.component; - -public class MutableTreeRootHolderRule extends TreeRootHolderRule implements MutableTreeRootHolder { - @Override - public MutableTreeRootHolderRule setRoots(Component root, Component reportRoot) { - delegate.setRoots(root, reportRoot); - return this; - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/NoComponentProvider.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/NoComponentProvider.java deleted file mode 100644 index 670b57d2efd..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/NoComponentProvider.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.component; - -public enum NoComponentProvider implements ComponentProvider { - INSTANCE; - - private static final String ERROR_MSG = "Can not add a measure by Component ref if MeasureRepositoryRule has not been created for some Component provider"; - - @Override - public void ensureInitialized() { - throw new IllegalStateException(ERROR_MSG); - } - - @Override - public void reset() { - // do nothing - } - - @Override - public Component getByRef(int componentRef) { - throw new IllegalStateException(ERROR_MSG); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ReportComponent.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ReportComponent.java deleted file mode 100644 index 0b10c06c7bb..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ReportComponent.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.component; - -import com.google.common.collect.ImmutableList; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; -import static java.util.Arrays.asList; -import static java.util.Objects.requireNonNull; - -/** - * Implementation of {@link Component} to unit test report components. - */ -public class ReportComponent implements Component { - - private static final FileAttributes DEFAULT_FILE_ATTRIBUTES = new FileAttributes(false, null, 1); - - public static final Component DUMB_PROJECT = builder(Type.PROJECT, 1) - .setKey("PROJECT_KEY") - .setPublicKey("PUBLIC_PROJECT_KEY") - .setUuid("PROJECT_UUID") - .setName("Project Name") - .setProjectVersion("1.0-SNAPSHOT") - .build(); - - private final Type type; - private final Status status; - private final String name; - private final String shortName; - @CheckForNull - private final String description; - private final String key; - private final String publicKey; - private final String uuid; - private final ProjectAttributes projectAttributes; - private final ReportAttributes reportAttributes; - private final FileAttributes fileAttributes; - private final List children; - - private ReportComponent(Builder builder) { - this.type = builder.type; - this.status = builder.status; - this.key = builder.key; - this.publicKey = builder.publicKey; - this.name = builder.name == null ? String.valueOf(builder.key) : builder.name; - this.shortName = builder.shortName == null ? this.name : builder.shortName; - this.description = builder.description; - this.uuid = builder.uuid; - this.projectAttributes = Optional.ofNullable(builder.projectVersion) - .map(v -> new ProjectAttributes(v, builder.buildString, builder.scmRevisionId)) - .orElse(null); - this.reportAttributes = ReportAttributes.newBuilder(builder.ref) - .build(); - this.fileAttributes = builder.fileAttributes == null ? DEFAULT_FILE_ATTRIBUTES : builder.fileAttributes; - this.children = ImmutableList.copyOf(builder.children); - } - - @Override - public Type getType() { - return type; - } - - @Override - public Status getStatus() { - return status; - } - - @Override - public String getUuid() { - if (uuid == null) { - throw new UnsupportedOperationException(String.format("Component uuid of ref '%d' has not be fed yet", this.reportAttributes.getRef())); - } - return uuid; - } - - @Override - public String getDbKey() { - if (key == null) { - throw new UnsupportedOperationException(String.format("Component key of ref '%d' has not be fed yet", this.reportAttributes.getRef())); - } - return key; - } - - @Override - public String getKey() { - if (publicKey == null) { - throw new UnsupportedOperationException(String.format("Component key of ref '%d' has not be fed yet", this.reportAttributes.getRef())); - } - return publicKey; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String getShortName() { - return this.shortName; - } - - @Override - @CheckForNull - public String getDescription() { - return this.description; - } - - @Override - public List getChildren() { - return children; - } - - @Override - public ProjectAttributes getProjectAttributes() { - checkState(this.type == Type.PROJECT); - return this.projectAttributes; - } - - @Override - public ReportAttributes getReportAttributes() { - return this.reportAttributes; - } - - @Override - public FileAttributes getFileAttributes() { - checkState(this.type == Type.FILE, "Only component of type FILE can have a FileAttributes object"); - return this.fileAttributes; - } - - @Override - public ProjectViewAttributes getProjectViewAttributes() { - throw new IllegalStateException("Only component of type PROJECT_VIEW can have a ProjectViewAttributes object"); - } - - @Override - public SubViewAttributes getSubViewAttributes() { - throw new IllegalStateException("Only component of type SUBVIEW have a SubViewAttributes object"); - } - - @Override - public ViewAttributes getViewAttributes() { - throw new IllegalStateException("Only component of type VIEW have a ViewAttributes object"); - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ReportComponent that = (ReportComponent) o; - return uuid.equals(that.uuid); - } - - @Override - public int hashCode() { - return uuid.hashCode(); - } - - @Override - public String toString() { - return "ReportComponent{" + - "ref=" + this.reportAttributes.getRef() + - ", key='" + key + '\'' + - ", type=" + type + - '}'; - } - - public static Builder builder(Type type, int ref) { - String key = "key_" + ref; - return new Builder(type, ref).setKey(key).setPublicKey(key).setUuid("uuid_" + ref).setName("name_" + ref); - } - - public static final class Builder { - private final Type type; - private final int ref; - private Status status; - private String uuid; - private String key; - private String publicKey; - private String name; - private String shortName; - private String projectVersion; - private String buildString; - private String scmRevisionId; - private String description; - private FileAttributes fileAttributes; - private final List children = new ArrayList<>(); - - private Builder(Type type, int ref) { - checkArgument(type.isReportType(), "Component type must be a report type"); - this.type = type; - this.ref = ref; - if (type == Type.PROJECT) { - this.projectVersion = "toBeDefined"; - } - } - - public Builder setStatus(Status s) { - this.status = requireNonNull(s); - return this; - } - - public Builder setUuid(String s) { - this.uuid = requireNonNull(s); - return this; - } - - public Builder setName(@Nullable String s) { - this.name = s; - return this; - } - - public Builder setShortName(@Nullable String s) { - this.shortName = s; - return this; - } - - public Builder setKey(String s) { - this.key = requireNonNull(s); - return this; - } - - public Builder setPublicKey(String publicKey) { - this.publicKey = requireNonNull(publicKey); - return this; - } - - public Builder setProjectVersion(@Nullable String s) { - checkProjectVersion(s); - this.projectVersion = s; - return this; - } - - public Builder setBuildString(@Nullable String buildString) { - checkBuildString(buildString); - this.buildString = buildString; - return this; - } - - public Builder setScmRevisionId(@Nullable String scmRevisionId) { - this.scmRevisionId = scmRevisionId; - return this; - } - - public Builder setFileAttributes(FileAttributes fileAttributes) { - checkState(type == Type.FILE, "Only Component of type File can have File attributes"); - this.fileAttributes = fileAttributes; - return this; - } - - public Builder setDescription(@Nullable String description) { - this.description = description; - return this; - } - - public Builder addChildren(Component... c) { - for (Component component : c) { - checkArgument(component.getType().isReportType()); - } - this.children.addAll(asList(c)); - return this; - } - - public ReportComponent build() { - checkProjectVersion(this.projectVersion); - checkBuildString(this.buildString); - return new ReportComponent(this); - } - - private void checkProjectVersion(@Nullable String s) { - checkArgument(type != Type.PROJECT ^ s != null, "Project version must and can only be set on Project"); - } - - private void checkBuildString(@Nullable String s) { - checkArgument(type == Type.PROJECT || s == null, "BuildString can only be set on Project"); - } - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/TreeComponentProvider.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/TreeComponentProvider.java deleted file mode 100644 index 10ebd61aeb7..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/TreeComponentProvider.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.component; - -import java.util.HashMap; -import java.util.Map; - -import static com.google.common.base.Preconditions.checkState; - -public final class TreeComponentProvider extends AbstractComponentProvider { - private final Component root; - private final Map componentsByRef = new HashMap<>(); - - public TreeComponentProvider(Component root) { - this.root = root; - ensureInitialized(); - } - - private static String getRef(Component component) { - return component.getType().isReportType() ? String.valueOf(component.getReportAttributes().getRef()) : component.getDbKey(); - } - - @Override - protected void ensureInitializedImpl() { - new DepthTraversalTypeAwareCrawler( - new TypeAwareVisitorAdapter(CrawlerDepthLimit.LEAVES, ComponentVisitor.Order.PRE_ORDER) { - @Override - public void visitAny(Component component) { - String ref = getRef(component); - checkState(!componentsByRef.containsKey(ref), "Tree contains more than one component with ref " + ref); - componentsByRef.put(ref, component); - } - }).visit(root); - } - - @Override - protected void resetImpl() { - // we can not reset - } - - @Override - protected Component getByRefImpl(int componentRef) { - Component component = componentsByRef.get(String.valueOf(componentRef)); - checkState(component != null, "Can not find Component for ref " + componentRef); - return component; - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderComponentProvider.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderComponentProvider.java deleted file mode 100644 index da7eae0c878..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderComponentProvider.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.component; - -public final class TreeRootHolderComponentProvider extends AbstractComponentProvider { - private final TreeRootHolder treeRootHolder; - private TreeComponentProvider delegate; - - public TreeRootHolderComponentProvider(TreeRootHolder treeRootHolder) { - this.treeRootHolder = treeRootHolder; - } - - @Override - protected void ensureInitializedImpl() { - if (this.delegate == null) { - this.delegate = new TreeComponentProvider(treeRootHolder.getRoot()); - this.delegate.ensureInitialized(); - } - } - - @Override - protected void resetImpl() { - this.delegate = null; - } - - @Override - protected Component getByRefImpl(int componentRef) { - return delegate.getByRef(componentRef); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderRule.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderRule.java deleted file mode 100644 index bfdaa2fff06..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderRule.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.component; - -import java.util.Optional; -import org.junit.rules.ExternalResource; - -public class TreeRootHolderRule extends ExternalResource implements TreeRootHolder { - protected TreeRootHolderImpl delegate = new TreeRootHolderImpl(); - - @Override - protected void after() { - this.delegate = null; - } - - public TreeRootHolderRule setRoot(Component root) { - return setRoots(root, root); - } - - public TreeRootHolderRule setRoots(Component root, Component reportRoot) { - delegate = new TreeRootHolderImpl(); - delegate.setRoots(root, reportRoot); - return this; - } - - @Override - public boolean isEmpty() { - return delegate.isEmpty(); - } - - @Override - public Component getRoot() { - return delegate.getRoot(); - } - - @Override - public Component getReportTreeRoot() { - return delegate.getReportTreeRoot(); - } - - @Override - public Component getComponentByRef(int ref) { - return delegate.getComponentByRef(ref); - } - - @Override - public Optional getOptionalComponentByRef(int ref) { - return delegate.getOptionalComponentByRef(ref); - } - - @Override public Component getReportTreeComponentByRef(int ref) { - return delegate.getReportTreeComponentByRef(ref); - } - - @Override - public int getSize() { - return delegate.getSize(); - } - -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ViewsComponent.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ViewsComponent.java deleted file mode 100644 index a8f5afb35dd..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ViewsComponent.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.component; - -import com.google.common.collect.ImmutableList; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; -import static java.util.Arrays.asList; -import static java.util.Objects.requireNonNull; - -/** - * Implementation of {@link Component} to unit test views components. - */ -public class ViewsComponent implements Component { - private final Type type; - private final String key; - private final String uuid; - private final String name; - private final String description; - private final List children; - private final ProjectViewAttributes projectViewAttributes; - private final SubViewAttributes subViewAttributes; - private final ViewAttributes viewAttributes; - - private ViewsComponent(Type type, String key, @Nullable String uuid, @Nullable String name, @Nullable String description, - List children, @Nullable ProjectViewAttributes projectViewAttributes, @Nullable SubViewAttributes subViewAttributes, - @Nullable ViewAttributes viewAttributes) { - checkArgument(type.isViewsType(), "Component type must be a Views type"); - this.type = type; - this.key = requireNonNull(key); - this.uuid = uuid; - this.name = name; - this.description = description; - this.children = ImmutableList.copyOf(children); - this.projectViewAttributes = projectViewAttributes; - this.subViewAttributes = subViewAttributes; - this.viewAttributes = viewAttributes; - } - - public static Builder builder(Type type, String key) { - return new Builder(type, key); - } - - public static Builder builder(Type type, int key) { - return new Builder(type, String.valueOf(key)); - } - - public static final class Builder { - private final Type type; - private String key; - private String uuid; - private String name; - private String description; - private List children = new ArrayList<>(); - private ProjectViewAttributes projectViewAttributes; - private SubViewAttributes subViewAttributes; - private ViewAttributes viewAttributes; - - private Builder(Type type, String key) { - this.type = type; - this.key = key; - } - - public Builder setUuid(@Nullable String uuid) { - this.uuid = uuid; - return this; - } - - public Builder setKey(String key) { - this.key = key; - return this; - } - - public Builder setName(@Nullable String name) { - this.name = name; - return this; - } - - public Builder setDescription(String description) { - this.description = description; - return this; - } - - public Builder setChildren(List children) { - this.children = children; - return this; - } - - public Builder setProjectViewAttributes(@Nullable ProjectViewAttributes projectViewAttributes) { - this.projectViewAttributes = projectViewAttributes; - return this; - } - - public Builder setSubViewAttributes(@Nullable SubViewAttributes subViewAttributes) { - this.subViewAttributes = subViewAttributes; - return this; - } - - public Builder setViewAttributes(@Nullable ViewAttributes viewAttributes) { - this.viewAttributes = viewAttributes; - return this; - } - - public Builder addChildren(Component... c) { - for (Component viewsComponent : c) { - checkArgument(viewsComponent.getType().isViewsType()); - } - this.children.addAll(asList(c)); - return this; - } - - public ViewsComponent build() { - return new ViewsComponent(type, key, uuid, name, description, children, projectViewAttributes, subViewAttributes, viewAttributes); - } - } - - @Override - public Type getType() { - return type; - } - - @Override - public Status getStatus() { - return Status.UNAVAILABLE; - } - - @Override - public String getUuid() { - return uuid; - } - - @Override - public String getDbKey() { - return key; - } - - /** - * Views has no branch feature, the public key is the same as the key - */ - @Override - public String getKey() { - return getDbKey(); - } - - @Override - public String getName() { - checkState(this.name != null, "No name has been set"); - return this.name; - } - - @Override - public String getShortName() { - return getName(); - } - - @Override - @CheckForNull - public String getDescription() { - return this.description; - } - - @Override - public List getChildren() { - return children; - } - - @Override - public ProjectAttributes getProjectAttributes() { - throw new IllegalStateException("A component of type " + type + " does not have project attributes"); - } - - @Override - public ReportAttributes getReportAttributes() { - throw new IllegalStateException("A component of type " + type + " does not have report attributes"); - } - - @Override - public FileAttributes getFileAttributes() { - throw new IllegalStateException("A component of type " + type + " does not have file attributes"); - } - - @Override - public ProjectViewAttributes getProjectViewAttributes() { - checkState(this.type != Type.PROJECT_VIEW || this.projectViewAttributes != null, "A ProjectViewAttribute object should have been set"); - return this.projectViewAttributes; - } - - @Override - public SubViewAttributes getSubViewAttributes() { - checkState(this.type != Type.SUBVIEW || this.subViewAttributes != null, "A SubViewAttributes object should have been set"); - return this.subViewAttributes; - } - - @Override - public ViewAttributes getViewAttributes() { - checkState(this.type != Type.VIEW || this.viewAttributes != null, "A ViewAttributes object should have been set"); - return viewAttributes; - } - - @Override - public String toString() { - return "ViewsComponent{" + - "type=" + type + - ", key='" + key + '\'' + - ", uuid='" + uuid + '\'' + - ", name='" + name + '\'' + - ", children=" + children + - ", projectViewAttributes=" + projectViewAttributes + - ", subViewAttributes=" + subViewAttributes + - ", viewAttributes=" + viewAttributes + - '}'; - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ViewsComponent that = (ViewsComponent) o; - return key.equals(that.key); - } - - @Override - public int hashCode() { - return Objects.hash(key); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureAssert.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureAssert.java deleted file mode 100644 index 7b8d2eaa2bc..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureAssert.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.measure; - -import java.util.Objects; -import java.util.Optional; -import javax.annotation.Nullable; -import org.assertj.core.api.AbstractAssert; -import org.assertj.core.data.Offset; - -import static java.lang.Math.abs; - -public class MeasureAssert extends AbstractAssert { - - protected MeasureAssert(@Nullable Measure actual) { - super(actual, MeasureAssert.class); - } - - public static MeasureAssert assertThat(Measure actual) { - return new MeasureAssert(actual); - } - - public static MeasureAssert assertThat(@Nullable Optional actual) { - return new MeasureAssert(actual == null ? null : actual.orElse(null)); - } - - public MeasureAssert hasValueType(Measure.ValueType expected) { - isNotNull(); - - if (actual.getValueType() != expected) { - failWithMessage("Expected ValueType of Measure to be <%s> but was <%s>", expected, actual.getValueType()); - } - - return this; - } - - public MeasureAssert hasValue(int expected) { - isNotNull(); - - if (actual.getValueType() != Measure.ValueType.INT) { - failWithMessage( - "Expected Measure to have an int value and therefore its ValueType to be <%s> but was <%s>", - Measure.ValueType.INT, actual.getValueType()); - } - - if (actual.getIntValue() != expected) { - failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getIntValue()); - } - - return this; - } - - public MeasureAssert hasValue(long expected) { - isNotNull(); - - if (actual.getValueType() != Measure.ValueType.LONG) { - failWithMessage( - "Expected Measure to have a long value and therefore its ValueType to be <%s> but was <%s>", - Measure.ValueType.LONG, actual.getValueType()); - } - - if (actual.getLongValue() != expected) { - failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getLongValue()); - } - - return this; - } - - public MeasureAssert hasValue(double expected) { - isNotNull(); - - if (actual.getValueType() != Measure.ValueType.DOUBLE) { - failWithMessage( - "Expected Measure to have a double value and therefore its ValueType to be <%s> but was <%s>", - Measure.ValueType.DOUBLE, actual.getValueType()); - } - - if (actual.getDoubleValue() != expected) { - failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getDoubleValue()); - } - - return this; - } - - public MeasureAssert hasValue(boolean expected) { - isNotNull(); - - if (actual.getValueType() != Measure.ValueType.BOOLEAN) { - failWithMessage( - "Expected Measure to have a boolean value and therefore its ValueType to be <%s> but was <%s>", - Measure.ValueType.DOUBLE, actual.getValueType()); - } - - if (actual.getBooleanValue() != expected) { - failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getBooleanValue()); - } - - return this; - } - - public MeasureAssert hasValue(String expected) { - isNotNull(); - - if (actual.getValueType() != Measure.ValueType.STRING) { - failWithMessage( - "Expected Measure to have a String value and therefore its ValueType to be <%s> but was <%s>", - Measure.ValueType.DOUBLE, actual.getValueType()); - } - - if (!Objects.equals(actual.getStringValue(), expected)) { - failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getStringValue()); - } - - return this; - } - - public MeasureAssert hasValue(Measure.Level expected) { - isNotNull(); - - if (actual.getValueType() != Measure.ValueType.LEVEL) { - failWithMessage( - "Expected Measure to have a Level value and therefore its ValueType to be <%s> but was <%s>", - Measure.ValueType.DOUBLE, actual.getValueType()); - } - - if (actual.getLevelValue() != expected) { - failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getLevelValue()); - } - - return this; - } - - public MeasureAssert hasNoValue() { - isNotNull(); - - if (actual.getValueType() != Measure.ValueType.NO_VALUE) { - failWithMessage( - "Expected Measure to have no value and therefore its ValueType to be <%s> but was <%s>", - Measure.ValueType.DOUBLE, actual.getValueType()); - } - - return this; - } - - public MeasureAssert hasData(String expected) { - isNotNull(); - - if (!Objects.equals(actual.getData(), expected)) { - failWithMessage("Expected data of Measure to be <%s> but was <%s>", expected, actual.getData()); - } - - return this; - } - - public MeasureAssert hasNoData() { - isNotNull(); - - if (actual.getData() == null) { - failWithMessage("Expected Measure to have no data but was <%s>", actual.getData()); - } - - return this; - } - - public MeasureAssert hasQualityGateLevel(Measure.Level expected) { - isNotNull(); - hasQualityGateStatus(); - - if (actual.getQualityGateStatus().getStatus() != expected) { - failWithMessage("Expected Level of QualityGateStatus of Measure to be <%s> but was <%s>", expected, actual.getQualityGateStatus().getStatus()); - } - - return this; - } - - public MeasureAssert hasQualityGateText(String expected) { - isNotNull(); - hasQualityGateStatus(); - - if (!Objects.equals(actual.getQualityGateStatus().getText(), expected)) { - failWithMessage("Expected text of QualityGateStatus of Measure to be \n<%s>\n but was \n<%s>", expected, actual.getQualityGateStatus().getText()); - } - - return this; - } - - private void hasQualityGateStatus() { - if (!actual.hasQualityGateStatus()) { - failWithMessage("Expected Measure to have a QualityGateStatus but it did not"); - } - } - - public MeasureAssert hasVariation(double expected) { - isNotNull(); - hasVariation(); - - if (!actual.hasVariation()) { - failWithMessage("Expected Measure to have a variation but it did not"); - } - - double variation = actual.getVariation(); - if (variation != expected) { - failWithMessage("Expected variation of Measure to be <%s> but was <%s>", expected, variation); - } - - return this; - } - - public MeasureAssert hasVariation(double expected, Offset offset) { - isNotNull(); - hasVariation(); - - if (!actual.hasVariation()) { - failWithMessage("Expected Measure to have a variation but it did not"); - } - - double variation = actual.getVariation(); - if (abs(expected - variation) > offset.value) { - failWithMessage( - "Expected variation of Measure to be close to <%s> by less than <%s> but was <%s>", - expected, offset.value, variation); - } - - return this; - } - - private void hasVariation() { - if (!actual.hasVariation()) { - failWithMessage("Expected Measure to have a variation but it did not"); - } - } - - public void isAbsent() { - if (actual != null) { - failWithMessage("Expected measure to be absent"); - } - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepoEntry.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepoEntry.java deleted file mode 100644 index 2cf7fc130c6..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepoEntry.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.measure; - -import com.google.common.base.Function; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.SetMultimap; -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.Map; -import java.util.Objects; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.sonar.ce.task.projectanalysis.component.Component; - -/** - * This class represents a metric key and an associated measure. - * It can be used to easily compare the content of the SetMultimap returned by {@link MeasureRepository#getRawMeasures(Component)} - * or {@link MeasureRepositoryRule#getAddedRawMeasures(int)}. - *

- * This class is also highly useful to accurately make sure of the SetMultimap content since this - * object implements a deep equals of Measure objects (see {@link #deepEquals(Measure, Measure)}), when - * {@link Measure#equals(Object)} only care about the ruleId and characteristicId. - *

- *

- * In order to explore the content of the SetMultimap, use {@link #toEntries(SetMultimap)} to convert it - * to an Iterable of {@link MeasureRepoEntry} and then take benefit of AssertJ API, eg.: - *

- * assertThat(MeasureRepoEntry.toEntries(measureRepository.getAddedRawMeasures(componentRef))).containsOnly(
- *   MeasureRepoEntry.entryOf(DEVELOPMENT_COST_KEY, newMeasureBuilder().create(Long.toString(expectedDevCost))),
- *   MeasureRepoEntry.entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(expectedDebtRatio))
- * );
- * 
- *

- */ -public final class MeasureRepoEntry { - private final String metricKey; - private final Measure measure; - - public MeasureRepoEntry(String metricKey, Measure measure) { - this.metricKey = metricKey; - this.measure = measure; - } - - public static Function, MeasureRepoEntry> toMeasureRepoEntry() { - return EntryToMeasureRepoEntry.INSTANCE; - } - - public static Iterable toEntries(SetMultimap data) { - return FluentIterable.from(data.entries()).transform(toMeasureRepoEntry()).toList(); - } - - public static MeasureRepoEntry entryOf(String metricKey, Measure measure) { - return new MeasureRepoEntry(metricKey, measure); - } - - public static boolean deepEquals(Measure measure, Measure measure1) { - return measure.getValueType() == measure1.getValueType() - && equalsByValue(measure, measure1) - && equalsByVariation(measure, measure1) - && equalsByQualityGateStatus(measure, measure1) - && Objects.equals(measure.getData(), measure1.getData()); - } - - private static boolean equalsByValue(Measure measure, Measure measure1) { - switch (measure.getValueType()) { - case BOOLEAN: - return measure.getBooleanValue() == measure1.getBooleanValue(); - case INT: - return measure.getIntValue() == measure1.getIntValue(); - case LONG: - return measure.getLongValue() == measure1.getLongValue(); - case DOUBLE: - return Double.compare(measure.getDoubleValue(), measure1.getDoubleValue()) == 0; - case STRING: - return measure.getStringValue().equals(measure1.getStringValue()); - case LEVEL: - return measure.getLevelValue() == measure1.getLevelValue(); - case NO_VALUE: - return true; - default: - throw new IllegalArgumentException("Unsupported ValueType " + measure.getValueType()); - } - } - - private static boolean equalsByVariation(Measure measure, Measure measure1) { - return measure.hasVariation() == measure1.hasVariation() && (!measure.hasVariation() - || Double.compare(scale(measure.getVariation()), scale(measure1.getVariation())) == 0); - } - - private static final int DOUBLE_PRECISION = 1; - - private static double scale(double value) { - BigDecimal bd = BigDecimal.valueOf(value); - return bd.setScale(DOUBLE_PRECISION, RoundingMode.HALF_UP).doubleValue(); - } - - private static boolean equalsByQualityGateStatus(Measure measure, Measure measure1) { - if (measure.hasQualityGateStatus() != measure1.hasQualityGateStatus()) { - return false; - } - if (!measure.hasQualityGateStatus()) { - return true; - } - return Objects.equals(measure.getQualityGateStatus(), measure1.getQualityGateStatus()); - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - MeasureRepoEntry that = (MeasureRepoEntry) o; - return Objects.equals(metricKey, that.metricKey) && - deepEquals(measure, that.measure); - } - - @Override - public int hashCode() { - return Objects.hash(metricKey, measure); - } - - @Override - public String toString() { - return "<" + metricKey + ", " + measure + '>'; - } - - private enum EntryToMeasureRepoEntry implements Function, MeasureRepoEntry> { - INSTANCE; - - @Nullable - @Override - public MeasureRepoEntry apply(@Nonnull Map.Entry input) { - return new MeasureRepoEntry(input.getKey(), input.getValue()); - } - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepositoryRule.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepositoryRule.java deleted file mode 100644 index 2c579151024..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepositoryRule.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.measure; - -import com.google.common.base.Function; -import com.google.common.base.Predicate; -import com.google.common.collect.ImmutableSetMultimap; -import com.google.common.collect.SetMultimap; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import javax.annotation.CheckForNull; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.junit.rules.ExternalResource; -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.ComponentProvider; -import org.sonar.ce.task.projectanalysis.component.NoComponentProvider; -import org.sonar.ce.task.projectanalysis.component.TreeComponentProvider; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolderComponentProvider; -import org.sonar.ce.task.projectanalysis.metric.Metric; -import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.collect.FluentIterable.from; -import static com.google.common.collect.Maps.filterKeys; -import static java.lang.String.format; -import static java.util.Objects.requireNonNull; - -/** - * An implementation of MeasureRepository as a JUnit rule which provides add methods for raw measures and extra add - * methods that takes component ref and metric keys thanks to the integration with various Component and Metric - * providers. - */ -public class MeasureRepositoryRule extends ExternalResource implements MeasureRepository { - private final ComponentProvider componentProvider; - @CheckForNull - private final MetricRepositoryRule metricRepositoryRule; - private final Map baseMeasures = new HashMap<>(); - private final Map rawMeasures = new HashMap<>(); - private final Map initialRawMeasures = new HashMap<>(); - private final Predicate> isAddedMeasure = input -> !initialRawMeasures.containsKey(input.getKey()) - || !MeasureRepoEntry.deepEquals(input.getValue(), initialRawMeasures.get(input.getKey())); - - private MeasureRepositoryRule(ComponentProvider componentProvider, @Nullable MetricRepositoryRule metricRepositoryRule) { - this.componentProvider = componentProvider; - this.metricRepositoryRule = metricRepositoryRule; - } - - @Override - protected void after() { - componentProvider.reset(); - baseMeasures.clear(); - rawMeasures.clear(); - } - - public static MeasureRepositoryRule create() { - return new MeasureRepositoryRule(NoComponentProvider.INSTANCE, null); - } - - public static MeasureRepositoryRule create(TreeRootHolder treeRootHolder, MetricRepositoryRule metricRepositoryRule) { - return new MeasureRepositoryRule(new TreeRootHolderComponentProvider(treeRootHolder), requireNonNull(metricRepositoryRule)); - } - - public static MeasureRepositoryRule create(Component treeRoot, MetricRepositoryRule metricRepositoryRule) { - return new MeasureRepositoryRule(new TreeComponentProvider(treeRoot), requireNonNull(metricRepositoryRule)); - } - - public MeasureRepositoryRule addBaseMeasure(int componentRef, String metricKey, Measure measure) { - checkAndInitProvidersState(); - - InternalKey internalKey = new InternalKey(componentProvider.getByRef(componentRef), metricRepositoryRule.getByKey(metricKey)); - checkState(!baseMeasures.containsKey(internalKey), format("Can not add a BaseMeasure twice for a Component (ref=%s) and Metric (key=%s)", componentRef, metricKey)); - - baseMeasures.put(internalKey, measure); - - return this; - } - - public SetMultimap getRawMeasures(int componentRef) { - return getRawMeasures(componentProvider.getByRef(componentRef)); - } - - /** - * Return measures that were added by the step (using {@link #add(Component, Metric, Measure)}). - * It does not contain the one added in the test by {@link #addRawMeasure(int, String, Measure)} - */ - public SetMultimap getAddedRawMeasures(int componentRef) { - checkAndInitProvidersState(); - - return getAddedRawMeasures(componentProvider.getByRef(componentRef)); - } - - /** - * Return a measure that were added by the step (using {@link #add(Component, Metric, Measure)}). - * It does not contain the one added in the test by {@link #addRawMeasure(int, String, Measure)} - */ - public Optional getAddedRawMeasure(Component component, String metricKey) { - return getAddedRawMeasure(component.getReportAttributes().getRef(), metricKey); - } - - /** - * Return a measure that were added by the step (using {@link #add(Component, Metric, Measure)}). - * It does not contain the one added in the test by {@link #addRawMeasure(int, String, Measure)} - */ - public Optional getAddedRawMeasure(int componentRef, String metricKey) { - checkAndInitProvidersState(); - - Set measures = getAddedRawMeasures(componentProvider.getByRef(componentRef)).get(metricKey); - if (measures.isEmpty()) { - return Optional.empty(); - } - checkArgument(measures.size() == 1, String.format("There is more than one measure on metric '%s' for component '%s'", metricKey, componentRef)); - return Optional.of(measures.iterator().next()); - } - - /** - * Return measures that were added by the step (using {@link #add(Component, Metric, Measure)}). - * It does not contain the one added in the test by {@link #addRawMeasure(int, String, Measure)} - */ - public SetMultimap getAddedRawMeasures(Component component) { - checkAndInitProvidersState(); - - ImmutableSetMultimap.Builder builder = ImmutableSetMultimap.builder(); - for (Map.Entry entry : from(filterKeys(rawMeasures, hasComponentRef(component)).entrySet()).filter(isAddedMeasure)) { - builder.put(entry.getKey().getMetricKey(), entry.getValue()); - } - return builder.build(); - } - - public MeasureRepositoryRule addRawMeasure(int componentRef, String metricKey, Measure measure) { - checkAndInitProvidersState(); - - InternalKey internalKey = new InternalKey(componentProvider.getByRef(componentRef), metricRepositoryRule.getByKey(metricKey)); - checkState(!rawMeasures.containsKey(internalKey), format( - "A measure can only be set once for Component (ref=%s), Metric (key=%s)", - componentRef, metricKey)); - - rawMeasures.put(internalKey, measure); - initialRawMeasures.put(internalKey, measure); - - return this; - } - - @Override - public Optional getBaseMeasure(Component component, Metric metric) { - return Optional.ofNullable(baseMeasures.get(new InternalKey(component, metric))); - } - - @Override - public Optional getRawMeasure(Component component, Metric metric) { - return Optional.ofNullable(rawMeasures.get(new InternalKey(component, metric))); - } - - @Override - public Set getRawMeasures(Component component, Metric metric) { - return from(filterKeys(rawMeasures, hasComponentRef(component)).entrySet()).filter(new MatchMetric(metric)).transform(ToMeasure.INSTANCE).toSet(); - } - - @Override - public SetMultimap getRawMeasures(Component component) { - ImmutableSetMultimap.Builder builder = ImmutableSetMultimap.builder(); - for (Map.Entry entry : filterKeys(rawMeasures, hasComponentRef(component)).entrySet()) { - builder.put(entry.getKey().getMetricKey(), entry.getValue()); - } - return builder.build(); - } - - private HasComponentRefPredicate hasComponentRef(Component component) { - return new HasComponentRefPredicate(component); - } - - @Override - public void add(Component component, Metric metric, Measure measure) { - String ref = getRef(component); - InternalKey internalKey = new InternalKey(ref, metric.getKey()); - if (rawMeasures.containsKey(internalKey)) { - throw new UnsupportedOperationException(format( - "A measure can only be set once for Component (ref=%s), Metric (key=%s)", - ref, metric.getKey())); - } - rawMeasures.put(internalKey, measure); - } - - @Override - public void update(Component component, Metric metric, Measure measure) { - String componentRef = getRef(component); - InternalKey internalKey = new InternalKey(componentRef, metric.getKey()); - if (!rawMeasures.containsKey(internalKey)) { - throw new UnsupportedOperationException(format( - "A measure can only be updated if it has been added first for Component (ref=%s), Metric (key=%s)", - componentRef, metric.getKey())); - } - rawMeasures.put(internalKey, measure); - } - - private void checkAndInitProvidersState() { - checkState(metricRepositoryRule != null, "Can not add a measure by metric key if MeasureRepositoryRule has not been created for a MetricRepository"); - componentProvider.ensureInitialized(); - } - - public boolean isEmpty() { - return rawMeasures.isEmpty(); - } - - private static final class InternalKey { - private final String componentRef; - private final String metricKey; - - public InternalKey(Component component, Metric metric) { - this(getRef(component), metric.getKey()); - } - - private InternalKey(String componentRef, String metricKey) { - this.componentRef = componentRef; - this.metricKey = metricKey; - } - - public String getComponentRef() { - return componentRef; - } - - public String getMetricKey() { - return metricKey; - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - InternalKey that = (InternalKey) o; - return Objects.equals(componentRef, that.componentRef) && - Objects.equals(metricKey, that.metricKey); - } - - @Override - public int hashCode() { - return Objects.hash(componentRef, metricKey); - } - - @Override - public String toString() { - return "InternalKey{" + - "component=" + componentRef + - ", metric='" + metricKey + '\'' + - '}'; - } - } - - private static class HasComponentRefPredicate implements Predicate { - - private final String componentRef; - - public HasComponentRefPredicate(Component component) { - this.componentRef = getRef(component); - } - - @Override - public boolean apply(@Nonnull InternalKey input) { - return input.getComponentRef().equals(this.componentRef); - } - } - - private static String getRef(Component component) { - return component.getType().isReportType() ? String.valueOf(component.getReportAttributes().getRef()) : component.getDbKey(); - } - - private static class MatchMetric implements Predicate> { - private final Metric metric; - - public MatchMetric(Metric metric) { - this.metric = metric; - } - - @Override - public boolean apply(@Nonnull Map.Entry input) { - return input.getKey().getMetricKey().equals(metric.getKey()); - } - } - - private enum ToMeasure implements Function, Measure> { - INSTANCE; - - @Nullable - @Override - public Measure apply(@Nonnull Map.Entry input) { - return input.getValue(); - } - } - -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/metric/MetricRepositoryRule.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/metric/MetricRepositoryRule.java deleted file mode 100644 index 7f781ff34b0..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/metric/MetricRepositoryRule.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.metric; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import org.junit.rules.ExternalResource; - -import static com.google.common.base.Preconditions.checkState; -import static java.lang.String.format; -import static java.util.Objects.requireNonNull; - -public class MetricRepositoryRule extends ExternalResource implements MetricRepository { - private final Map metricsByKey = new HashMap<>(); - private final Map metricsById = new HashMap<>(); - - /** - * Convenience method to add a {@link Metric} to the repository created from a {@link org.sonar.api.measures.Metric}, - * most of the time it will be a constant of the {@link org.sonar.api.measures.CoreMetrics} class. - *

- * For the id of the created metric, this method uses the hashCode of the metric's key. If you want to specify - * the id of the create {@link Metric}, use {@link #add(int, org.sonar.api.measures.Metric)} - *

- */ - public MetricRepositoryRule add(org.sonar.api.measures.Metric coreMetric) { - add(from(coreMetric)); - return this; - } - - /** - * Convenience method to add a {@link Metric} to the repository created from a {@link org.sonar.api.measures.Metric} - * and with the specified id, most of the time it will be a constant of the {@link org.sonar.api.measures.CoreMetrics} - * class. - */ - public MetricRepositoryRule add(int id, org.sonar.api.measures.Metric coreMetric) { - add(from(id, coreMetric)); - return this; - } - - private static Metric from(org.sonar.api.measures.Metric coreMetric) { - return from(coreMetric.getKey().hashCode(), coreMetric); - } - - private static Metric from(int id, org.sonar.api.measures.Metric coreMetric) { - return new MetricImpl( - id, coreMetric.getKey(), coreMetric.getName(), - convert(coreMetric.getType()), - coreMetric.getDecimalScale(), - coreMetric.getBestValue(), coreMetric.isOptimizedBestValue()); - } - - private static Metric.MetricType convert(org.sonar.api.measures.Metric.ValueType coreMetricType) { - return Metric.MetricType.valueOf(coreMetricType.name()); - } - - public MetricRepositoryRule add(Metric metric) { - requireNonNull(metric.getKey(), "key can not be null"); - requireNonNull(metric.getId(), "id can not be null"); - - checkState(!metricsByKey.containsKey(metric.getKey()), format("Repository already contains a metric for key %s", metric.getKey())); - checkState(!metricsById.containsKey((long) metric.getId()), format("Repository already contains a metric for id %s", metric.getId())); - - metricsByKey.put(metric.getKey(), metric); - metricsById.put((long) metric.getId(), metric); - - return this; - } - - @Override - protected void after() { - this.metricsById.clear(); - this.metricsById.clear(); - } - - @Override - public Metric getByKey(String key) { - Metric res = metricsByKey.get(key); - checkState(res != null, format("No Metric can be found for key %s", key)); - return res; - } - - @Override - public Metric getById(long id) { - Metric res = metricsById.get(id); - checkState(res != null, format("No Metric can be found for id %s", id)); - return res; - } - - @Override - public Optional getOptionalById(long id) { - return Optional.of(metricsById.get(id)); - } - - @Override - public Iterable getAll() { - return metricsByKey.values(); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/BaseStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/BaseStepTest.java deleted file mode 100644 index 16aed8003df..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/BaseStepTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.ce.task.projectanalysis.step; - -import org.junit.Test; -import org.sonar.ce.task.step.ComputationStep; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Temporary solution to test metadata. Should be replaced by a medium test of - * all computation stack - */ -public abstract class BaseStepTest { - - protected abstract ComputationStep step(); - - @Test - public void test_metadata() { - assertThat(step().toString()).isNotEmpty(); - assertThat(step().getDescription()).isNotEmpty(); - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/analysis/AnalysisMetadataHolderRule.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/analysis/AnalysisMetadataHolderRule.java new file mode 100644 index 00000000000..34a2e0f3657 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/analysis/AnalysisMetadataHolderRule.java @@ -0,0 +1,270 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.analysis; + +import java.util.Date; +import java.util.Map; +import java.util.Optional; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.junit.rules.ExternalResource; +import org.sonar.ce.task.util.InitializedProperty; +import org.sonar.db.component.BranchType; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.server.project.Project; +import org.sonar.server.qualityprofile.QualityProfile; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; +import static org.apache.commons.lang.StringUtils.defaultIfBlank; + +public class AnalysisMetadataHolderRule extends ExternalResource implements MutableAnalysisMetadataHolder { + + private final InitializedProperty organizationsEnabled = new InitializedProperty<>(); + + private final InitializedProperty organization = new InitializedProperty<>(); + + private final InitializedProperty uuid = new InitializedProperty<>(); + + private final InitializedProperty analysisDate = new InitializedProperty<>(); + + private final InitializedProperty baseAnalysis = new InitializedProperty<>(); + + private final InitializedProperty crossProjectDuplicationEnabled = new InitializedProperty<>(); + + private final InitializedProperty branch = new InitializedProperty<>(); + + private final InitializedProperty pullRequestId = new InitializedProperty<>(); + + private final InitializedProperty project = new InitializedProperty<>(); + + private final InitializedProperty rootComponentRef = new InitializedProperty<>(); + + private final InitializedProperty> qProfilesPerLanguage = new InitializedProperty<>(); + + private final InitializedProperty> pluginsByKey = new InitializedProperty<>(); + + private final InitializedProperty scmRevision = new InitializedProperty<>(); + + @Override + public AnalysisMetadataHolderRule setOrganizationsEnabled(boolean isOrganizationsEnabled) { + this.organizationsEnabled.setProperty(isOrganizationsEnabled); + return this; + } + + @Override + public boolean isOrganizationsEnabled() { + checkState(organizationsEnabled.isInitialized(), "Organizations enabled flag has not been set"); + return organizationsEnabled.getProperty(); + } + + @Override + public AnalysisMetadataHolderRule setOrganization(Organization organization) { + requireNonNull(organization, "organization can't be null"); + this.organization.setProperty(organization); + return this; + } + + public AnalysisMetadataHolderRule setOrganizationUuid(String uuid, String defaultQualityGateUuid) { + requireNonNull(uuid, "organization uuid can't be null"); + this.organization + .setProperty(Organization.from(new OrganizationDto().setUuid(uuid).setKey("key_" + uuid).setName("name_" + uuid).setDefaultQualityGateUuid(defaultQualityGateUuid))); + return this; + } + + @Override + public Organization getOrganization() { + checkState(organization.isInitialized(), "Organization has not been set"); + return this.organization.getProperty(); + } + + @Override + public AnalysisMetadataHolderRule setUuid(String s) { + checkNotNull(s, "UUID must not be null"); + this.uuid.setProperty(s); + return this; + } + + @Override + public String getUuid() { + checkState(uuid.isInitialized(), "Analysis UUID has not been set"); + return this.uuid.getProperty(); + } + + public AnalysisMetadataHolderRule setAnalysisDate(Date date) { + checkNotNull(date, "Date must not be null"); + this.analysisDate.setProperty(date.getTime()); + return this; + } + + @Override + public AnalysisMetadataHolderRule setAnalysisDate(long date) { + checkNotNull(date, "Date must not be null"); + this.analysisDate.setProperty(date); + return this; + } + + @Override + public long getAnalysisDate() { + checkState(analysisDate.isInitialized(), "Analysis date has not been set"); + return this.analysisDate.getProperty(); + } + + @Override + public boolean hasAnalysisDateBeenSet() { + return analysisDate.isInitialized(); + } + + @Override + public boolean isFirstAnalysis() { + return getBaseAnalysis() == null; + } + + @Override + public AnalysisMetadataHolderRule setBaseAnalysis(@Nullable Analysis baseAnalysis) { + this.baseAnalysis.setProperty(baseAnalysis); + return this; + } + + @Override + @CheckForNull + public Analysis getBaseAnalysis() { + checkState(baseAnalysis.isInitialized(), "Base analysis has not been set"); + return baseAnalysis.getProperty(); + } + + @Override + public AnalysisMetadataHolderRule setCrossProjectDuplicationEnabled(boolean isCrossProjectDuplicationEnabled) { + this.crossProjectDuplicationEnabled.setProperty(isCrossProjectDuplicationEnabled); + return this; + } + + @Override + public boolean isCrossProjectDuplicationEnabled() { + checkState(crossProjectDuplicationEnabled.isInitialized(), "Cross project duplication flag has not been set"); + return crossProjectDuplicationEnabled.getProperty(); + } + + @Override + public AnalysisMetadataHolderRule setBranch(Branch branch) { + this.branch.setProperty(branch); + return this; + } + + @Override + public Branch getBranch() { + checkState(branch.isInitialized(), "Branch has not been set"); + return branch.getProperty(); + } + + @Override + public MutableAnalysisMetadataHolder setPullRequestKey(String pullRequestKey) { + this.pullRequestId.setProperty(pullRequestKey); + return this; + } + + @Override + public String getPullRequestKey() { + checkState(pullRequestId.isInitialized(), "Pull request id has not been set"); + return pullRequestId.getProperty(); + } + + @Override + public AnalysisMetadataHolderRule setProject(Project p) { + this.project.setProperty(p); + return this; + } + + @Override + public Project getProject() { + checkState(project.isInitialized(), "Project has not been set"); + return project.getProperty(); + } + + @Override + public AnalysisMetadataHolderRule setRootComponentRef(int rootComponentRef) { + this.rootComponentRef.setProperty(rootComponentRef); + return this; + } + + @Override + public int getRootComponentRef() { + checkState(rootComponentRef.isInitialized(), "Root component ref has not been set"); + return rootComponentRef.getProperty(); + } + + @Override + public AnalysisMetadataHolderRule setQProfilesByLanguage(Map qProfilesPerLanguage) { + this.qProfilesPerLanguage.setProperty(qProfilesPerLanguage); + return this; + } + + @Override + public Map getQProfilesByLanguage() { + checkState(qProfilesPerLanguage.isInitialized(), "QProfile per language has not been set"); + return qProfilesPerLanguage.getProperty(); + } + + @Override + public AnalysisMetadataHolderRule setScannerPluginsByKey(Map plugins) { + this.pluginsByKey.setProperty(plugins); + return this; + } + + @Override + public Map getScannerPluginsByKey() { + checkState(pluginsByKey.isInitialized(), "Plugins per key has not been set"); + return pluginsByKey.getProperty(); + } + + @Override + public MutableAnalysisMetadataHolder setScmRevision(@Nullable String s) { + checkState(!this.scmRevision.isInitialized(), "ScmRevisionId has already been set"); + this.scmRevision.setProperty(defaultIfBlank(s, null)); + return this; + } + + @Override + public Optional getScmRevision() { + if (!scmRevision.isInitialized()) { + return Optional.empty(); + } + return Optional.ofNullable(scmRevision.getProperty()); + } + + @Override + public boolean isShortLivingBranch() { + Branch property = this.branch.getProperty(); + return property != null && property.getType() == BranchType.SHORT; + } + + @Override + public boolean isLongLivingBranch() { + Branch property = this.branch.getProperty(); + return property != null && property.getType() == BranchType.LONG; + } + + @Override + public boolean isPullRequest() { + Branch property = this.branch.getProperty(); + return property != null && property.getType() == BranchType.PULL_REQUEST; + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/analysis/MutableAnalysisMetadataHolderRule.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/analysis/MutableAnalysisMetadataHolderRule.java new file mode 100644 index 00000000000..a622ff7cdb5 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/analysis/MutableAnalysisMetadataHolderRule.java @@ -0,0 +1,211 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.analysis; + +import java.util.Map; +import java.util.Optional; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.junit.rules.ExternalResource; +import org.sonar.core.platform.PlatformEditionProvider; +import org.sonar.server.project.Project; +import org.sonar.server.qualityprofile.QualityProfile; + +import static org.mockito.Mockito.mock; + +public class MutableAnalysisMetadataHolderRule extends ExternalResource implements MutableAnalysisMetadataHolder { + + private PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class); + private AnalysisMetadataHolderImpl delegate = new AnalysisMetadataHolderImpl(editionProvider); + + @Override + protected void after() { + delegate = new AnalysisMetadataHolderImpl(editionProvider); + } + + @Override + public boolean isOrganizationsEnabled() { + return delegate.isOrganizationsEnabled(); + } + + @Override + public MutableAnalysisMetadataHolderRule setOrganizationsEnabled(boolean isOrganizationsEnabled) { + delegate.setOrganizationsEnabled(isOrganizationsEnabled); + return this; + } + + @Override + public MutableAnalysisMetadataHolderRule setOrganization(Organization organization) { + delegate.setOrganization(organization); + return this; + } + + @Override + public Organization getOrganization() { + return delegate.getOrganization(); + } + + public MutableAnalysisMetadataHolderRule setUuid(String s) { + delegate.setUuid(s); + return this; + } + + @Override + public String getUuid() { + return delegate.getUuid(); + } + + public MutableAnalysisMetadataHolderRule setAnalysisDate(long date) { + delegate.setAnalysisDate(date); + return this; + } + + @Override + public long getAnalysisDate() { + return delegate.getAnalysisDate(); + } + + @Override + public boolean hasAnalysisDateBeenSet() { + return delegate.hasAnalysisDateBeenSet(); + } + + @Override + public boolean isFirstAnalysis() { + return delegate.isFirstAnalysis(); + } + + @Override + public MutableAnalysisMetadataHolderRule setBaseAnalysis(@Nullable Analysis baseAnalysis) { + delegate.setBaseAnalysis(baseAnalysis); + return this; + } + + @Override + @CheckForNull + public Analysis getBaseAnalysis() { + return delegate.getBaseAnalysis(); + } + + @Override + public boolean isCrossProjectDuplicationEnabled() { + return delegate.isCrossProjectDuplicationEnabled(); + } + + @Override + public MutableAnalysisMetadataHolderRule setCrossProjectDuplicationEnabled(boolean isCrossProjectDuplicationEnabled) { + delegate.setCrossProjectDuplicationEnabled(isCrossProjectDuplicationEnabled); + return this; + } + + @Override + public Branch getBranch() { + return delegate.getBranch(); + } + + @Override + public MutableAnalysisMetadataHolderRule setBranch(Branch branch) { + delegate.setBranch(branch); + return this; + } + + @Override + public String getPullRequestKey() { + return delegate.getPullRequestKey(); + } + + @Override + public MutableAnalysisMetadataHolder setPullRequestKey(String pullRequestKey) { + delegate.setPullRequestKey(pullRequestKey); + return this; + } + + @Override + public MutableAnalysisMetadataHolderRule setProject(@Nullable Project project) { + delegate.setProject(project); + return this; + } + + @Override + public Project getProject() { + return delegate.getProject(); + } + + @Override + public MutableAnalysisMetadataHolderRule setRootComponentRef(int rootComponentRef) { + delegate.setRootComponentRef(rootComponentRef); + return this; + } + + @Override + public int getRootComponentRef() { + return delegate.getRootComponentRef(); + } + + @Override + public MutableAnalysisMetadataHolder setQProfilesByLanguage(Map qprofilesByLanguage) { + delegate.setQProfilesByLanguage(qprofilesByLanguage); + return this; + } + + @Override + public Map getQProfilesByLanguage() { + return delegate.getQProfilesByLanguage(); + } + + @Override + public MutableAnalysisMetadataHolder setScannerPluginsByKey(Map plugins) { + delegate.setScannerPluginsByKey(plugins); + return this; + } + + @Override + public Map getScannerPluginsByKey() { + return delegate.getScannerPluginsByKey(); + } + + + + @Override + public MutableAnalysisMetadataHolder setScmRevision(String scmRevisionId) { + delegate.setScmRevision(scmRevisionId); + return this; + } + + @Override + public Optional getScmRevision() { + return delegate.getScmRevision(); + } + + @Override + public boolean isShortLivingBranch() { + return delegate.isShortLivingBranch(); + } + + @Override + public boolean isLongLivingBranch() { + return delegate.isLongLivingBranch(); + } + + @Override + public boolean isPullRequest() { + return delegate.isPullRequest(); + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/AbstractComponentProvider.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/AbstractComponentProvider.java new file mode 100644 index 00000000000..b45de74bc26 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/AbstractComponentProvider.java @@ -0,0 +1,52 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.component; + +import static com.google.common.base.Preconditions.checkState; + +abstract class AbstractComponentProvider implements ComponentProvider { + private boolean initialized = false; + + @Override + public void ensureInitialized() { + if (!this.initialized) { + ensureInitializedImpl(); + this.initialized = true; + } + } + + protected abstract void ensureInitializedImpl(); + + @Override + public void reset() { + resetImpl(); + this.initialized = false; + } + + protected abstract void resetImpl(); + + @Override + public Component getByRef(int componentRef) { + checkState(this.initialized, "%s has not been initialized", getClass().getSimpleName()); + return getByRefImpl(componentRef); + } + + protected abstract Component getByRefImpl(int componentRef); +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/ComponentProvider.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/ComponentProvider.java new file mode 100644 index 00000000000..7d042647b07 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/ComponentProvider.java @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.component; + +public interface ComponentProvider { + /** + * does nothing if already initialized + */ + void ensureInitialized(); + + void reset(); + + /** + * @throws IllegalStateException if no component is found for the specified ref + * @throws IllegalStateException if provider has not been initialized + */ + Component getByRef(int componentRef); +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/MutableTreeRootHolderRule.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/MutableTreeRootHolderRule.java new file mode 100644 index 00000000000..506a4e2ee2e --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/MutableTreeRootHolderRule.java @@ -0,0 +1,28 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.component; + +public class MutableTreeRootHolderRule extends TreeRootHolderRule implements MutableTreeRootHolder { + @Override + public MutableTreeRootHolderRule setRoots(Component root, Component reportRoot) { + delegate.setRoots(root, reportRoot); + return this; + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/NoComponentProvider.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/NoComponentProvider.java new file mode 100644 index 00000000000..670b57d2efd --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/NoComponentProvider.java @@ -0,0 +1,41 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.component; + +public enum NoComponentProvider implements ComponentProvider { + INSTANCE; + + private static final String ERROR_MSG = "Can not add a measure by Component ref if MeasureRepositoryRule has not been created for some Component provider"; + + @Override + public void ensureInitialized() { + throw new IllegalStateException(ERROR_MSG); + } + + @Override + public void reset() { + // do nothing + } + + @Override + public Component getByRef(int componentRef) { + throw new IllegalStateException(ERROR_MSG); + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/ReportComponent.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/ReportComponent.java new file mode 100644 index 00000000000..0b10c06c7bb --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/ReportComponent.java @@ -0,0 +1,304 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.component; + +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Arrays.asList; +import static java.util.Objects.requireNonNull; + +/** + * Implementation of {@link Component} to unit test report components. + */ +public class ReportComponent implements Component { + + private static final FileAttributes DEFAULT_FILE_ATTRIBUTES = new FileAttributes(false, null, 1); + + public static final Component DUMB_PROJECT = builder(Type.PROJECT, 1) + .setKey("PROJECT_KEY") + .setPublicKey("PUBLIC_PROJECT_KEY") + .setUuid("PROJECT_UUID") + .setName("Project Name") + .setProjectVersion("1.0-SNAPSHOT") + .build(); + + private final Type type; + private final Status status; + private final String name; + private final String shortName; + @CheckForNull + private final String description; + private final String key; + private final String publicKey; + private final String uuid; + private final ProjectAttributes projectAttributes; + private final ReportAttributes reportAttributes; + private final FileAttributes fileAttributes; + private final List children; + + private ReportComponent(Builder builder) { + this.type = builder.type; + this.status = builder.status; + this.key = builder.key; + this.publicKey = builder.publicKey; + this.name = builder.name == null ? String.valueOf(builder.key) : builder.name; + this.shortName = builder.shortName == null ? this.name : builder.shortName; + this.description = builder.description; + this.uuid = builder.uuid; + this.projectAttributes = Optional.ofNullable(builder.projectVersion) + .map(v -> new ProjectAttributes(v, builder.buildString, builder.scmRevisionId)) + .orElse(null); + this.reportAttributes = ReportAttributes.newBuilder(builder.ref) + .build(); + this.fileAttributes = builder.fileAttributes == null ? DEFAULT_FILE_ATTRIBUTES : builder.fileAttributes; + this.children = ImmutableList.copyOf(builder.children); + } + + @Override + public Type getType() { + return type; + } + + @Override + public Status getStatus() { + return status; + } + + @Override + public String getUuid() { + if (uuid == null) { + throw new UnsupportedOperationException(String.format("Component uuid of ref '%d' has not be fed yet", this.reportAttributes.getRef())); + } + return uuid; + } + + @Override + public String getDbKey() { + if (key == null) { + throw new UnsupportedOperationException(String.format("Component key of ref '%d' has not be fed yet", this.reportAttributes.getRef())); + } + return key; + } + + @Override + public String getKey() { + if (publicKey == null) { + throw new UnsupportedOperationException(String.format("Component key of ref '%d' has not be fed yet", this.reportAttributes.getRef())); + } + return publicKey; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public String getShortName() { + return this.shortName; + } + + @Override + @CheckForNull + public String getDescription() { + return this.description; + } + + @Override + public List getChildren() { + return children; + } + + @Override + public ProjectAttributes getProjectAttributes() { + checkState(this.type == Type.PROJECT); + return this.projectAttributes; + } + + @Override + public ReportAttributes getReportAttributes() { + return this.reportAttributes; + } + + @Override + public FileAttributes getFileAttributes() { + checkState(this.type == Type.FILE, "Only component of type FILE can have a FileAttributes object"); + return this.fileAttributes; + } + + @Override + public ProjectViewAttributes getProjectViewAttributes() { + throw new IllegalStateException("Only component of type PROJECT_VIEW can have a ProjectViewAttributes object"); + } + + @Override + public SubViewAttributes getSubViewAttributes() { + throw new IllegalStateException("Only component of type SUBVIEW have a SubViewAttributes object"); + } + + @Override + public ViewAttributes getViewAttributes() { + throw new IllegalStateException("Only component of type VIEW have a ViewAttributes object"); + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ReportComponent that = (ReportComponent) o; + return uuid.equals(that.uuid); + } + + @Override + public int hashCode() { + return uuid.hashCode(); + } + + @Override + public String toString() { + return "ReportComponent{" + + "ref=" + this.reportAttributes.getRef() + + ", key='" + key + '\'' + + ", type=" + type + + '}'; + } + + public static Builder builder(Type type, int ref) { + String key = "key_" + ref; + return new Builder(type, ref).setKey(key).setPublicKey(key).setUuid("uuid_" + ref).setName("name_" + ref); + } + + public static final class Builder { + private final Type type; + private final int ref; + private Status status; + private String uuid; + private String key; + private String publicKey; + private String name; + private String shortName; + private String projectVersion; + private String buildString; + private String scmRevisionId; + private String description; + private FileAttributes fileAttributes; + private final List children = new ArrayList<>(); + + private Builder(Type type, int ref) { + checkArgument(type.isReportType(), "Component type must be a report type"); + this.type = type; + this.ref = ref; + if (type == Type.PROJECT) { + this.projectVersion = "toBeDefined"; + } + } + + public Builder setStatus(Status s) { + this.status = requireNonNull(s); + return this; + } + + public Builder setUuid(String s) { + this.uuid = requireNonNull(s); + return this; + } + + public Builder setName(@Nullable String s) { + this.name = s; + return this; + } + + public Builder setShortName(@Nullable String s) { + this.shortName = s; + return this; + } + + public Builder setKey(String s) { + this.key = requireNonNull(s); + return this; + } + + public Builder setPublicKey(String publicKey) { + this.publicKey = requireNonNull(publicKey); + return this; + } + + public Builder setProjectVersion(@Nullable String s) { + checkProjectVersion(s); + this.projectVersion = s; + return this; + } + + public Builder setBuildString(@Nullable String buildString) { + checkBuildString(buildString); + this.buildString = buildString; + return this; + } + + public Builder setScmRevisionId(@Nullable String scmRevisionId) { + this.scmRevisionId = scmRevisionId; + return this; + } + + public Builder setFileAttributes(FileAttributes fileAttributes) { + checkState(type == Type.FILE, "Only Component of type File can have File attributes"); + this.fileAttributes = fileAttributes; + return this; + } + + public Builder setDescription(@Nullable String description) { + this.description = description; + return this; + } + + public Builder addChildren(Component... c) { + for (Component component : c) { + checkArgument(component.getType().isReportType()); + } + this.children.addAll(asList(c)); + return this; + } + + public ReportComponent build() { + checkProjectVersion(this.projectVersion); + checkBuildString(this.buildString); + return new ReportComponent(this); + } + + private void checkProjectVersion(@Nullable String s) { + checkArgument(type != Type.PROJECT ^ s != null, "Project version must and can only be set on Project"); + } + + private void checkBuildString(@Nullable String s) { + checkArgument(type == Type.PROJECT || s == null, "BuildString can only be set on Project"); + } + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/TreeComponentProvider.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/TreeComponentProvider.java new file mode 100644 index 00000000000..10ebd61aeb7 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/TreeComponentProvider.java @@ -0,0 +1,64 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.component; + +import java.util.HashMap; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkState; + +public final class TreeComponentProvider extends AbstractComponentProvider { + private final Component root; + private final Map componentsByRef = new HashMap<>(); + + public TreeComponentProvider(Component root) { + this.root = root; + ensureInitialized(); + } + + private static String getRef(Component component) { + return component.getType().isReportType() ? String.valueOf(component.getReportAttributes().getRef()) : component.getDbKey(); + } + + @Override + protected void ensureInitializedImpl() { + new DepthTraversalTypeAwareCrawler( + new TypeAwareVisitorAdapter(CrawlerDepthLimit.LEAVES, ComponentVisitor.Order.PRE_ORDER) { + @Override + public void visitAny(Component component) { + String ref = getRef(component); + checkState(!componentsByRef.containsKey(ref), "Tree contains more than one component with ref " + ref); + componentsByRef.put(ref, component); + } + }).visit(root); + } + + @Override + protected void resetImpl() { + // we can not reset + } + + @Override + protected Component getByRefImpl(int componentRef) { + Component component = componentsByRef.get(String.valueOf(componentRef)); + checkState(component != null, "Can not find Component for ref " + componentRef); + return component; + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderComponentProvider.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderComponentProvider.java new file mode 100644 index 00000000000..da7eae0c878 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderComponentProvider.java @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.component; + +public final class TreeRootHolderComponentProvider extends AbstractComponentProvider { + private final TreeRootHolder treeRootHolder; + private TreeComponentProvider delegate; + + public TreeRootHolderComponentProvider(TreeRootHolder treeRootHolder) { + this.treeRootHolder = treeRootHolder; + } + + @Override + protected void ensureInitializedImpl() { + if (this.delegate == null) { + this.delegate = new TreeComponentProvider(treeRootHolder.getRoot()); + this.delegate.ensureInitialized(); + } + } + + @Override + protected void resetImpl() { + this.delegate = null; + } + + @Override + protected Component getByRefImpl(int componentRef) { + return delegate.getByRef(componentRef); + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderRule.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderRule.java new file mode 100644 index 00000000000..bfdaa2fff06 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/TreeRootHolderRule.java @@ -0,0 +1,77 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.component; + +import java.util.Optional; +import org.junit.rules.ExternalResource; + +public class TreeRootHolderRule extends ExternalResource implements TreeRootHolder { + protected TreeRootHolderImpl delegate = new TreeRootHolderImpl(); + + @Override + protected void after() { + this.delegate = null; + } + + public TreeRootHolderRule setRoot(Component root) { + return setRoots(root, root); + } + + public TreeRootHolderRule setRoots(Component root, Component reportRoot) { + delegate = new TreeRootHolderImpl(); + delegate.setRoots(root, reportRoot); + return this; + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public Component getRoot() { + return delegate.getRoot(); + } + + @Override + public Component getReportTreeRoot() { + return delegate.getReportTreeRoot(); + } + + @Override + public Component getComponentByRef(int ref) { + return delegate.getComponentByRef(ref); + } + + @Override + public Optional getOptionalComponentByRef(int ref) { + return delegate.getOptionalComponentByRef(ref); + } + + @Override public Component getReportTreeComponentByRef(int ref) { + return delegate.getReportTreeComponentByRef(ref); + } + + @Override + public int getSize() { + return delegate.getSize(); + } + +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/ViewsComponent.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/ViewsComponent.java new file mode 100644 index 00000000000..a8f5afb35dd --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/component/ViewsComponent.java @@ -0,0 +1,253 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.component; + +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Arrays.asList; +import static java.util.Objects.requireNonNull; + +/** + * Implementation of {@link Component} to unit test views components. + */ +public class ViewsComponent implements Component { + private final Type type; + private final String key; + private final String uuid; + private final String name; + private final String description; + private final List children; + private final ProjectViewAttributes projectViewAttributes; + private final SubViewAttributes subViewAttributes; + private final ViewAttributes viewAttributes; + + private ViewsComponent(Type type, String key, @Nullable String uuid, @Nullable String name, @Nullable String description, + List children, @Nullable ProjectViewAttributes projectViewAttributes, @Nullable SubViewAttributes subViewAttributes, + @Nullable ViewAttributes viewAttributes) { + checkArgument(type.isViewsType(), "Component type must be a Views type"); + this.type = type; + this.key = requireNonNull(key); + this.uuid = uuid; + this.name = name; + this.description = description; + this.children = ImmutableList.copyOf(children); + this.projectViewAttributes = projectViewAttributes; + this.subViewAttributes = subViewAttributes; + this.viewAttributes = viewAttributes; + } + + public static Builder builder(Type type, String key) { + return new Builder(type, key); + } + + public static Builder builder(Type type, int key) { + return new Builder(type, String.valueOf(key)); + } + + public static final class Builder { + private final Type type; + private String key; + private String uuid; + private String name; + private String description; + private List children = new ArrayList<>(); + private ProjectViewAttributes projectViewAttributes; + private SubViewAttributes subViewAttributes; + private ViewAttributes viewAttributes; + + private Builder(Type type, String key) { + this.type = type; + this.key = key; + } + + public Builder setUuid(@Nullable String uuid) { + this.uuid = uuid; + return this; + } + + public Builder setKey(String key) { + this.key = key; + return this; + } + + public Builder setName(@Nullable String name) { + this.name = name; + return this; + } + + public Builder setDescription(String description) { + this.description = description; + return this; + } + + public Builder setChildren(List children) { + this.children = children; + return this; + } + + public Builder setProjectViewAttributes(@Nullable ProjectViewAttributes projectViewAttributes) { + this.projectViewAttributes = projectViewAttributes; + return this; + } + + public Builder setSubViewAttributes(@Nullable SubViewAttributes subViewAttributes) { + this.subViewAttributes = subViewAttributes; + return this; + } + + public Builder setViewAttributes(@Nullable ViewAttributes viewAttributes) { + this.viewAttributes = viewAttributes; + return this; + } + + public Builder addChildren(Component... c) { + for (Component viewsComponent : c) { + checkArgument(viewsComponent.getType().isViewsType()); + } + this.children.addAll(asList(c)); + return this; + } + + public ViewsComponent build() { + return new ViewsComponent(type, key, uuid, name, description, children, projectViewAttributes, subViewAttributes, viewAttributes); + } + } + + @Override + public Type getType() { + return type; + } + + @Override + public Status getStatus() { + return Status.UNAVAILABLE; + } + + @Override + public String getUuid() { + return uuid; + } + + @Override + public String getDbKey() { + return key; + } + + /** + * Views has no branch feature, the public key is the same as the key + */ + @Override + public String getKey() { + return getDbKey(); + } + + @Override + public String getName() { + checkState(this.name != null, "No name has been set"); + return this.name; + } + + @Override + public String getShortName() { + return getName(); + } + + @Override + @CheckForNull + public String getDescription() { + return this.description; + } + + @Override + public List getChildren() { + return children; + } + + @Override + public ProjectAttributes getProjectAttributes() { + throw new IllegalStateException("A component of type " + type + " does not have project attributes"); + } + + @Override + public ReportAttributes getReportAttributes() { + throw new IllegalStateException("A component of type " + type + " does not have report attributes"); + } + + @Override + public FileAttributes getFileAttributes() { + throw new IllegalStateException("A component of type " + type + " does not have file attributes"); + } + + @Override + public ProjectViewAttributes getProjectViewAttributes() { + checkState(this.type != Type.PROJECT_VIEW || this.projectViewAttributes != null, "A ProjectViewAttribute object should have been set"); + return this.projectViewAttributes; + } + + @Override + public SubViewAttributes getSubViewAttributes() { + checkState(this.type != Type.SUBVIEW || this.subViewAttributes != null, "A SubViewAttributes object should have been set"); + return this.subViewAttributes; + } + + @Override + public ViewAttributes getViewAttributes() { + checkState(this.type != Type.VIEW || this.viewAttributes != null, "A ViewAttributes object should have been set"); + return viewAttributes; + } + + @Override + public String toString() { + return "ViewsComponent{" + + "type=" + type + + ", key='" + key + '\'' + + ", uuid='" + uuid + '\'' + + ", name='" + name + '\'' + + ", children=" + children + + ", projectViewAttributes=" + projectViewAttributes + + ", subViewAttributes=" + subViewAttributes + + ", viewAttributes=" + viewAttributes + + '}'; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ViewsComponent that = (ViewsComponent) o; + return key.equals(that.key); + } + + @Override + public int hashCode() { + return Objects.hash(key); + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureAssert.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureAssert.java new file mode 100644 index 00000000000..7b8d2eaa2bc --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureAssert.java @@ -0,0 +1,255 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.measure; + +import java.util.Objects; +import java.util.Optional; +import javax.annotation.Nullable; +import org.assertj.core.api.AbstractAssert; +import org.assertj.core.data.Offset; + +import static java.lang.Math.abs; + +public class MeasureAssert extends AbstractAssert { + + protected MeasureAssert(@Nullable Measure actual) { + super(actual, MeasureAssert.class); + } + + public static MeasureAssert assertThat(Measure actual) { + return new MeasureAssert(actual); + } + + public static MeasureAssert assertThat(@Nullable Optional actual) { + return new MeasureAssert(actual == null ? null : actual.orElse(null)); + } + + public MeasureAssert hasValueType(Measure.ValueType expected) { + isNotNull(); + + if (actual.getValueType() != expected) { + failWithMessage("Expected ValueType of Measure to be <%s> but was <%s>", expected, actual.getValueType()); + } + + return this; + } + + public MeasureAssert hasValue(int expected) { + isNotNull(); + + if (actual.getValueType() != Measure.ValueType.INT) { + failWithMessage( + "Expected Measure to have an int value and therefore its ValueType to be <%s> but was <%s>", + Measure.ValueType.INT, actual.getValueType()); + } + + if (actual.getIntValue() != expected) { + failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getIntValue()); + } + + return this; + } + + public MeasureAssert hasValue(long expected) { + isNotNull(); + + if (actual.getValueType() != Measure.ValueType.LONG) { + failWithMessage( + "Expected Measure to have a long value and therefore its ValueType to be <%s> but was <%s>", + Measure.ValueType.LONG, actual.getValueType()); + } + + if (actual.getLongValue() != expected) { + failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getLongValue()); + } + + return this; + } + + public MeasureAssert hasValue(double expected) { + isNotNull(); + + if (actual.getValueType() != Measure.ValueType.DOUBLE) { + failWithMessage( + "Expected Measure to have a double value and therefore its ValueType to be <%s> but was <%s>", + Measure.ValueType.DOUBLE, actual.getValueType()); + } + + if (actual.getDoubleValue() != expected) { + failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getDoubleValue()); + } + + return this; + } + + public MeasureAssert hasValue(boolean expected) { + isNotNull(); + + if (actual.getValueType() != Measure.ValueType.BOOLEAN) { + failWithMessage( + "Expected Measure to have a boolean value and therefore its ValueType to be <%s> but was <%s>", + Measure.ValueType.DOUBLE, actual.getValueType()); + } + + if (actual.getBooleanValue() != expected) { + failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getBooleanValue()); + } + + return this; + } + + public MeasureAssert hasValue(String expected) { + isNotNull(); + + if (actual.getValueType() != Measure.ValueType.STRING) { + failWithMessage( + "Expected Measure to have a String value and therefore its ValueType to be <%s> but was <%s>", + Measure.ValueType.DOUBLE, actual.getValueType()); + } + + if (!Objects.equals(actual.getStringValue(), expected)) { + failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getStringValue()); + } + + return this; + } + + public MeasureAssert hasValue(Measure.Level expected) { + isNotNull(); + + if (actual.getValueType() != Measure.ValueType.LEVEL) { + failWithMessage( + "Expected Measure to have a Level value and therefore its ValueType to be <%s> but was <%s>", + Measure.ValueType.DOUBLE, actual.getValueType()); + } + + if (actual.getLevelValue() != expected) { + failWithMessage("Expected value of Measure to be <%s> but was <%s>", expected, actual.getLevelValue()); + } + + return this; + } + + public MeasureAssert hasNoValue() { + isNotNull(); + + if (actual.getValueType() != Measure.ValueType.NO_VALUE) { + failWithMessage( + "Expected Measure to have no value and therefore its ValueType to be <%s> but was <%s>", + Measure.ValueType.DOUBLE, actual.getValueType()); + } + + return this; + } + + public MeasureAssert hasData(String expected) { + isNotNull(); + + if (!Objects.equals(actual.getData(), expected)) { + failWithMessage("Expected data of Measure to be <%s> but was <%s>", expected, actual.getData()); + } + + return this; + } + + public MeasureAssert hasNoData() { + isNotNull(); + + if (actual.getData() == null) { + failWithMessage("Expected Measure to have no data but was <%s>", actual.getData()); + } + + return this; + } + + public MeasureAssert hasQualityGateLevel(Measure.Level expected) { + isNotNull(); + hasQualityGateStatus(); + + if (actual.getQualityGateStatus().getStatus() != expected) { + failWithMessage("Expected Level of QualityGateStatus of Measure to be <%s> but was <%s>", expected, actual.getQualityGateStatus().getStatus()); + } + + return this; + } + + public MeasureAssert hasQualityGateText(String expected) { + isNotNull(); + hasQualityGateStatus(); + + if (!Objects.equals(actual.getQualityGateStatus().getText(), expected)) { + failWithMessage("Expected text of QualityGateStatus of Measure to be \n<%s>\n but was \n<%s>", expected, actual.getQualityGateStatus().getText()); + } + + return this; + } + + private void hasQualityGateStatus() { + if (!actual.hasQualityGateStatus()) { + failWithMessage("Expected Measure to have a QualityGateStatus but it did not"); + } + } + + public MeasureAssert hasVariation(double expected) { + isNotNull(); + hasVariation(); + + if (!actual.hasVariation()) { + failWithMessage("Expected Measure to have a variation but it did not"); + } + + double variation = actual.getVariation(); + if (variation != expected) { + failWithMessage("Expected variation of Measure to be <%s> but was <%s>", expected, variation); + } + + return this; + } + + public MeasureAssert hasVariation(double expected, Offset offset) { + isNotNull(); + hasVariation(); + + if (!actual.hasVariation()) { + failWithMessage("Expected Measure to have a variation but it did not"); + } + + double variation = actual.getVariation(); + if (abs(expected - variation) > offset.value) { + failWithMessage( + "Expected variation of Measure to be close to <%s> by less than <%s> but was <%s>", + expected, offset.value, variation); + } + + return this; + } + + private void hasVariation() { + if (!actual.hasVariation()) { + failWithMessage("Expected Measure to have a variation but it did not"); + } + } + + public void isAbsent() { + if (actual != null) { + failWithMessage("Expected measure to be absent"); + } + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepoEntry.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepoEntry.java new file mode 100644 index 00000000000..2cf7fc130c6 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepoEntry.java @@ -0,0 +1,157 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.measure; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.SetMultimap; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Map; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.sonar.ce.task.projectanalysis.component.Component; + +/** + * This class represents a metric key and an associated measure. + * It can be used to easily compare the content of the SetMultimap returned by {@link MeasureRepository#getRawMeasures(Component)} + * or {@link MeasureRepositoryRule#getAddedRawMeasures(int)}. + *

+ * This class is also highly useful to accurately make sure of the SetMultimap content since this + * object implements a deep equals of Measure objects (see {@link #deepEquals(Measure, Measure)}), when + * {@link Measure#equals(Object)} only care about the ruleId and characteristicId. + *

+ *

+ * In order to explore the content of the SetMultimap, use {@link #toEntries(SetMultimap)} to convert it + * to an Iterable of {@link MeasureRepoEntry} and then take benefit of AssertJ API, eg.: + *

+ * assertThat(MeasureRepoEntry.toEntries(measureRepository.getAddedRawMeasures(componentRef))).containsOnly(
+ *   MeasureRepoEntry.entryOf(DEVELOPMENT_COST_KEY, newMeasureBuilder().create(Long.toString(expectedDevCost))),
+ *   MeasureRepoEntry.entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(expectedDebtRatio))
+ * );
+ * 
+ *

+ */ +public final class MeasureRepoEntry { + private final String metricKey; + private final Measure measure; + + public MeasureRepoEntry(String metricKey, Measure measure) { + this.metricKey = metricKey; + this.measure = measure; + } + + public static Function, MeasureRepoEntry> toMeasureRepoEntry() { + return EntryToMeasureRepoEntry.INSTANCE; + } + + public static Iterable toEntries(SetMultimap data) { + return FluentIterable.from(data.entries()).transform(toMeasureRepoEntry()).toList(); + } + + public static MeasureRepoEntry entryOf(String metricKey, Measure measure) { + return new MeasureRepoEntry(metricKey, measure); + } + + public static boolean deepEquals(Measure measure, Measure measure1) { + return measure.getValueType() == measure1.getValueType() + && equalsByValue(measure, measure1) + && equalsByVariation(measure, measure1) + && equalsByQualityGateStatus(measure, measure1) + && Objects.equals(measure.getData(), measure1.getData()); + } + + private static boolean equalsByValue(Measure measure, Measure measure1) { + switch (measure.getValueType()) { + case BOOLEAN: + return measure.getBooleanValue() == measure1.getBooleanValue(); + case INT: + return measure.getIntValue() == measure1.getIntValue(); + case LONG: + return measure.getLongValue() == measure1.getLongValue(); + case DOUBLE: + return Double.compare(measure.getDoubleValue(), measure1.getDoubleValue()) == 0; + case STRING: + return measure.getStringValue().equals(measure1.getStringValue()); + case LEVEL: + return measure.getLevelValue() == measure1.getLevelValue(); + case NO_VALUE: + return true; + default: + throw new IllegalArgumentException("Unsupported ValueType " + measure.getValueType()); + } + } + + private static boolean equalsByVariation(Measure measure, Measure measure1) { + return measure.hasVariation() == measure1.hasVariation() && (!measure.hasVariation() + || Double.compare(scale(measure.getVariation()), scale(measure1.getVariation())) == 0); + } + + private static final int DOUBLE_PRECISION = 1; + + private static double scale(double value) { + BigDecimal bd = BigDecimal.valueOf(value); + return bd.setScale(DOUBLE_PRECISION, RoundingMode.HALF_UP).doubleValue(); + } + + private static boolean equalsByQualityGateStatus(Measure measure, Measure measure1) { + if (measure.hasQualityGateStatus() != measure1.hasQualityGateStatus()) { + return false; + } + if (!measure.hasQualityGateStatus()) { + return true; + } + return Objects.equals(measure.getQualityGateStatus(), measure1.getQualityGateStatus()); + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MeasureRepoEntry that = (MeasureRepoEntry) o; + return Objects.equals(metricKey, that.metricKey) && + deepEquals(measure, that.measure); + } + + @Override + public int hashCode() { + return Objects.hash(metricKey, measure); + } + + @Override + public String toString() { + return "<" + metricKey + ", " + measure + '>'; + } + + private enum EntryToMeasureRepoEntry implements Function, MeasureRepoEntry> { + INSTANCE; + + @Nullable + @Override + public MeasureRepoEntry apply(@Nonnull Map.Entry input) { + return new MeasureRepoEntry(input.getKey(), input.getValue()); + } + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepositoryRule.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepositoryRule.java new file mode 100644 index 00000000000..2c579151024 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/measure/MeasureRepositoryRule.java @@ -0,0 +1,316 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.measure; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.SetMultimap; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.junit.rules.ExternalResource; +import org.sonar.ce.task.projectanalysis.component.Component; +import org.sonar.ce.task.projectanalysis.component.ComponentProvider; +import org.sonar.ce.task.projectanalysis.component.NoComponentProvider; +import org.sonar.ce.task.projectanalysis.component.TreeComponentProvider; +import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; +import org.sonar.ce.task.projectanalysis.component.TreeRootHolderComponentProvider; +import org.sonar.ce.task.projectanalysis.metric.Metric; +import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.FluentIterable.from; +import static com.google.common.collect.Maps.filterKeys; +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +/** + * An implementation of MeasureRepository as a JUnit rule which provides add methods for raw measures and extra add + * methods that takes component ref and metric keys thanks to the integration with various Component and Metric + * providers. + */ +public class MeasureRepositoryRule extends ExternalResource implements MeasureRepository { + private final ComponentProvider componentProvider; + @CheckForNull + private final MetricRepositoryRule metricRepositoryRule; + private final Map baseMeasures = new HashMap<>(); + private final Map rawMeasures = new HashMap<>(); + private final Map initialRawMeasures = new HashMap<>(); + private final Predicate> isAddedMeasure = input -> !initialRawMeasures.containsKey(input.getKey()) + || !MeasureRepoEntry.deepEquals(input.getValue(), initialRawMeasures.get(input.getKey())); + + private MeasureRepositoryRule(ComponentProvider componentProvider, @Nullable MetricRepositoryRule metricRepositoryRule) { + this.componentProvider = componentProvider; + this.metricRepositoryRule = metricRepositoryRule; + } + + @Override + protected void after() { + componentProvider.reset(); + baseMeasures.clear(); + rawMeasures.clear(); + } + + public static MeasureRepositoryRule create() { + return new MeasureRepositoryRule(NoComponentProvider.INSTANCE, null); + } + + public static MeasureRepositoryRule create(TreeRootHolder treeRootHolder, MetricRepositoryRule metricRepositoryRule) { + return new MeasureRepositoryRule(new TreeRootHolderComponentProvider(treeRootHolder), requireNonNull(metricRepositoryRule)); + } + + public static MeasureRepositoryRule create(Component treeRoot, MetricRepositoryRule metricRepositoryRule) { + return new MeasureRepositoryRule(new TreeComponentProvider(treeRoot), requireNonNull(metricRepositoryRule)); + } + + public MeasureRepositoryRule addBaseMeasure(int componentRef, String metricKey, Measure measure) { + checkAndInitProvidersState(); + + InternalKey internalKey = new InternalKey(componentProvider.getByRef(componentRef), metricRepositoryRule.getByKey(metricKey)); + checkState(!baseMeasures.containsKey(internalKey), format("Can not add a BaseMeasure twice for a Component (ref=%s) and Metric (key=%s)", componentRef, metricKey)); + + baseMeasures.put(internalKey, measure); + + return this; + } + + public SetMultimap getRawMeasures(int componentRef) { + return getRawMeasures(componentProvider.getByRef(componentRef)); + } + + /** + * Return measures that were added by the step (using {@link #add(Component, Metric, Measure)}). + * It does not contain the one added in the test by {@link #addRawMeasure(int, String, Measure)} + */ + public SetMultimap getAddedRawMeasures(int componentRef) { + checkAndInitProvidersState(); + + return getAddedRawMeasures(componentProvider.getByRef(componentRef)); + } + + /** + * Return a measure that were added by the step (using {@link #add(Component, Metric, Measure)}). + * It does not contain the one added in the test by {@link #addRawMeasure(int, String, Measure)} + */ + public Optional getAddedRawMeasure(Component component, String metricKey) { + return getAddedRawMeasure(component.getReportAttributes().getRef(), metricKey); + } + + /** + * Return a measure that were added by the step (using {@link #add(Component, Metric, Measure)}). + * It does not contain the one added in the test by {@link #addRawMeasure(int, String, Measure)} + */ + public Optional getAddedRawMeasure(int componentRef, String metricKey) { + checkAndInitProvidersState(); + + Set measures = getAddedRawMeasures(componentProvider.getByRef(componentRef)).get(metricKey); + if (measures.isEmpty()) { + return Optional.empty(); + } + checkArgument(measures.size() == 1, String.format("There is more than one measure on metric '%s' for component '%s'", metricKey, componentRef)); + return Optional.of(measures.iterator().next()); + } + + /** + * Return measures that were added by the step (using {@link #add(Component, Metric, Measure)}). + * It does not contain the one added in the test by {@link #addRawMeasure(int, String, Measure)} + */ + public SetMultimap getAddedRawMeasures(Component component) { + checkAndInitProvidersState(); + + ImmutableSetMultimap.Builder builder = ImmutableSetMultimap.builder(); + for (Map.Entry entry : from(filterKeys(rawMeasures, hasComponentRef(component)).entrySet()).filter(isAddedMeasure)) { + builder.put(entry.getKey().getMetricKey(), entry.getValue()); + } + return builder.build(); + } + + public MeasureRepositoryRule addRawMeasure(int componentRef, String metricKey, Measure measure) { + checkAndInitProvidersState(); + + InternalKey internalKey = new InternalKey(componentProvider.getByRef(componentRef), metricRepositoryRule.getByKey(metricKey)); + checkState(!rawMeasures.containsKey(internalKey), format( + "A measure can only be set once for Component (ref=%s), Metric (key=%s)", + componentRef, metricKey)); + + rawMeasures.put(internalKey, measure); + initialRawMeasures.put(internalKey, measure); + + return this; + } + + @Override + public Optional getBaseMeasure(Component component, Metric metric) { + return Optional.ofNullable(baseMeasures.get(new InternalKey(component, metric))); + } + + @Override + public Optional getRawMeasure(Component component, Metric metric) { + return Optional.ofNullable(rawMeasures.get(new InternalKey(component, metric))); + } + + @Override + public Set getRawMeasures(Component component, Metric metric) { + return from(filterKeys(rawMeasures, hasComponentRef(component)).entrySet()).filter(new MatchMetric(metric)).transform(ToMeasure.INSTANCE).toSet(); + } + + @Override + public SetMultimap getRawMeasures(Component component) { + ImmutableSetMultimap.Builder builder = ImmutableSetMultimap.builder(); + for (Map.Entry entry : filterKeys(rawMeasures, hasComponentRef(component)).entrySet()) { + builder.put(entry.getKey().getMetricKey(), entry.getValue()); + } + return builder.build(); + } + + private HasComponentRefPredicate hasComponentRef(Component component) { + return new HasComponentRefPredicate(component); + } + + @Override + public void add(Component component, Metric metric, Measure measure) { + String ref = getRef(component); + InternalKey internalKey = new InternalKey(ref, metric.getKey()); + if (rawMeasures.containsKey(internalKey)) { + throw new UnsupportedOperationException(format( + "A measure can only be set once for Component (ref=%s), Metric (key=%s)", + ref, metric.getKey())); + } + rawMeasures.put(internalKey, measure); + } + + @Override + public void update(Component component, Metric metric, Measure measure) { + String componentRef = getRef(component); + InternalKey internalKey = new InternalKey(componentRef, metric.getKey()); + if (!rawMeasures.containsKey(internalKey)) { + throw new UnsupportedOperationException(format( + "A measure can only be updated if it has been added first for Component (ref=%s), Metric (key=%s)", + componentRef, metric.getKey())); + } + rawMeasures.put(internalKey, measure); + } + + private void checkAndInitProvidersState() { + checkState(metricRepositoryRule != null, "Can not add a measure by metric key if MeasureRepositoryRule has not been created for a MetricRepository"); + componentProvider.ensureInitialized(); + } + + public boolean isEmpty() { + return rawMeasures.isEmpty(); + } + + private static final class InternalKey { + private final String componentRef; + private final String metricKey; + + public InternalKey(Component component, Metric metric) { + this(getRef(component), metric.getKey()); + } + + private InternalKey(String componentRef, String metricKey) { + this.componentRef = componentRef; + this.metricKey = metricKey; + } + + public String getComponentRef() { + return componentRef; + } + + public String getMetricKey() { + return metricKey; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalKey that = (InternalKey) o; + return Objects.equals(componentRef, that.componentRef) && + Objects.equals(metricKey, that.metricKey); + } + + @Override + public int hashCode() { + return Objects.hash(componentRef, metricKey); + } + + @Override + public String toString() { + return "InternalKey{" + + "component=" + componentRef + + ", metric='" + metricKey + '\'' + + '}'; + } + } + + private static class HasComponentRefPredicate implements Predicate { + + private final String componentRef; + + public HasComponentRefPredicate(Component component) { + this.componentRef = getRef(component); + } + + @Override + public boolean apply(@Nonnull InternalKey input) { + return input.getComponentRef().equals(this.componentRef); + } + } + + private static String getRef(Component component) { + return component.getType().isReportType() ? String.valueOf(component.getReportAttributes().getRef()) : component.getDbKey(); + } + + private static class MatchMetric implements Predicate> { + private final Metric metric; + + public MatchMetric(Metric metric) { + this.metric = metric; + } + + @Override + public boolean apply(@Nonnull Map.Entry input) { + return input.getKey().getMetricKey().equals(metric.getKey()); + } + } + + private enum ToMeasure implements Function, Measure> { + INSTANCE; + + @Nullable + @Override + public Measure apply(@Nonnull Map.Entry input) { + return input.getValue(); + } + } + +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/metric/MetricRepositoryRule.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/metric/MetricRepositoryRule.java new file mode 100644 index 00000000000..7f781ff34b0 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/metric/MetricRepositoryRule.java @@ -0,0 +1,116 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.metric; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import org.junit.rules.ExternalResource; + +import static com.google.common.base.Preconditions.checkState; +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +public class MetricRepositoryRule extends ExternalResource implements MetricRepository { + private final Map metricsByKey = new HashMap<>(); + private final Map metricsById = new HashMap<>(); + + /** + * Convenience method to add a {@link Metric} to the repository created from a {@link org.sonar.api.measures.Metric}, + * most of the time it will be a constant of the {@link org.sonar.api.measures.CoreMetrics} class. + *

+ * For the id of the created metric, this method uses the hashCode of the metric's key. If you want to specify + * the id of the create {@link Metric}, use {@link #add(int, org.sonar.api.measures.Metric)} + *

+ */ + public MetricRepositoryRule add(org.sonar.api.measures.Metric coreMetric) { + add(from(coreMetric)); + return this; + } + + /** + * Convenience method to add a {@link Metric} to the repository created from a {@link org.sonar.api.measures.Metric} + * and with the specified id, most of the time it will be a constant of the {@link org.sonar.api.measures.CoreMetrics} + * class. + */ + public MetricRepositoryRule add(int id, org.sonar.api.measures.Metric coreMetric) { + add(from(id, coreMetric)); + return this; + } + + private static Metric from(org.sonar.api.measures.Metric coreMetric) { + return from(coreMetric.getKey().hashCode(), coreMetric); + } + + private static Metric from(int id, org.sonar.api.measures.Metric coreMetric) { + return new MetricImpl( + id, coreMetric.getKey(), coreMetric.getName(), + convert(coreMetric.getType()), + coreMetric.getDecimalScale(), + coreMetric.getBestValue(), coreMetric.isOptimizedBestValue()); + } + + private static Metric.MetricType convert(org.sonar.api.measures.Metric.ValueType coreMetricType) { + return Metric.MetricType.valueOf(coreMetricType.name()); + } + + public MetricRepositoryRule add(Metric metric) { + requireNonNull(metric.getKey(), "key can not be null"); + requireNonNull(metric.getId(), "id can not be null"); + + checkState(!metricsByKey.containsKey(metric.getKey()), format("Repository already contains a metric for key %s", metric.getKey())); + checkState(!metricsById.containsKey((long) metric.getId()), format("Repository already contains a metric for id %s", metric.getId())); + + metricsByKey.put(metric.getKey(), metric); + metricsById.put((long) metric.getId(), metric); + + return this; + } + + @Override + protected void after() { + this.metricsById.clear(); + this.metricsById.clear(); + } + + @Override + public Metric getByKey(String key) { + Metric res = metricsByKey.get(key); + checkState(res != null, format("No Metric can be found for key %s", key)); + return res; + } + + @Override + public Metric getById(long id) { + Metric res = metricsById.get(id); + checkState(res != null, format("No Metric can be found for id %s", id)); + return res; + } + + @Override + public Optional getOptionalById(long id) { + return Optional.of(metricsById.get(id)); + } + + @Override + public Iterable getAll() { + return metricsByKey.values(); + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/step/BaseStepTest.java b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/step/BaseStepTest.java new file mode 100644 index 00000000000..16aed8003df --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/testFixtures/java/org/sonar/ce/task/projectanalysis/step/BaseStepTest.java @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.ce.task.projectanalysis.step; + +import org.junit.Test; +import org.sonar.ce.task.step.ComputationStep; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Temporary solution to test metadata. Should be replaced by a medium test of + * all computation stack + */ +public abstract class BaseStepTest { + + protected abstract ComputationStep step(); + + @Test + public void test_metadata() { + assertThat(step().toString()).isNotEmpty(); + assertThat(step().getDescription()).isNotEmpty(); + } +}