3 * Copyright (C) 2009-2021 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.ce.task.projectanalysis.step;
22 import com.google.common.collect.ImmutableList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.Date;
26 import java.util.List;
28 import java.util.Optional;
29 import java.util.stream.Collectors;
30 import javax.annotation.Nullable;
31 import org.junit.Before;
32 import org.junit.Rule;
33 import org.junit.Test;
34 import org.sonar.api.measures.CoreMetrics;
35 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
36 import org.sonar.ce.task.projectanalysis.component.Component;
37 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
38 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
39 import org.sonar.ce.task.projectanalysis.measure.Measure;
40 import org.sonar.ce.task.projectanalysis.measure.MeasureRepository;
41 import org.sonar.ce.task.projectanalysis.metric.Metric;
42 import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
43 import org.sonar.ce.task.projectanalysis.qualityprofile.MutableQProfileStatusRepository;
44 import org.sonar.ce.task.projectanalysis.qualityprofile.RegisterQualityProfileStatusStep;
45 import org.sonar.ce.task.step.TestComputationStepContext;
46 import org.sonar.server.qualityprofile.QPMeasureData;
47 import org.sonar.server.qualityprofile.QualityProfile;
49 import static org.mockito.ArgumentMatchers.eq;
50 import static org.mockito.Mockito.mock;
51 import static org.mockito.Mockito.verify;
52 import static org.mockito.Mockito.verifyNoMoreInteractions;
53 import static org.mockito.Mockito.when;
54 import static org.sonar.ce.task.projectanalysis.qualityprofile.QProfileStatusRepository.Status.ADDED;
55 import static org.sonar.ce.task.projectanalysis.qualityprofile.QProfileStatusRepository.Status.REMOVED;
56 import static org.sonar.ce.task.projectanalysis.qualityprofile.QProfileStatusRepository.Status.UNCHANGED;
57 import static org.sonar.ce.task.projectanalysis.qualityprofile.QProfileStatusRepository.Status.UPDATED;
60 public class RegisterQualityProfileStatusStepTest {
62 private static final String QP_NAME_1 = "qp_1";
63 private static final String QP_NAME_2 = "qp_2";
64 private static final String LANGUAGE_KEY_1 = "language_key1";
65 private static final String LANGUAGE_KEY_2 = "language_key_2";
68 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
70 private MetricRepository metricRepository = mock(MetricRepository.class);
71 private MeasureRepository measureRepository = mock(MeasureRepository.class);
72 private MutableQProfileStatusRepository qProfileStatusRepository = mock(MutableQProfileStatusRepository.class);
73 private AnalysisMetadataHolder analysisMetadataHolder = mock(AnalysisMetadataHolder.class);
74 private Metric qualityProfileMetric = mock(Metric.class);
76 private RegisterQualityProfileStatusStep underTest = new RegisterQualityProfileStatusStep(treeRootHolder, measureRepository, metricRepository, qProfileStatusRepository, analysisMetadataHolder);
80 when(metricRepository.getByKey(CoreMetrics.QUALITY_PROFILES_KEY)).thenReturn(qualityProfileMetric);
81 treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("uuid").setKey("key").build());
85 public void register_nothing_if_no_base_measure() {
86 when(measureRepository.getBaseMeasure(treeRootHolder.getRoot(), qualityProfileMetric)).thenReturn(Optional.empty());
88 underTest.execute(new TestComputationStepContext());
90 verifyNoMoreInteractions(qProfileStatusRepository);
94 public void register_nothing_if_no_base_and_quality_profile_measure_is_empty() {
95 mockBaseQPMeasures(treeRootHolder.getRoot(), null);
97 underTest.execute(new TestComputationStepContext());
99 verifyNoMoreInteractions(qProfileStatusRepository);
103 public void register_removed_profile() {
104 QualityProfile qp = qp(QP_NAME_1, LANGUAGE_KEY_1, new Date());
106 mockBaseQPMeasures(treeRootHolder.getRoot(), new QualityProfile[] {qp});
108 underTest.execute(new TestComputationStepContext());
110 verify(qProfileStatusRepository).register(eq(qp.getQpKey()), eq(REMOVED));
111 verifyNoMoreInteractions(qProfileStatusRepository);
115 public void register_added_profile() {
116 QualityProfile qp1 = qp(QP_NAME_1, LANGUAGE_KEY_1, new Date(1000L));
117 QualityProfile qp2 = qp(QP_NAME_2, LANGUAGE_KEY_2, new Date(1000L));
119 mockBaseQPMeasures(treeRootHolder.getRoot(), arrayOf(qp1));
120 mockRawQProfiles(ImmutableList.of(qp1, qp2));
121 underTest.execute(new TestComputationStepContext());
123 verify(qProfileStatusRepository).register(eq(qp1.getQpKey()), eq(UNCHANGED));
124 verify(qProfileStatusRepository).register(eq(qp2.getQpKey()), eq(ADDED));
125 verifyNoMoreInteractions(qProfileStatusRepository);
129 public void register_updated_profile() {
130 QualityProfile qp1 = qp(QP_NAME_1, LANGUAGE_KEY_1, new Date(1000L));
131 QualityProfile qp2 = qp(QP_NAME_1, LANGUAGE_KEY_1, new Date(1200L));
133 mockBaseQPMeasures(treeRootHolder.getRoot(), arrayOf(qp1));
134 mockRawQProfiles(ImmutableList.of(qp2));
135 underTest.execute(new TestComputationStepContext());
137 verify(qProfileStatusRepository).register(eq(qp2.getQpKey()), eq(UPDATED));
138 verifyNoMoreInteractions(qProfileStatusRepository);
142 public void register_unchanged_profile() {
143 QualityProfile qp1 = qp(QP_NAME_1, LANGUAGE_KEY_1, new Date(1000L));
145 mockBaseQPMeasures(treeRootHolder.getRoot(), arrayOf(qp1));
146 mockRawQProfiles(ImmutableList.of(qp1));
147 underTest.execute(new TestComputationStepContext());
149 verify(qProfileStatusRepository).register(eq(qp1.getQpKey()), eq(UNCHANGED));
150 verifyNoMoreInteractions(qProfileStatusRepository);
153 private void mockBaseQPMeasures(Component component, @Nullable QualityProfile[] previous) {
154 when(measureRepository.getBaseMeasure(component, qualityProfileMetric)).thenReturn(Optional.of(newMeasure(previous)));
157 private void mockRawQProfiles(@Nullable List<QualityProfile> previous) {
158 Map<String, QualityProfile> qpByLanguages = previous.stream().collect(Collectors.toMap(QualityProfile::getLanguageKey, q -> q));
159 when(analysisMetadataHolder.getQProfilesByLanguage()).thenReturn(qpByLanguages);
162 private static QualityProfile qp(String qpName, String languageKey, Date date) {
163 return new QualityProfile(qpName + "-" + languageKey, qpName, languageKey, date);
166 private static QualityProfile[] arrayOf(QualityProfile... qps) {
170 private static Measure newMeasure(@Nullable QualityProfile... qps) {
171 return Measure.newMeasureBuilder().create(toJson(qps));
174 private static String toJson(@Nullable QualityProfile... qps) {
175 List<QualityProfile> qualityProfiles = qps == null ? Collections.emptyList() : Arrays.asList(qps);
176 return QPMeasureData.toJson(new QPMeasureData(qualityProfiles));