From 1484ea4e115e549d260bb9fad2a6f114284dbd10 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Wed, 17 Jan 2018 11:39:05 +0100 Subject: [PATCH] SONAR-10247 add and populate QGChangeEvent#getPreviousStatus --- .../measure/live/LiveMeasureComputerImpl.java | 27 +++- .../changeevent/QGChangeEvent.java | 11 +- .../live/LiveMeasureComputerImplTest.java | 138 +++++++++++++++--- .../changeevent/QGChangeEventTest.java | 34 ++++- .../WebhookQGChangeEventListenerTest.java | 24 +-- 5 files changed, 186 insertions(+), 48 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java index 3f6f986c236..4bfc67be844 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java @@ -24,10 +24,14 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; +import javax.annotation.CheckForNull; import org.sonar.api.config.Configuration; +import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; +import org.sonar.api.utils.log.Loggers; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.BranchDto; @@ -109,9 +113,9 @@ public class LiveMeasureComputerImpl implements LiveMeasureComputer { DebtRatingGrid debtRatingGrid = new DebtRatingGrid(config); MeasureMatrix matrix = new MeasureMatrix(components, metricsPerId.values(), dbMeasures); + FormulaContextImpl context = new FormulaContextImpl(matrix, debtRatingGrid); components.forEach(c -> { IssueCounter issueCounter = new IssueCounter(dbClient.issueDao().selectIssueGroupsByBaseComponent(dbSession, c, beginningOfLeakPeriod.orElse(Long.MAX_VALUE))); - FormulaContextImpl context = new FormulaContextImpl(matrix, debtRatingGrid); for (IssueMetricFormula formula : formulaFactory.getFormulas()) { // exclude leak formulas when leak period is not defined if (beginningOfLeakPeriod.isPresent() || !formula.isOnLeak()) { @@ -131,7 +135,26 @@ public class LiveMeasureComputerImpl implements LiveMeasureComputer { matrix.getChanged().forEach(m -> dbClient.liveMeasureDao().insertOrUpdate(dbSession, m, null)); projectIndexer.commitAndIndex(dbSession, singleton(project), ProjectIndexer.Cause.MEASURE_CHANGE); - return Optional.of(new QGChangeEvent(project, branch, lastAnalysis.get(), config, () -> Optional.of(evaluatedQualityGate))); + Metric.Level previousStatus = loadPreviousStatus(project, matrix); + return Optional.of( + new QGChangeEvent(project, branch, lastAnalysis.get(), config, previousStatus, () -> Optional.of(evaluatedQualityGate))); + } + + @CheckForNull + private static Metric.Level loadPreviousStatus(ComponentDto project, MeasureMatrix matrix) { + return matrix.getMeasure(project, CoreMetrics.ALERT_STATUS_KEY) + .map(liveMeasureDto -> liveMeasureDto.getTextValue()) + .filter(Objects::nonNull) + .map(m -> { + try { + return Metric.Level.valueOf(m); + } catch (IllegalArgumentException e) { + Loggers.get(LiveMeasureComputerImpl.class) + .trace("Failed to parse value of metric '{}'", m, e); + return null; + } + }) + .orElse(null); } private List loadTreeOfComponents(DbSession dbSession, List touchedComponents) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java index 7b8f6a6b0d4..d0ec3241844 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEvent.java @@ -21,8 +21,10 @@ package org.sonar.server.qualitygate.changeevent; import java.util.Optional; import java.util.function.Supplier; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import org.sonar.api.config.Configuration; +import org.sonar.api.measures.Metric; import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.SnapshotDto; @@ -36,14 +38,16 @@ public class QGChangeEvent { private final BranchDto branch; private final SnapshotDto analysis; private final Configuration projectConfiguration; + private final Metric.Level previousStatus; private final Supplier> qualityGateSupplier; public QGChangeEvent(ComponentDto project, BranchDto branch, SnapshotDto analysis, Configuration projectConfiguration, - Supplier> qualityGateSupplier) { + @Nullable Metric.Level previousStatus, Supplier> qualityGateSupplier) { this.project = requireNonNull(project, "project can't be null"); this.branch = requireNonNull(branch, "branch can't be null"); this.analysis = requireNonNull(analysis, "analysis can't be null"); this.projectConfiguration = requireNonNull(projectConfiguration, "projectConfiguration can't be null"); + this.previousStatus = previousStatus; this.qualityGateSupplier = requireNonNull(qualityGateSupplier, "qualityGateSupplier can't be null"); } @@ -63,6 +67,10 @@ public class QGChangeEvent { return projectConfiguration; } + public Optional getPreviousStatus() { + return Optional.ofNullable(previousStatus); + } + public Supplier> getQualityGateSupplier() { return qualityGateSupplier; } @@ -74,6 +82,7 @@ public class QGChangeEvent { ", branch=" + toString(branch) + ", analysis=" + toString(analysis) + ", projectConfiguration=" + projectConfiguration + + ", previousStatus=" + previousStatus + ", qualityGateSupplier=" + qualityGateSupplier + '}'; } diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/live/LiveMeasureComputerImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/live/LiveMeasureComputerImplTest.java index be76582d739..c93037ddc44 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/live/LiveMeasureComputerImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/live/LiveMeasureComputerImplTest.java @@ -19,28 +19,39 @@ */ package org.sonar.server.measure.live; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.mockito.Mockito; +import org.junit.runner.RunWith; import org.sonar.api.config.PropertyDefinitions; import org.sonar.api.config.internal.MapSettings; +import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; import org.sonar.api.resources.Qualifiers; import org.sonar.core.config.CorePropertyDefinitions; +import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.component.BranchDto; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.metric.MetricDto; +import org.sonar.db.organization.OrganizationDto; import org.sonar.server.computation.task.projectanalysis.qualitymodel.Rating; import org.sonar.server.es.ProjectIndexer; import org.sonar.server.es.TestProjectIndexers; +import org.sonar.server.qualitygate.EvaluatedQualityGate; +import org.sonar.server.qualitygate.QualityGate; import org.sonar.server.qualitygate.changeevent.QGChangeEvent; import org.sonar.server.settings.ProjectConfigurationLoader; import org.sonar.server.settings.TestProjectConfigurationLoader; @@ -49,9 +60,15 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.singleton; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.same; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.sonar.api.resources.Qualifiers.ORDERED_BOTTOM_UP; +@RunWith(DataProviderRunner.class) public class LiveMeasureComputerImplTest { @Rule @@ -62,23 +79,30 @@ public class LiveMeasureComputerImplTest { private TestProjectIndexers projectIndexer = new TestProjectIndexers(); private MetricDto intMetric; private MetricDto ratingMetric; + private MetricDto alertStatusMetric; + private OrganizationDto organization; private ComponentDto project; private ComponentDto dir; private ComponentDto file1; private ComponentDto file2; + private LiveQualityGateComputer qGateComputer = mock(LiveQualityGateComputer.class); + private QualityGate qualityGate = mock(QualityGate.class); + private EvaluatedQualityGate newQualityGate = mock(EvaluatedQualityGate.class); @Before public void setUp() throws Exception { intMetric = db.measures().insertMetric(m -> m.setValueType(Metric.ValueType.INT.name())); ratingMetric = db.measures().insertMetric(m -> m.setValueType(Metric.ValueType.RATING.name())); - project = db.components().insertMainBranch(); + alertStatusMetric = db.measures().insertMetric(m -> m.setKey(CoreMetrics.ALERT_STATUS_KEY)); + organization = db.organizations().insert(); + project = db.components().insertMainBranch(organization); dir = db.components().insertComponent(ComponentTesting.newDirectory(project, "src/main/java")); file1 = db.components().insertComponent(ComponentTesting.newFileDto(project, dir)); file2 = db.components().insertComponent(ComponentTesting.newFileDto(project, dir)); } @Test - public void compute_and_insert_measures_if_they_dont_exist_yet() { + public void compute_and_insert_measures_if_they_do_not_exist_yet() { markProjectAsAnalyzed(project); List result = run(asList(file1, file2), newQualifierBasedIntFormula(), newRatingConstantFormula(Rating.C)); @@ -171,11 +195,11 @@ public class LiveMeasureComputerImplTest { public void refresh_leak_measures() { markProjectAsAnalyzed(project); db.measures().insertLiveMeasure(project, intMetric, m -> m.setVariation(42.0).setValue(null)); - db.measures().insertLiveMeasure(project, ratingMetric, m -> m.setVariation((double)Rating.E.getIndex())); + db.measures().insertLiveMeasure(project, ratingMetric, m -> m.setVariation((double) Rating.E.getIndex())); db.measures().insertLiveMeasure(dir, intMetric, m -> m.setVariation(42.0).setValue(null)); - db.measures().insertLiveMeasure(dir, ratingMetric, m -> m.setVariation((double)Rating.D.getIndex())); + db.measures().insertLiveMeasure(dir, ratingMetric, m -> m.setVariation((double) Rating.D.getIndex())); db.measures().insertLiveMeasure(file1, intMetric, m -> m.setVariation(42.0).setValue(null)); - db.measures().insertLiveMeasure(file1, ratingMetric, m -> m.setVariation((double)Rating.C.getIndex())); + db.measures().insertLiveMeasure(file1, ratingMetric, m -> m.setVariation((double) Rating.C.getIndex())); // generates values 1, 2, 3 on leak measures List result = run(file1, newQualifierBasedIntLeakFormula(), newRatingLeakFormula(Rating.B)); @@ -193,7 +217,7 @@ public class LiveMeasureComputerImplTest { } @Test - public void do_nothing_if_project_has_not_being_analyzed() { + public void do_nothing_if_project_has_not_been_analyzed() { // project has no snapshots List result = run(file1, newIncrementalFormula()); @@ -236,8 +260,90 @@ public class LiveMeasureComputerImplTest { } @Test - public void compute_quality_gate_status() { - // FIXME + public void event_contains_no_previousStatus_if_measure_does_not_exist() { + markProjectAsAnalyzed(project); + + List result = run(file1); + + assertThat(result) + .extracting(QGChangeEvent::getPreviousStatus) + .containsExactly(Optional.empty()); + } + + @Test + public void event_contains_no_previousStatus_if_measure_exists_and_has_no_value() { + markProjectAsAnalyzed(project); + db.measures().insertLiveMeasure(project, alertStatusMetric, m -> m.setData((String) null)); + + List result = run(file1); + + assertThat(result) + .extracting(QGChangeEvent::getPreviousStatus) + .containsExactly(Optional.empty()); + } + + @Test + public void event_contains_no_previousStatus_if_measure_exists_and_is_empty() { + markProjectAsAnalyzed(project); + db.measures().insertLiveMeasure(project, alertStatusMetric, m -> m.setData("")); + + List result = run(file1); + + assertThat(result) + .extracting(QGChangeEvent::getPreviousStatus) + .containsExactly(Optional.empty()); + } + + @Test + public void event_contains_no_previousStatus_if_measure_exists_and_is_not_a_level() { + markProjectAsAnalyzed(project); + db.measures().insertLiveMeasure(project, alertStatusMetric, m -> m.setData("fooBar")); + + List result = run(file1); + + assertThat(result) + .extracting(QGChangeEvent::getPreviousStatus) + .containsExactly(Optional.empty()); + } + + @Test + @UseDataProvider("metricLevels") + public void event_contains_previousStatus_if_measure_exists(Metric.Level level) { + markProjectAsAnalyzed(project); + db.measures().insertLiveMeasure(project, alertStatusMetric, m -> m.setData(level.name())); + db.measures().insertLiveMeasure(project, intMetric, m -> m.setVariation(42.0).setValue(null)); + + List result = run(file1, newQualifierBasedIntLeakFormula()); + + assertThat(result) + .extracting(QGChangeEvent::getPreviousStatus) + .containsExactly(Optional.of(level)); + } + + @DataProvider + public static Object[][] metricLevels() { + return Arrays.stream(Metric.Level.values()) + .map(l -> new Object[] {l}) + .toArray(Object[][]::new); + } + + @Test + public void event_contains_newQualityGate_computed_by_LiveQualityGateComputer() { + markProjectAsAnalyzed(project); + db.measures().insertLiveMeasure(project, alertStatusMetric, m -> m.setData(Metric.Level.WARN.name())); + db.measures().insertLiveMeasure(project, intMetric, m -> m.setVariation(42.0).setValue(null)); + BranchDto branch = db.getDbClient().branchDao().selectByKey(db.getSession(), project.projectUuid(), "master") + .orElseThrow(() -> new IllegalStateException("Can't find master branch")); + + List result = run(file1, newQualifierBasedIntLeakFormula()); + + assertThat(result) + .extracting(QGChangeEvent::getQualityGateSupplier) + .extracting(Supplier::get) + .containsExactly(Optional.of(newQualityGate)); + verify(qGateComputer).loadQualityGate(any(DbSession.class), eq(organization), eq(project), eq(branch)); + verify(qGateComputer).getMetricsRelatedTo(qualityGate); + verify(qGateComputer).refreshGateStatus(eq(project), same(qualityGate), any(MeasureMatrix.class)); } @Test @@ -260,7 +366,11 @@ public class LiveMeasureComputerImplTest { private List run(Collection components, IssueMetricFormula... formulas) { IssueMetricFormulaFactory formulaFactory = new TestIssueMetricFormulaFactory(asList(formulas)); - LiveQualityGateComputer qGateComputer = mock(LiveQualityGateComputer.class, Mockito.RETURNS_DEEP_STUBS); + when(qGateComputer.loadQualityGate(any(DbSession.class), any(OrganizationDto.class), any(ComponentDto.class), any(BranchDto.class))) + .thenReturn(qualityGate); + when(qGateComputer.getMetricsRelatedTo(qualityGate)).thenReturn(singleton(CoreMetrics.ALERT_STATUS_KEY)); + when(qGateComputer.refreshGateStatus(eq(project), same(qualityGate), any(MeasureMatrix.class))) + .thenReturn(newQualityGate); MapSettings settings = new MapSettings(new PropertyDefinitions(CorePropertyDefinitions.all())); ProjectConfigurationLoader configurationLoader = new TestProjectConfigurationLoader(settings.asConfig()); @@ -332,14 +442,6 @@ public class LiveMeasureComputerImplTest { }); } - private IssueMetricFormula newIncrementalLeakFormula() { - Metric metric = new Metric.Builder(intMetric.getKey(), intMetric.getShortName(), Metric.ValueType.valueOf(intMetric.getValueType())).create(); - AtomicInteger counter = new AtomicInteger(); - return new IssueMetricFormula(metric, true, (ctx, issues) -> { - ctx.setLeakValue((double) counter.incrementAndGet()); - }); - } - private IssueMetricFormula newRatingLeakFormula(Rating rating) { Metric metric = new Metric.Builder(ratingMetric.getKey(), ratingMetric.getShortName(), Metric.ValueType.valueOf(ratingMetric.getValueType())).create(); return new IssueMetricFormula(metric, true, (ctx, issues) -> { diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java index 7a28aa4f93f..71ec3e6cb79 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java @@ -20,12 +20,14 @@ package org.sonar.server.qualitygate.changeevent; import java.util.Optional; +import java.util.Random; import java.util.function.Supplier; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mockito; import org.sonar.api.config.Configuration; +import org.sonar.api.measures.Metric; import org.sonar.db.component.BranchDto; import org.sonar.db.component.BranchType; import org.sonar.db.component.ComponentDto; @@ -50,6 +52,7 @@ public class QGChangeEventTest { .setUuid("pto") .setCreatedAt(8_999_999_765L); private Configuration configuration = Mockito.mock(Configuration.class); + private Metric.Level previousStatus = Metric.Level.values()[new Random().nextInt(Metric.Level.values().length)]; private Supplier> supplier = Optional::empty; @Test @@ -57,7 +60,7 @@ public class QGChangeEventTest { expectedException.expect(NullPointerException.class); expectedException.expectMessage("project can't be null"); - new QGChangeEvent(null, branch, analysis, configuration, supplier); + new QGChangeEvent(null, branch, analysis, configuration, previousStatus, supplier); } @Test @@ -65,7 +68,7 @@ public class QGChangeEventTest { expectedException.expect(NullPointerException.class); expectedException.expectMessage("branch can't be null"); - new QGChangeEvent(project, null, analysis, configuration, supplier); + new QGChangeEvent(project, null, analysis, configuration, previousStatus, supplier); } @Test @@ -73,7 +76,7 @@ public class QGChangeEventTest { expectedException.expect(NullPointerException.class); expectedException.expectMessage("analysis can't be null"); - new QGChangeEvent(project, branch, null, configuration, supplier); + new QGChangeEvent(project, branch, null, configuration, previousStatus, supplier); } @Test @@ -81,7 +84,12 @@ public class QGChangeEventTest { expectedException.expect(NullPointerException.class); expectedException.expectMessage("projectConfiguration can't be null"); - new QGChangeEvent(project, branch, analysis, null, supplier); + new QGChangeEvent(project, branch, analysis, null, previousStatus, supplier); + } + + @Test + public void constructor_does_not_fail_with_NPE_if_previousStatus_is_null() { + new QGChangeEvent(project, branch, analysis, configuration, null, supplier); } @Test @@ -89,26 +97,36 @@ public class QGChangeEventTest { expectedException.expect(NullPointerException.class); expectedException.expectMessage("qualityGateSupplier can't be null"); - new QGChangeEvent(project, branch, analysis, configuration, null); + new QGChangeEvent(project, branch, analysis, configuration, previousStatus, null); } @Test public void verify_getters() { - QGChangeEvent underTest = new QGChangeEvent(project, branch, analysis, configuration, supplier); + QGChangeEvent underTest = new QGChangeEvent(project, branch, analysis, configuration, previousStatus, supplier); assertThat(underTest.getProject()).isSameAs(project); assertThat(underTest.getBranch()).isSameAs(branch); assertThat(underTest.getAnalysis()).isSameAs(analysis); assertThat(underTest.getProjectConfiguration()).isSameAs(configuration); + assertThat(underTest.getPreviousStatus()).contains(previousStatus); assertThat(underTest.getQualityGateSupplier()).isSameAs(supplier); } + @Test + public void getPreviousStatus_returns_empty_when_previousStatus_is_null() { + QGChangeEvent underTest = new QGChangeEvent(project, branch, analysis, configuration, previousStatus, supplier); + + assertThat(underTest.getPreviousStatus()).contains(previousStatus); + } + @Test public void overrides_toString() { - QGChangeEvent underTest = new QGChangeEvent(project, branch, analysis, configuration, supplier); + QGChangeEvent underTest = new QGChangeEvent(project, branch, analysis, configuration, previousStatus, supplier); assertThat(underTest.toString()) - .isEqualTo("QGChangeEvent{project=bar:foo, branch=SHORT:bar:doh:zop, analysis=pto:8999999765, projectConfiguration=" + configuration.toString() + + .isEqualTo("QGChangeEvent{project=bar:foo, branch=SHORT:bar:doh:zop, analysis=pto:8999999765" + + ", projectConfiguration=" + configuration.toString() + + ", previousStatus=" + previousStatus + ", qualityGateSupplier=" + supplier + "}"); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookQGChangeEventListenerTest.java b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookQGChangeEventListenerTest.java index 1f0bb7d2e7f..747e5c802ff 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookQGChangeEventListenerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookQGChangeEventListenerTest.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Random; import java.util.Set; import java.util.function.Supplier; import javax.annotation.Nullable; @@ -55,7 +56,6 @@ import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; @@ -88,7 +88,8 @@ public class WebhookQGChangeEventListenerTest { public void onIssueChanges_has_no_effect_if_no_webhook_is_configured() { Configuration configuration1 = mock(Configuration.class); mockWebhookDisabled(configuration1); - QGChangeEvent qualityGateEvent = new QGChangeEvent(new ComponentDto(), new BranchDto(), new SnapshotDto(), configuration1, Optional::empty); + Metric.Level previousStatus = Metric.Level.values()[new Random().nextInt(Metric.Level.values().length)]; + QGChangeEvent qualityGateEvent = new QGChangeEvent(new ComponentDto(), new BranchDto(), new SnapshotDto(), configuration1, previousStatus, Optional::empty); mockedUnderTest.onIssueChanges(qualityGateEvent, CHANGED_ISSUES_ARE_IGNORED); @@ -214,28 +215,12 @@ public class WebhookQGChangeEventListenerTest { any(Supplier.class)); } - private void verifyWebhookNotCalled(ComponentAndBranch componentAndBranch, SnapshotDto analysis, Configuration branchConfiguration) { - verify(webHooks).isEnabled(branchConfiguration); - verify(webHooks, times(0)).sendProjectAnalysisUpdate( - Matchers.same(branchConfiguration), - Matchers.eq(new WebHooks.Analysis(componentAndBranch.uuid(), analysis.getUuid(), null)), - any(Supplier.class)); - } - private List extractPayloadFactoryArguments(int time) { ArgumentCaptor projectAnalysisCaptor = ArgumentCaptor.forClass(ProjectAnalysis.class); verify(webhookPayloadFactory, Mockito.times(time)).create(projectAnalysisCaptor.capture()); return projectAnalysisCaptor.getAllValues(); } - private ComponentAndBranch insertPrivateBranch(OrganizationDto organization, BranchType branchType) { - ComponentDto project = dbTester.components().insertPrivateProject(organization); - BranchDto branchDto = newBranchDto(project.projectUuid(), branchType) - .setKey("foo"); - ComponentDto newComponent = dbTester.components().insertProjectBranch(project, branchDto); - return new ComponentAndBranch(newComponent, branchDto); - } - public ComponentAndBranch insertMainBranch(OrganizationDto organization) { ComponentDto project = newPrivateProjectDto(organization); BranchDto branch = newBranchDto(project, LONG).setKey("master"); @@ -276,7 +261,8 @@ public class WebhookQGChangeEventListenerTest { } private static QGChangeEvent newQGChangeEvent(ComponentAndBranch branch, SnapshotDto analysis, Configuration configuration, @Nullable EvaluatedQualityGate evaluatedQualityGate) { - return new QGChangeEvent(branch.component, branch.branch, analysis, configuration, () -> Optional.ofNullable(evaluatedQualityGate)); + Metric.Level previousStatus = Metric.Level.values()[new Random().nextInt(Metric.Level.values().length)]; + return new QGChangeEvent(branch.component, branch.branch, analysis, configuration, previousStatus, () -> Optional.ofNullable(evaluatedQualityGate)); } } -- 2.39.5