From 80645fca839ea97ee472f01ebb81f40af0f179f5 Mon Sep 17 00:00:00 2001 From: Eric Hartmann Date: Wed, 27 Sep 2017 17:32:21 +0200 Subject: [PATCH] SONAR-9891 Add Analysis to PostProjectAnalysisTask.ProjectAnalysis --- .../db/webhook/WebhookDeliveryLiteDto.java | 1 + .../PostProjectAnalysisTasksExecutor.java | 91 +++++--- .../webhook/WebhookPostTask.java | 47 ++-- .../org/sonar/server/webhook/Analysis.java | 64 ++++++ .../sonar/server/webhook/ProjectAnalysis.java | 13 +- .../org/sonar/server/webhook/WebHooks.java | 17 +- .../org/sonar/server/webhook/Webhook.java | 17 +- .../webhook/WebhookDeliveryStorage.java | 4 +- .../webhook/WebhookPayloadFactoryImpl.java | 4 +- .../PostProjectAnalysisTasksExecutorTest.java | 15 +- .../projectanalysis/webhook/Analysis.java | 44 ++++ .../webhook/ProjectAnalysis.java | 92 ++++++++ .../webhook/WebhookPostTaskTest.java | 29 ++- .../sonar/server/webhook/AnalysisTest.java | 78 +++++++ .../server/webhook/ProjectAnalysisTest.java | 61 ++--- .../webhook/WebhookDeliveryStorageTest.java | 2 +- .../WebhookPayloadFactoryImplTest.java | 4 +- .../org/sonar/server/webhook/WebhookTest.java | 79 +++++++ .../org/sonar/api/ce/posttask/Analysis.java | 35 +++ .../ce/posttask/PostProjectAnalysisTask.java | 14 +- .../PostProjectAnalysisTaskTester.java | 217 ++++++++++++++---- .../PostProjectAnalysisTaskTesterTest.java | 5 +- 22 files changed, 769 insertions(+), 164 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/webhook/Analysis.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/Analysis.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/ProjectAnalysis.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/webhook/AnalysisTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookTest.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/Analysis.java diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/webhook/WebhookDeliveryLiteDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/webhook/WebhookDeliveryLiteDto.java index 804899768fd..30107eadb61 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/webhook/WebhookDeliveryLiteDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/webhook/WebhookDeliveryLiteDto.java @@ -62,6 +62,7 @@ public class WebhookDeliveryLiteDto { return (T)this; } + @CheckForNull public String getCeTaskUuid() { return ceTaskUuid; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java index 08f532c8cd7..8c8f367a88b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java @@ -19,13 +19,15 @@ */ package org.sonar.server.computation.task.projectanalysis.api.posttask; -import com.google.common.base.Optional; import java.util.Collection; import java.util.Date; import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import org.sonar.api.ce.posttask.Analysis; import org.sonar.api.ce.posttask.Branch; import org.sonar.api.ce.posttask.CeTask; import org.sonar.api.ce.posttask.PostProjectAnalysisTask; @@ -44,9 +46,11 @@ import org.sonar.server.computation.task.projectanalysis.qualitygate.QualityGate import org.sonar.server.computation.task.projectanalysis.qualitygate.QualityGateStatusHolder; import org.sonar.server.computation.task.step.ComputationStepExecutor; -import static com.google.common.collect.FluentIterable.from; import static java.lang.String.format; import static java.util.Objects.requireNonNull; +import static java.util.Optional.empty; +import static java.util.Optional.of; +import static java.util.Optional.ofNullable; import static org.sonar.api.ce.posttask.CeTask.Status.FAILED; import static org.sonar.api.ce.posttask.CeTask.Status.SUCCESS; @@ -96,13 +100,13 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor return; } - ProjectAnalysis projectAnalysis = createProjectAnalysis(allStepsExecuted ? SUCCESS : FAILED); + ProjectAnalysisImpl projectAnalysis = createProjectAnalysis(allStepsExecuted ? SUCCESS : FAILED); for (PostProjectAnalysisTask postProjectAnalysisTask : postProjectAnalysisTasks) { executeTask(projectAnalysis, postProjectAnalysisTask); } } - private static void executeTask(ProjectAnalysis projectAnalysis, PostProjectAnalysisTask postProjectAnalysisTask) { + private static void executeTask(ProjectAnalysisImpl projectAnalysis, PostProjectAnalysisTask postProjectAnalysisTask) { try { postProjectAnalysisTask.finished(projectAnalysis); } catch (Exception e) { @@ -110,19 +114,27 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor } } - private ProjectAnalysis createProjectAnalysis(CeTask.Status status) { - Long analysisDate = getAnalysisDate(); - - return new ProjectAnalysis( + private ProjectAnalysisImpl createProjectAnalysis(CeTask.Status status) { + return new ProjectAnalysisImpl( new CeTaskImpl(this.ceTask.getUuid(), status), createProject(this.ceTask), - analysisDate, - analysisDate == null ? system2.now() : analysisDate, + getAnalysis().orElse(null), + getAnalysis().map(a -> a.getDate().getTime()).orElse(system2.now()), ScannerContextImpl.from(reportReader.readContextProperties()), status == SUCCESS ? createQualityGate() : null, createBranch()); } + private Optional getAnalysis() { + Long analysisDate = getAnalysisDate(); + + if (analysisDate != null) { + return of(new AnalysisImpl(analysisMetadataHolder.getUuid(), analysisDate)); + } else { + return empty(); + } + } + private static Project createProject(org.sonar.ce.queue.CeTask ceTask) { return new ProjectImpl( ceTask.getComponentUuid(), @@ -140,7 +152,7 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor @CheckForNull private QualityGateImpl createQualityGate() { - Optional qualityGateOptional = this.qualityGateHolder.getQualityGate(); + com.google.common.base.Optional qualityGateOptional = this.qualityGateHolder.getQualityGate(); if (qualityGateOptional.isPresent()) { org.sonar.server.computation.task.projectanalysis.qualitygate.QualityGate qualityGate = qualityGateOptional.get(); @@ -155,7 +167,7 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor @CheckForNull private BranchImpl createBranch() { - java.util.Optional analysisBranchOpt = analysisMetadataHolder.getBranch(); + Optional analysisBranchOpt = analysisMetadataHolder.getBranch(); if (analysisBranchOpt.isPresent() && !analysisBranchOpt.get().isLegacyFeature()) { org.sonar.server.computation.task.projectanalysis.analysis.Branch branch = analysisBranchOpt.get(); return new BranchImpl(branch.isMain(), branch.getName(), Branch.Type.valueOf(branch.getType().name())); @@ -179,29 +191,28 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor } private static Collection convert(Set conditions, Map statusPerConditions) { - return from(conditions) - .transform(new ConditionToCondition(statusPerConditions)) - .toList(); + return conditions.stream() + .map(new ConditionToCondition(statusPerConditions)::apply).collect(Collectors.toList()); } - private static class ProjectAnalysis implements PostProjectAnalysisTask.ProjectAnalysis { + private static class ProjectAnalysisImpl implements PostProjectAnalysisTask.ProjectAnalysis { private final CeTask ceTask; private final Project project; - @Nullable - private final Long analysisDate; private final long date; private final ScannerContext scannerContext; @Nullable private final QualityGate qualityGate; @Nullable private final Branch branch; + @Nullable + private final Analysis analysis; - private ProjectAnalysis(CeTask ceTask, Project project, - @Nullable Long analysisDate, long date, + private ProjectAnalysisImpl(CeTask ceTask, Project project, + @Nullable Analysis analysis, long date, ScannerContext scannerContext, @Nullable QualityGate qualityGate, @Nullable Branch branch) { this.ceTask = requireNonNull(ceTask, "ceTask can not be null"); this.project = requireNonNull(project, "project can not be null"); - this.analysisDate = analysisDate; + this.analysis = analysis; this.date = date; this.scannerContext = requireNonNull(scannerContext, "scannerContext can not be null"); this.qualityGate = qualityGate; @@ -219,8 +230,8 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor } @Override - public java.util.Optional getBranch() { - return java.util.Optional.ofNullable(branch); + public Optional getBranch() { + return ofNullable(branch); } @Override @@ -235,11 +246,13 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor } @Override - public java.util.Optional getAnalysisDate() { - if (analysisDate == null) { - return java.util.Optional.empty(); - } - return java.util.Optional.of(new Date(analysisDate)); + public Optional getAnalysisDate() { + return analysis == null ? empty() : ofNullable(analysis.getDate()); + } + + @Override + public Optional getAnalysis() { + return ofNullable(analysis); } @Override @@ -252,12 +265,32 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor return "ProjectAnalysis{" + "ceTask=" + ceTask + ", project=" + project + - ", analysisDate=" + analysisDate + ", date=" + date + ", scannerContext=" + scannerContext + ", qualityGate=" + qualityGate + + ", analysis=" + analysis + '}'; } } + private static class AnalysisImpl implements Analysis { + + private final String analysisUuid; + private final long date; + + private AnalysisImpl(String analysisUuid, long date) { + this.analysisUuid = analysisUuid; + this.date = date; + } + + @Override + public String getAnalysisUuid() { + return analysisUuid; + } + + @Override + public Date getDate() { + return new Date(date); + } + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookPostTask.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookPostTask.java index e489df52c14..4af599492d7 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookPostTask.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookPostTask.java @@ -19,12 +19,13 @@ */ package org.sonar.server.computation.task.projectanalysis.webhook; -import java.util.Date; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import org.sonar.api.ce.posttask.PostProjectAnalysisTask; import org.sonar.api.config.Configuration; import org.sonar.server.computation.task.projectanalysis.component.ConfigurationRepository; +import org.sonar.server.webhook.Analysis; import org.sonar.server.webhook.Branch; import org.sonar.server.webhook.CeTask; import org.sonar.server.webhook.Project; @@ -50,28 +51,32 @@ public class WebhookPostTask implements PostProjectAnalysisTask { webHooks.sendProjectAnalysisUpdate( config, - new WebHooks.Analysis(analysis.getProject().getUuid(), "", analysis.getCeTask().getId()), // FIXME + new WebHooks.Analysis( + analysis.getProject().getUuid(), + analysis.getAnalysis().map(org.sonar.api.ce.posttask.Analysis::getAnalysisUuid).orElse(null), + analysis.getCeTask().getId()), () -> payloadFactory.create(convert(analysis))); } - private static org.sonar.server.webhook.ProjectAnalysis convert(ProjectAnalysis analysis) { - return new org.sonar.server.webhook.ProjectAnalysis( - new CeTask(analysis.getCeTask().getId(), CeTask.Status.valueOf(analysis.getCeTask().getStatus().name())), - new Project(analysis.getProject().getUuid(), analysis.getProject().getKey(), analysis.getProject().getName()), - analysis.getBranch().map(b -> new Branch(b.isMain(), b.getName().orElse(null), Branch.Type.valueOf(b.getType().name()))).orElse(null), - Optional.ofNullable(analysis.getQualityGate()) - .map(qg -> new QualityGate( - qg.getId(), - qg.getName(), - QualityGate.Status.valueOf(qg.getStatus().name()), - qg.getConditions().stream() - .map(c -> new QualityGate.Condition(QualityGate.EvaluationStatus.valueOf(c.getStatus().name()), c.getMetricKey(), QualityGate.Operator.valueOf(c.getOperator().name()), - c.getErrorThreshold(), c.getWarningThreshold(), c.isOnLeakPeriod(), - c.getStatus() == org.sonar.api.ce.posttask.QualityGate.EvaluationStatus.NO_VALUE ? null : c.getValue())) - .collect(Collectors.toSet()))) - .orElse(null), - analysis.getAnalysisDate().map(Date::getTime).orElse(null), - analysis.getScannerContext().getProperties()); - } + private static org.sonar.server.webhook.ProjectAnalysis convert(ProjectAnalysis projectAnalysis) { + CeTask ceTask = new CeTask(projectAnalysis.getCeTask().getId(), CeTask.Status.valueOf(projectAnalysis.getCeTask().getStatus().name())); + Project project = new Project(projectAnalysis.getProject().getUuid(), projectAnalysis.getProject().getKey(), projectAnalysis.getProject().getName()); + Analysis analysis = projectAnalysis.getAnalysis().map(a -> new Analysis(a.getAnalysisUuid(), a.getDate())).orElse(null); + Branch branch = projectAnalysis.getBranch().map(b -> new Branch(b.isMain(), b.getName().orElse(null), Branch.Type.valueOf(b.getType().name()))).orElse(null); + QualityGate qualityGate = Optional.ofNullable(projectAnalysis.getQualityGate()) + .map(qg -> new QualityGate( + qg.getId(), + qg.getName(), + QualityGate.Status.valueOf(qg.getStatus().name()), + qg.getConditions().stream() + .map(c -> new QualityGate.Condition(QualityGate.EvaluationStatus.valueOf(c.getStatus().name()), c.getMetricKey(), QualityGate.Operator.valueOf(c.getOperator().name()), + c.getErrorThreshold(), c.getWarningThreshold(), c.isOnLeakPeriod(), + c.getStatus() == org.sonar.api.ce.posttask.QualityGate.EvaluationStatus.NO_VALUE ? null : c.getValue())) + .collect(Collectors.toSet()))) + .orElse(null); + Long date = projectAnalysis.getAnalysis().map(a -> a.getDate().getTime()).orElse(null); + Map properties = projectAnalysis.getScannerContext().getProperties(); + return new org.sonar.server.webhook.ProjectAnalysis(ceTask, project, analysis, branch, qualityGate, date, properties); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/Analysis.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/Analysis.java new file mode 100644 index 00000000000..a0a7c005b3a --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/Analysis.java @@ -0,0 +1,64 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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.server.webhook; + +import com.google.common.base.Objects; +import java.util.Date; + +import static java.util.Objects.requireNonNull; + +public final class Analysis { + private final String uuid; + private final Date date; + + public Analysis(String uuid, Date date) { + requireNonNull(uuid, "uuid must not be null"); + requireNonNull(date, "date must not be null"); + this.uuid = uuid; + this.date = date; + } + + public String getUuid() { + return uuid; + } + + public Date getDate() { + return date; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Analysis)) { + return false; + } + Analysis analysis = (Analysis) o; + return Objects.equal(uuid, analysis.uuid) && + Objects.equal(date, analysis.date); + } + + @Override + public int hashCode() { + return Objects.hashCode(uuid, date); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/ProjectAnalysis.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/ProjectAnalysis.java index 7184c57c9f2..ce1de8cc381 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/webhook/ProjectAnalysis.java +++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/ProjectAnalysis.java @@ -19,7 +19,6 @@ */ package org.sonar.server.webhook; -import java.util.Date; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -35,8 +34,9 @@ public class ProjectAnalysis { private final QualityGate qualityGate; private final Long date; private final Map properties; + private final Analysis analysis; - public ProjectAnalysis(CeTask ceTask, Project project, + public ProjectAnalysis(CeTask ceTask, Project project, @Nullable Analysis analysis, @Nullable Branch branch, @Nullable QualityGate qualityGate, @Nullable Long date, Map properties) { this.ceTask = requireNonNull(ceTask, "ceTask can't be null"); this.project = requireNonNull(project, "project can't be null"); @@ -44,6 +44,7 @@ public class ProjectAnalysis { this.qualityGate = qualityGate; this.date = date; this.properties = copyOf(requireNonNull(properties, "properties can't be null")); + this.analysis = analysis; } public CeTask getCeTask() { @@ -62,14 +63,14 @@ public class ProjectAnalysis { return Optional.ofNullable(qualityGate); } - public Optional getAnalysisDate() { - return Optional.ofNullable(date).map(Date::new); - } - public Map getProperties() { return properties; } + public Optional getAnalysis() { + return Optional.ofNullable(analysis); + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/WebHooks.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/WebHooks.java index a65a7526375..66bac2b535c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/webhook/WebHooks.java +++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/WebHooks.java @@ -19,7 +19,7 @@ */ package org.sonar.server.webhook; -import com.google.common.base.Objects; +import java.util.Objects; import java.util.function.Supplier; import javax.annotation.CheckForNull; import javax.annotation.Nullable; @@ -48,9 +48,9 @@ public interface WebHooks { private final String ceTaskUuid; private final String analysisUuid; - public Analysis(String projectUuid, String analysisUuid, @Nullable String ceTaskUuid) { + public Analysis(String projectUuid, @Nullable String analysisUuid, @Nullable String ceTaskUuid) { this.projectUuid = requireNonNull(projectUuid, "projectUuid can't be null"); - this.analysisUuid = requireNonNull(analysisUuid, "analysisUuid can't be null"); + this.analysisUuid = analysisUuid; this.ceTaskUuid = ceTaskUuid; } @@ -63,6 +63,7 @@ public interface WebHooks { return ceTaskUuid; } + @CheckForNull public String getAnalysisUuid() { return analysisUuid; } @@ -72,18 +73,18 @@ public interface WebHooks { if (this == o) { return true; } - if (!(o instanceof Analysis)) { + if (o == null || getClass() != o.getClass()) { return false; } Analysis analysis = (Analysis) o; - return Objects.equal(projectUuid, analysis.projectUuid) && - Objects.equal(ceTaskUuid, analysis.ceTaskUuid) && - Objects.equal(analysisUuid, analysis.analysisUuid); + return Objects.equals(projectUuid, analysis.projectUuid) && + Objects.equals(ceTaskUuid, analysis.ceTaskUuid) && + Objects.equals(analysisUuid, analysis.analysisUuid); } @Override public int hashCode() { - return Objects.hashCode(projectUuid, ceTaskUuid, analysisUuid); + return Objects.hash(projectUuid, ceTaskUuid, analysisUuid); } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/Webhook.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/Webhook.java index 1e43b9f1de1..07b43bf557b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/webhook/Webhook.java +++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/Webhook.java @@ -19,10 +19,12 @@ */ package org.sonar.server.webhook; -import javax.annotation.CheckForNull; +import java.util.Optional; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import static java.util.Objects.requireNonNull; +import static java.util.Optional.ofNullable; @Immutable public class Webhook { @@ -33,10 +35,10 @@ public class Webhook { private final String name; private final String url; - public Webhook(String componentUuid, String ceTaskUuid, String analysisUuid, String name, String url) { + public Webhook(String componentUuid, @Nullable String ceTaskUuid, @Nullable String analysisUuid, String name, String url) { this.componentUuid = requireNonNull(componentUuid); this.ceTaskUuid = ceTaskUuid; - this.analysisUuid = requireNonNull(analysisUuid); + this.analysisUuid = analysisUuid; this.name = requireNonNull(name); this.url = requireNonNull(url); } @@ -45,9 +47,8 @@ public class Webhook { return componentUuid; } - @CheckForNull - public String getCeTaskUuid() { - return ceTaskUuid; + public Optional getCeTaskUuid() { + return ofNullable(ceTaskUuid); } public String getName() { @@ -58,7 +59,7 @@ public class Webhook { return url; } - public String getAnalysisUuid() { - return analysisUuid; + public Optional getAnalysisUuid() { + return ofNullable(analysisUuid); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookDeliveryStorage.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookDeliveryStorage.java index 5824dc823df..0225b0a87b8 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookDeliveryStorage.java +++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookDeliveryStorage.java @@ -66,8 +66,8 @@ public class WebhookDeliveryStorage { WebhookDeliveryDto dto = new WebhookDeliveryDto(); dto.setUuid(uuidFactory.create()); dto.setComponentUuid(delivery.getWebhook().getComponentUuid()); - dto.setCeTaskUuid(delivery.getWebhook().getCeTaskUuid()); - dto.setAnalysisUuid(delivery.getWebhook().getAnalysisUuid()); + delivery.getWebhook().getCeTaskUuid().ifPresent(dto::setCeTaskUuid); + delivery.getWebhook().getAnalysisUuid().ifPresent(dto::setAnalysisUuid); dto.setName(delivery.getWebhook().getName()); dto.setUrl(delivery.getWebhook().getUrl()); dto.setSuccess(delivery.isSuccess()); diff --git a/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookPayloadFactoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookPayloadFactoryImpl.java index 613a0e985f1..b17fbd49b06 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookPayloadFactoryImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookPayloadFactoryImpl.java @@ -66,8 +66,8 @@ public class WebhookPayloadFactoryImpl implements WebhookPayloadFactory { } private static void writeDates(JsonWriter writer, ProjectAnalysis analysis, System2 system2) { - analysis.getAnalysisDate().ifPresent(date -> writer.propDateTime("analysedAt", date)); - writer.propDateTime("changedAt", analysis.getAnalysisDate().orElseGet(() -> new Date(system2.now()))); + analysis.getAnalysis().ifPresent(a -> writer.propDateTime("analysedAt", a.getDate())); + writer.propDateTime("changedAt", analysis.getAnalysis().map(Analysis::getDate).orElseGet(() -> new Date(system2.now()))); } private void writeProject(ProjectAnalysis analysis, JsonWriter writer, Project project) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java index e0f2d7c8a6d..1c9a6f786e9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java @@ -27,6 +27,7 @@ import java.util.Date; import java.util.List; import java.util.Optional; import javax.annotation.Nullable; +import org.apache.commons.lang.RandomStringUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -168,6 +169,7 @@ public class PostProjectAnalysisTasksExecutorTest { @Test public void date_comes_from_AnalysisMetadataHolder() { analysisMetadataHolder.setAnalysisDate(8_465_132_498L); + analysisMetadataHolder.setUuid(RandomStringUtils.randomAlphanumeric(40)); underTest.finished(true); @@ -190,24 +192,27 @@ public class PostProjectAnalysisTasksExecutorTest { } @Test - public void analysisDate_comes_from_AnalysisMetadataHolder_when_set() { + public void analysisDate_and_analysisUuid_comes_from_AnalysisMetadataHolder_when_set() { analysisMetadataHolder.setAnalysisDate(8465132498L); + analysisMetadataHolder.setUuid(RandomStringUtils.randomAlphanumeric(40)); underTest.finished(true); verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture()); - assertThat(projectAnalysisArgumentCaptor.getValue().getAnalysisDate()) - .contains(new Date(analysisMetadataHolder.getAnalysisDate())); + assertThat(projectAnalysisArgumentCaptor.getValue().getAnalysis().get().getDate()) + .isEqualTo(new Date(analysisMetadataHolder.getAnalysisDate())); + assertThat(projectAnalysisArgumentCaptor.getValue().getAnalysis().get().getAnalysisUuid()) + .isEqualTo(analysisMetadataHolder.getUuid()); } @Test - public void analysisDate_is_empty_when_not_set_in_AnalysisMetadataHolder() { + public void analysis_is_empty_when_not_set_in_AnalysisMetadataHolder() { underTest.finished(false); verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture()); - assertThat(projectAnalysisArgumentCaptor.getValue().getAnalysisDate()).isEmpty(); + assertThat(projectAnalysisArgumentCaptor.getValue().getAnalysis()).isEmpty(); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/Analysis.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/Analysis.java new file mode 100644 index 00000000000..cb91748a71d --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/Analysis.java @@ -0,0 +1,44 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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.server.computation.task.projectanalysis.webhook; + +import java.util.Date; + +public class Analysis implements org.sonar.api.ce.posttask.Analysis { + + private final String analysisUuid; + private final Long date; + + Analysis(String analysisUuid, Long date) { + this.analysisUuid = analysisUuid; + this.date = date; + } + + @Override + public String getAnalysisUuid() { + return analysisUuid; + } + + @Override + public Date getDate() { + return new Date(date); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/ProjectAnalysis.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/ProjectAnalysis.java new file mode 100644 index 00000000000..bfff4aef022 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/ProjectAnalysis.java @@ -0,0 +1,92 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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.server.computation.task.projectanalysis.webhook; + +import java.util.Date; +import java.util.Optional; +import javax.annotation.CheckForNull; +import org.sonar.api.ce.posttask.Analysis; +import org.sonar.api.ce.posttask.Branch; +import org.sonar.api.ce.posttask.CeTask; +import org.sonar.api.ce.posttask.PostProjectAnalysisTask; +import org.sonar.api.ce.posttask.Project; +import org.sonar.api.ce.posttask.QualityGate; +import org.sonar.api.ce.posttask.ScannerContext; + +public class ProjectAnalysis implements PostProjectAnalysisTask.ProjectAnalysis { + + private final Branch branch; + private final Project project; + private final CeTask ceTask; + private final QualityGate qualityGate; + private final Analysis analysis; + private final ScannerContext scannerContext; + + ProjectAnalysis(Project project, Branch branch, CeTask ceTask, QualityGate qualityGate, Analysis analysis, ScannerContext scannerContext) { + this.branch = branch; + this.project = project; + this.ceTask = ceTask; + this.qualityGate = qualityGate; + this.analysis = analysis; + this.scannerContext = scannerContext; + } + + @Override + public CeTask getCeTask() { + return ceTask; + } + + @Override + public Project getProject() { + return project; + } + + @Override + public Optional getBranch() { + return Optional.ofNullable(branch); + } + + @CheckForNull + @Override + public QualityGate getQualityGate() { + return qualityGate; + } + + @Override + public Date getDate() { + throw new UnsupportedOperationException(); + } + + @Override + public Optional getAnalysisDate() { + return analysis == null ? Optional.empty() : Optional.ofNullable(analysis.getDate()); + } + + @Override + public Optional getAnalysis() { + return Optional.ofNullable(analysis); + } + + @Override + public ScannerContext getScannerContext() { + return scannerContext; + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookPostTaskTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookPostTaskTest.java index 3169b72eb90..7b286d132b4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookPostTaskTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookPostTaskTest.java @@ -23,12 +23,15 @@ import java.util.Collections; import java.util.Date; import java.util.Random; import java.util.function.Supplier; +import javax.annotation.Nullable; +import org.apache.commons.lang.RandomStringUtils; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.sonar.api.ce.posttask.CeTask; import org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester; import org.sonar.api.ce.posttask.Project; +import org.sonar.api.ce.posttask.QualityGate; import org.sonar.api.config.Configuration; import org.sonar.server.computation.task.projectanalysis.component.ConfigurationRepository; import org.sonar.server.webhook.ProjectAnalysis; @@ -36,6 +39,7 @@ import org.sonar.server.webhook.WebHooks; import org.sonar.server.webhook.WebhookPayload; import org.sonar.server.webhook.WebhookPayloadFactory; +import static java.util.Collections.emptySet; import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; @@ -46,6 +50,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newCeTaskBuilder; import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newProjectBuilder; +import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newQualityGateBuilder; import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newScannerContextBuilder; public class WebhookPostTaskTest { @@ -65,6 +70,16 @@ public class WebhookPostTaskTest { @Test public void call_webhooks() { + callWebHooks(null, null); + QualityGate qualityGate = newQualityGateBuilder() + .setName("empty") + .setStatus(QualityGate.Status.OK) + .setId("1") + .build(); + callWebHooks(RandomStringUtils.randomAlphanumeric(40), qualityGate); + } + + private void callWebHooks(@Nullable String analysisUUid, @Nullable QualityGate qualityGate) { Project project = newProjectBuilder() .setUuid(randomAlphanumeric(3)) .setKey(randomAlphanumeric(4)) @@ -81,6 +96,8 @@ public class WebhookPostTaskTest { .withCeTask(ceTask) .withProject(project) .withScannerContext(newScannerContextBuilder().build()) + .withAnalysisUuid(analysisUUid) + .withQualityGate(qualityGate) .execute(); ArgumentCaptor supplierCaptor = ArgumentCaptor.forClass(Supplier.class); @@ -88,20 +105,26 @@ public class WebhookPostTaskTest { .sendProjectAnalysisUpdate( same(configuration), eq(new WebHooks.Analysis(project.getUuid(), - "", + analysisUUid, ceTask.getId())), supplierCaptor.capture()); assertThat(supplierCaptor.getValue().get()).isSameAs(webhookPayload); + org.sonar.server.webhook.QualityGate webQualityGate = null; + if (qualityGate != null) { + org.sonar.server.webhook.QualityGate.Status status = org.sonar.server.webhook.QualityGate.Status.valueOf(qualityGate.getStatus().name()); + webQualityGate = new org.sonar.server.webhook.QualityGate(qualityGate.getId(), qualityGate.getName(), status, emptySet()); + } + verify(payloadFactory).create(new ProjectAnalysis( new org.sonar.server.webhook.CeTask(ceTask.getId(), org.sonar.server.webhook.CeTask.Status.valueOf(ceTask.getStatus().name())), new org.sonar.server.webhook.Project(project.getUuid(), project.getKey(), project.getName()), null, null, - date.getTime(), + webQualityGate, + analysisUUid == null ? null : date.getTime(), Collections.emptyMap())); } - } diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/AnalysisTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/AnalysisTest.java new file mode 100644 index 00000000000..372af6594b9 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/AnalysisTest.java @@ -0,0 +1,78 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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.server.webhook; + +import java.util.Date; +import java.util.Random; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; +import static org.assertj.core.api.Assertions.assertThat; + +public class AnalysisTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void constructor_throws_NPE_when_uuid_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("uuid must not be null"); + + new Analysis(null, new Date()); + } + + @Test + public void constructor_throws_NPE_when_date_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("date must not be null"); + + new Analysis(randomAlphanumeric(40), null); + } + + @Test + public void test_equality() { + String uuid = randomAlphanumeric(35); + Date date = new Date(new Random().nextLong()); + Analysis underTest = new Analysis(uuid, date); + + assertThat(underTest).isEqualTo(underTest); + assertThat(underTest.getUuid()).isEqualTo(uuid); + assertThat(underTest.getDate()).isEqualTo(date); + + assertThat(underTest).isNotEqualTo(null); + assertThat(underTest).isNotEqualTo(new Analysis(uuid + "1", date)); + assertThat(underTest).isNotEqualTo(new Analysis(uuid, new Date(date.getTime() + 1_000))); + } + + @Test + public void test_hashcode() { + String uuid = randomAlphanumeric(35); + Date date = new Date(new Random().nextLong()); + Analysis underTest = new Analysis(uuid, date); + + assertThat(underTest.hashCode()).isEqualTo(underTest.hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new Analysis(uuid + "1", date).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new Analysis(uuid, new Date(date.getTime() + 1_000)).hashCode()); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/ProjectAnalysisTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/ProjectAnalysisTest.java index 1cad78c7c02..ac25205e134 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/webhook/ProjectAnalysisTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/ProjectAnalysisTest.java @@ -36,11 +36,13 @@ public class ProjectAnalysisTest { private final CeTask ceTask = new CeTask("id", CeTask.Status.SUCCESS); private final Project project = new Project("uuid", "key", "name"); + private final Analysis analysis = new Analysis("analysis_uuid", new Date()); private final Branch branch = new Branch(true, "name", Branch.Type.SHORT); private final QualityGate qualityGate = new QualityGate("id", "name", QualityGate.Status.WARN, emptySet()); private final Map properties = ImmutableMap.of("a", "b"); private ProjectAnalysis underTest = new ProjectAnalysis(ceTask, project, + analysis, branch, qualityGate, 1L, @@ -54,6 +56,7 @@ public class ProjectAnalysisTest { new ProjectAnalysis(null, project, + analysis, branch, qualityGate, 1L, @@ -68,6 +71,7 @@ public class ProjectAnalysisTest { new ProjectAnalysis(ceTask, null, + analysis, branch, qualityGate, 1L, @@ -82,6 +86,7 @@ public class ProjectAnalysisTest { new ProjectAnalysis(ceTask, project, + analysis, branch, qualityGate, 1L, @@ -94,52 +99,54 @@ public class ProjectAnalysisTest { assertThat(underTest.getProject()).isSameAs(project); assertThat(underTest.getBranch().get()).isSameAs(branch); assertThat(underTest.getQualityGate().get()).isSameAs(qualityGate); - assertThat(underTest.getAnalysisDate()).contains(new Date(1L)); assertThat(underTest.getProperties()).isEqualTo(properties); + assertThat(underTest.getAnalysis().get()).isEqualTo(analysis); - ProjectAnalysis underTestWithNulls = new ProjectAnalysis(ceTask, project, null, null, null, emptyMap()); + ProjectAnalysis underTestWithNulls = new ProjectAnalysis(ceTask, project, null, null, null, null, emptyMap()); assertThat(underTestWithNulls.getBranch()).isEmpty(); assertThat(underTestWithNulls.getQualityGate()).isEmpty(); - assertThat(underTestWithNulls.getAnalysisDate()).isEmpty(); assertThat(underTestWithNulls.getProperties()).isEmpty(); + assertThat(underTestWithNulls.getAnalysis()).isEmpty(); } @Test public void defines_equals_based_on_all_fields() { assertThat(underTest).isEqualTo(underTest); - assertThat(underTest).isEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, properties)); + assertThat(underTest).isEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, qualityGate, 1L, properties)); assertThat(underTest).isNotEqualTo(null); assertThat(underTest).isNotEqualTo(new Object()); - assertThat(underTest).isNotEqualTo(new ProjectAnalysis(new CeTask("2", CeTask.Status.SUCCESS), project, branch, qualityGate, 1L, properties)); - assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), branch, qualityGate, 1L, properties)); - assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), branch, qualityGate, 1L, properties)); - assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, null, qualityGate, 1L, properties)); - assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, new Branch(false, "B", Branch.Type.SHORT), qualityGate, 1L, properties)); - assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, null, 1L, properties)); - assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, new QualityGate("A", "B", QualityGate.Status.WARN, emptySet()), 1L, properties)); - assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, null, properties)); - assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 2L, properties)); - assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, emptyMap())); - assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, ImmutableMap.of("A", "B"))); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(new CeTask("2", CeTask.Status.SUCCESS), project, analysis, branch, qualityGate, 1L, properties)); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), analysis, branch, qualityGate, 1L, properties)); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), analysis, branch, qualityGate, 1L, properties)); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, null, null, qualityGate, 1L, properties)); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, null, qualityGate, 1L, properties)); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, new Branch(false, "B", Branch.Type.SHORT), qualityGate, 1L, properties)); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, null, 1L, properties)); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, new QualityGate("A", "B", QualityGate.Status.WARN, emptySet()), 1L, properties)); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, qualityGate, null, properties)); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, qualityGate, 2L, properties)); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, qualityGate, 1L, emptyMap())); + assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, qualityGate, 1L, ImmutableMap.of("A", "B"))); } @Test public void defines_hashcode_based_on_all_fields() { assertThat(underTest.hashCode()).isEqualTo(underTest.hashCode()); - assertThat(underTest.hashCode()).isEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, properties).hashCode()); + assertThat(underTest.hashCode()).isEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, qualityGate, 1L, properties).hashCode()); assertThat(underTest.hashCode()).isNotEqualTo(new Object().hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(new CeTask("2", CeTask.Status.SUCCESS), project, branch, qualityGate, 1L, properties).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), branch, qualityGate, 1L, properties).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), branch, qualityGate, 1L, properties).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, null, qualityGate, 1L, properties).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, new Branch(false, "B", Branch.Type.SHORT), qualityGate, 1L, properties).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, null, 1L, properties).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(new CeTask("2", CeTask.Status.SUCCESS), project, analysis, branch, qualityGate, 1L, properties).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), analysis, branch, qualityGate, 1L, properties).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), analysis, branch, qualityGate, 1L, properties).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, null, null, qualityGate, 1L, properties).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, null, qualityGate, 1L, properties).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, new Branch(false, "B", Branch.Type.SHORT), qualityGate, 1L, properties).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, null, 1L, properties).hashCode()); assertThat(underTest.hashCode()) - .isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, new QualityGate("A", "B", QualityGate.Status.WARN, emptySet()), 1L, properties).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, null, properties).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 2L, properties).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, emptyMap()).hashCode()); - assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, ImmutableMap.of("B", "C")).hashCode()); + .isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, new QualityGate("A", "B", QualityGate.Status.WARN, emptySet()), 1L, properties).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, qualityGate, null, properties).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, qualityGate, 2L, properties).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, qualityGate, 1L, emptyMap()).hashCode()); + assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, analysis, branch, qualityGate, 1L, ImmutableMap.of("B", "C")).hashCode()); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookDeliveryStorageTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookDeliveryStorageTest.java index 4477054190e..681486a370e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookDeliveryStorageTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookDeliveryStorageTest.java @@ -63,7 +63,7 @@ public class WebhookDeliveryStorageTest { WebhookDeliveryDto dto = dbClient.webhookDeliveryDao().selectByUuid(dbSession, DELIVERY_UUID).get(); assertThat(dto.getUuid()).isEqualTo(DELIVERY_UUID); assertThat(dto.getComponentUuid()).isEqualTo(delivery.getWebhook().getComponentUuid()); - assertThat(dto.getCeTaskUuid()).isEqualTo(delivery.getWebhook().getCeTaskUuid()); + assertThat(dto.getCeTaskUuid()).isEqualTo(delivery.getWebhook().getCeTaskUuid().get()); assertThat(dto.getName()).isEqualTo(delivery.getWebhook().getName()); assertThat(dto.getUrl()).isEqualTo(delivery.getWebhook().getUrl()); assertThat(dto.getCreatedAt()).isEqualTo(delivery.getAt()); diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookPayloadFactoryImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookPayloadFactoryImplTest.java index 56aea60cf48..919d10db577 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookPayloadFactoryImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookPayloadFactoryImplTest.java @@ -20,6 +20,7 @@ package org.sonar.server.webhook; import com.google.common.collect.ImmutableMap; +import java.util.Date; import java.util.Map; import javax.annotation.Nullable; import org.junit.Before; @@ -268,7 +269,6 @@ public class WebhookPayloadFactoryImplTest { private static ProjectAnalysis newAnalysis(CeTask task, @Nullable QualityGate gate, @Nullable Branch branch, @Nullable Long analysisDate, Map scannerProperties) { - return new ProjectAnalysis(task, new Project("P1_UUID", PROJECT_KEY, "Project One"), branch, gate, analysisDate, scannerProperties); + return new ProjectAnalysis(task, new Project("P1_UUID", PROJECT_KEY, "Project One"), analysisDate == null ? null : new Analysis("A_UUID1", new Date(analysisDate)), branch, gate, analysisDate, scannerProperties); } - } diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookTest.java new file mode 100644 index 00000000000..fb731fdabfb --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookTest.java @@ -0,0 +1,79 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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.server.webhook; + +import java.util.Optional; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; +import static org.assertj.core.api.Assertions.assertThat; + +public class WebhookTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void constructor_with_null_componentUuid_should_throw_NPE() { + expectedException.expect(NullPointerException.class); + + new Webhook(null, null, null, randomAlphanumeric(10), randomAlphanumeric(10)); + } + + @Test + public void constructor_with_null_name_should_throw_NPE() { + expectedException.expect(NullPointerException.class); + + new Webhook(randomAlphanumeric(10), null, null, null, randomAlphanumeric(10)); + } + + @Test + public void constructor_with_null_url_should_throw_NPE() { + expectedException.expect(NullPointerException.class); + + new Webhook(randomAlphanumeric(10), null, null, randomAlphanumeric(10), null); + } + + @Test + public void constructor_with_null_ceTaskUuid_or_analysisUuidurl_should_return_Optional_empty() { + String componentUuid = randomAlphanumeric(10); + String name = randomAlphanumeric(10); + String url = randomAlphanumeric(10); + Webhook underTest = new Webhook(componentUuid, null, null, name, url); + + assertThat(underTest.getComponentUuid()).isEqualTo(componentUuid); + assertThat(underTest.getName()).isEqualTo(name); + assertThat(underTest.getUrl()).isEqualTo(url); + assertThat(underTest.getCeTaskUuid()).isEqualTo(Optional.empty()); + assertThat(underTest.getAnalysisUuid()).isEqualTo(Optional.empty()); + + String ceTaskUuid = randomAlphanumeric(10); + String analysisUuid = randomAlphanumeric(10); + underTest = new Webhook(componentUuid, ceTaskUuid, analysisUuid, name, url); + assertThat(underTest.getComponentUuid()).isEqualTo(componentUuid); + assertThat(underTest.getName()).isEqualTo(name); + assertThat(underTest.getUrl()).isEqualTo(url); + assertThat(underTest.getCeTaskUuid().get()).isEqualTo(ceTaskUuid); + assertThat(underTest.getAnalysisUuid().get()).isEqualTo(analysisUuid); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/Analysis.java b/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/Analysis.java new file mode 100644 index 00000000000..b8f10fd6607 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/Analysis.java @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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.api.ce.posttask; + +import java.util.Date; + +public interface Analysis { + /** + * UUID of the analysis + */ + String getAnalysisUuid(); + + /** + * Date of the analysis. + */ + Date getDate(); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTask.java b/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTask.java index c63043a85e2..d8c2a07640b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTask.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTask.java @@ -80,7 +80,7 @@ public interface PostProjectAnalysisTask { *

* This date is the same as the date of the project analysis report and the snapshot. * - * @deprecated use {@link #getAnalysisDate()} instead. When {@link #getAnalysisDate()} returns + * @deprecated use {@link #getAnalysis().getDate()} instead. When {@link #getAnalysis()} returns * {@link Optional#empty() empty}, the current date will be returned. */ @Deprecated @@ -92,9 +92,21 @@ public interface PostProjectAnalysisTask { * This date is the same as the date of the project analysis report and therefore as the analysis in DB. It can be * missing when the status of the task is {@link org.sonar.api.ce.posttask.CeTask.Status#FAILED FAILED}. *

+ * @deprecated use {@link #getAnalysis().getDate()} instead */ + @Deprecated Optional getAnalysisDate(); + /** + * Analysis containing the UUID of the analysis and the date + * + *

+ * This Analysis can be missing when the status of the task is + * {@link org.sonar.api.ce.posttask.CeTask.Status#FAILED FAILED}. + *

+ */ + Optional getAnalysis(); + /** * Context as defined by scanner through {@link org.sonar.api.batch.sensor.SensorContext#addContextProperty(String, String)}. * It does not contain the settings used by scanner. diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTester.java index 2ab390b0cff..34f861791b7 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTester.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTester.java @@ -70,6 +70,7 @@ import static java.util.Objects.requireNonNull; * .setName("name") * .build()) * .at(new Date()) + * .withAnalysisUuid("uuid") * .withQualityGate( * newQualityGateBuilder() * .setId("id") @@ -111,6 +112,7 @@ public class PostProjectAnalysisTaskTester { @CheckForNull private Branch branch; private ScannerContext scannerContext; + private String analysisUuid; private PostProjectAnalysisTaskTester(PostProjectAnalysisTask underTest) { this.underTest = requireNonNull(underTest, "PostProjectAnalysisTask instance cannot be null"); @@ -177,59 +179,39 @@ public class PostProjectAnalysisTaskTester { return this; } + /** + * @since 6.6 + */ + public PostProjectAnalysisTaskTester withAnalysisUuid(@Nullable String analysisUuid) { + this.analysisUuid = analysisUuid; + return this; + } + public PostProjectAnalysisTask.ProjectAnalysis execute() { requireNonNull(ceTask, CE_TASK_CAN_NOT_BE_NULL); requireNonNull(project, PROJECT_CAN_NOT_BE_NULL); requireNonNull(date, DATE_CAN_NOT_BE_NULL); - PostProjectAnalysisTask.ProjectAnalysis projectAnalysis = new PostProjectAnalysisTask.ProjectAnalysis() { - @Override - public ScannerContext getScannerContext() { - return scannerContext; - } - - @Override - public CeTask getCeTask() { - return ceTask; - } - - @Override - public Project getProject() { - return project; - } - - @Override - public Optional getBranch() { - return Optional.ofNullable(branch); - } - - @Override - public QualityGate getQualityGate() { - return qualityGate; - } - - @Override - public Date getDate() { - return date; - } - - @Override - public Optional getAnalysisDate() { - return Optional.of(date); - } - - @Override - public String toString() { - return "ProjectAnalysis{" + - "ceTask=" + ceTask + - ", project=" + project + - ", date=" + date.getTime() + - ", analysisDate=" + date.getTime() + - ", qualityGate=" + qualityGate + - '}'; - } - }; - this.underTest.finished(projectAnalysis); + Analysis analysis = null; + if (date != null && analysisUuid != null) { + analysis = new AnalysisBuilder() + .setDate(date) + .setAnalysisUuid(analysisUuid) + .build(); + } + + PostProjectAnalysisTask.ProjectAnalysis projectAnalysis = new ProjectAnalysisBuilder() + .setCeTask(ceTask) + .setProject(project) + .setBranch(branch) + .setQualityGate(qualityGate) + .setAnalysis(analysis) + .setScannerContext(scannerContext) + .setDate(date) + .build(); + + this.underTest. + finished(projectAnalysis); return projectAnalysis; } @@ -634,4 +616,143 @@ public class PostProjectAnalysisTaskTester { return () -> properties; } } + + public static final class ProjectAnalysisBuilder { + private CeTask ceTask; + private Project project; + private Branch branch; + private QualityGate qualityGate; + private Analysis analysis; + private ScannerContext scannerContext; + private Date date; + + private ProjectAnalysisBuilder() { + // prevents instantiation outside PostProjectAnalysisTaskTester + } + + public ProjectAnalysisBuilder setCeTask(CeTask ceTask) { + this.ceTask = ceTask; + return this; + } + + public ProjectAnalysisBuilder setProject(Project project) { + this.project = project; + return this; + } + + public ProjectAnalysisBuilder setBranch(@Nullable Branch branch) { + this.branch = branch; + return this; + } + + public ProjectAnalysisBuilder setQualityGate(QualityGate qualityGate) { + this.qualityGate = qualityGate; + return this; + } + + public ProjectAnalysisBuilder setAnalysis(@Nullable Analysis analysis) { + this.analysis = analysis; + return this; + } + + public ProjectAnalysisBuilder setScannerContext(ScannerContext scannerContext) { + this.scannerContext = scannerContext; + return this; + } + + public ProjectAnalysisBuilder setDate(Date date) { + this.date = date; + return this; + } + + public PostProjectAnalysisTask.ProjectAnalysis build() { + return new PostProjectAnalysisTask.ProjectAnalysis() { + @Override + public CeTask getCeTask() { + return ceTask; + } + + @Override + public Project getProject() { + return project; + } + + @Override + public Optional getBranch() { + return Optional.ofNullable(branch); + } + + @CheckForNull + @Override + public QualityGate getQualityGate() { + return qualityGate; + } + + @Override + public Date getDate() { + return date; + } + + @Override + public Optional getAnalysisDate() { + return getAnalysis().map(Analysis::getDate); + } + + @Override + public Optional getAnalysis() { + return Optional.ofNullable(analysis); + } + + @Override + public ScannerContext getScannerContext() { + return scannerContext; + } + + @Override + public String toString() { + return "ProjectAnalysis{" + + "ceTask=" + ceTask + + ", project=" + project + + ", date=" + date.getTime() + + ", analysisDate=" + date.getTime() + + ", qualityGate=" + qualityGate + + '}'; + } + }; + } + } + + public static final class AnalysisBuilder { + private String analysisUuid; + private Date date; + + private AnalysisBuilder() { + // prevents instantiation outside PostProjectAnalysisTaskTester + } + + public AnalysisBuilder setAnalysisUuid(String analysisUuid) { + this.analysisUuid = analysisUuid; + return this; + } + + public AnalysisBuilder setDate(Date date) { + this.date = date; + return this; + } + + public Analysis build() { + return new Analysis() { + + @Override + public String getAnalysisUuid() { + return analysisUuid; + } + + @Override + public Date getDate() { + return date; + } + }; + } + } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTesterTest.java index 7696b02c7ad..baec1f163e7 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTesterTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTesterTest.java @@ -20,6 +20,7 @@ package org.sonar.api.ce.posttask; import java.util.Date; +import org.apache.commons.lang.RandomStringUtils; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -36,6 +37,7 @@ public class PostProjectAnalysisTaskTesterTest { private Project project = mock(Project.class); private long someDateAsLong = 846351351684351L; private Date someDate = new Date(someDateAsLong); + private String analysisUuid = RandomStringUtils.randomAlphanumeric(40); private QualityGate qualityGate = mock(QualityGate.class); private CaptorPostProjectAnalysisTask captorPostProjectAnalysisTask = new CaptorPostProjectAnalysisTask(); private PostProjectAnalysisTaskTester underTest = PostProjectAnalysisTaskTester.of(captorPostProjectAnalysisTask); @@ -99,7 +101,7 @@ public class PostProjectAnalysisTaskTesterTest { @Test public void verify_getters_of_ProjectAnalysis_object_passed_to_PostProjectAnalysisTask() { - underTest.withCeTask(ceTask).withProject(project).withQualityGate(qualityGate).at(someDate); + underTest.withCeTask(ceTask).withProject(project).withQualityGate(qualityGate).withAnalysisUuid(analysisUuid).at(someDate); underTest.execute(); @@ -109,6 +111,7 @@ public class PostProjectAnalysisTaskTesterTest { assertThat(projectAnalysis.getProject()).isSameAs(project); assertThat(projectAnalysis.getDate()).isSameAs(someDate); assertThat(projectAnalysis.getQualityGate()).isSameAs(qualityGate); + assertThat(projectAnalysis.getAnalysis().get().getAnalysisUuid()).isSameAs(analysisUuid); } @Test -- 2.39.5