]> source.dussan.org Git - sonarqube.git/blob
a3ff63478f3ec2c0cf758949f05cab2fe3886709
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2024 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.server.platform.db.migration.version.v108;
21
22 import java.nio.charset.StandardCharsets;
23 import java.sql.SQLException;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.stream.Collectors;
29 import org.junit.jupiter.api.Test;
30 import org.junit.jupiter.api.extension.RegisterExtension;
31 import org.slf4j.event.Level;
32 import org.sonar.api.testfixtures.log.LogTesterJUnit5;
33 import org.sonar.api.utils.System2;
34 import org.sonar.core.util.SequenceUuidFactory;
35 import org.sonar.db.MigrationDbTester;
36 import org.sonar.server.platform.db.migration.step.DataChange;
37
38 import static java.lang.String.format;
39 import static org.assertj.core.api.Assertions.assertThat;
40 import static org.assertj.core.api.Assertions.assertThatCode;
41 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
42 import static org.assertj.core.api.Assertions.tuple;
43 import static org.mockito.Mockito.mock;
44
45 class MigrateBranchesLiveMeasuresToMeasuresIT {
46
47   private static final String MEASURES_MIGRATED_COLUMN = "measures_migrated";
48   public static final String SELECT_MEASURE = "select component_uuid, branch_uuid, json_value, json_value_hash, created_at, updated_at " +
49     "from measures where component_uuid = '%s'";
50
51   @RegisterExtension
52   public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(MigrateBranchesLiveMeasuresToMeasures.class);
53
54   @RegisterExtension
55   private final LogTesterJUnit5 logTester = new LogTesterJUnit5();
56
57   private final SequenceUuidFactory uuidFactory = new SequenceUuidFactory();
58   private final System2 system2 = mock();
59   private final DataChange underTest = new MigrateBranchesLiveMeasuresToMeasures(db.database(), system2);
60
61   @Test
62   void shall_complete_when_tables_are_empty() throws SQLException {
63     underTest.execute();
64
65     assertThat(db.countRowsOfTable("measures")).isZero();
66   }
67
68   @Test
69   void migration_does_nothing_if_live_measures_table_is_missing() {
70     db.executeDdl("drop table live_measures");
71     db.assertTableDoesNotExist("live_measures");
72     String branch = "branch_3";
73     insertNotMigratedBranch(branch);
74
75     assertThatCode(underTest::execute)
76       .doesNotThrowAnyException();
77   }
78
79   @Test
80   void log_the_item_uuid_when_the_migration_fails() {
81     String nclocMetricUuid = insertMetric("ncloc", "INT");
82     String branch1 = "branch_1";
83     insertNotMigratedBranch(branch1);
84     insertMeasure(branch1, nclocMetricUuid, Map.of("value", 120));
85
86     db.executeDdl("drop table measures");
87     db.assertTableDoesNotExist("measures");
88
89     assertThatExceptionOfType(SQLException.class)
90       .isThrownBy(underTest::execute);
91
92     assertThat(logTester.logs(Level.ERROR))
93       .contains("Migration of branch branch_1 failed");
94   }
95
96   @Test
97   void shall_not_migrate_when_branch_is_already_flagged() throws SQLException {
98     String nclocMetricUuid = insertMetric("ncloc", "INT");
99     String qgStatusMetricUuid = insertMetric("quality_gate_status", "STRING");
100     String metricWithDataUuid = insertMetric("metric_with_data", "DATA");
101     String branch1 = "branch_1";
102     insertMigratedBranch(branch1);
103     insertMeasure(branch1, nclocMetricUuid, Map.of("value", 120));
104     insertMeasure(branch1, qgStatusMetricUuid, Map.of("text_value", "ok"));
105     insertMeasure(branch1, metricWithDataUuid, Map.of("measure_data", "some data".getBytes(StandardCharsets.UTF_8)));
106
107     insertMigratedBranch("branch_2");
108     insertMeasure("branch_2", nclocMetricUuid, Map.of("value", 14220));
109
110     underTest.execute();
111
112     assertThat(db.countRowsOfTable("measures")).isZero();
113   }
114
115   @Test
116   void should_flag_branch_with_no_measures() throws SQLException {
117     String branch = "branch_3";
118     insertNotMigratedBranch(branch);
119
120     underTest.execute();
121
122     assertBranchMigrated(branch);
123     assertThat(db.countRowsOfTable("measures")).isZero();
124   }
125
126   @Test
127   void should_migrate_branch_with_measures() throws SQLException {
128     String nclocMetricUuid = insertMetric("ncloc", "INT");
129     String qgStatusMetricUuid = insertMetric("quality_gate_status", "STRING");
130     String metricWithDataUuid = insertMetric("metric_with_data", "DATA");
131
132     String branch1 = "branch_4";
133     insertNotMigratedBranch(branch1);
134     String component1 = uuidFactory.create();
135     String component2 = uuidFactory.create();
136     insertMeasure(branch1, component1, nclocMetricUuid, Map.of("value", 120));
137     insertMeasure(branch1, component1, qgStatusMetricUuid, Map.of("text_value", "ok"));
138     insertMeasure(branch1, component2, metricWithDataUuid, Map.of("measure_data", "some data".getBytes(StandardCharsets.UTF_8)));
139
140     String branch2 = "branch_5";
141     insertNotMigratedBranch(branch2);
142     insertMeasure(branch2, nclocMetricUuid, Map.of("value", 64));
143
144     String migratedBranch = "branch_6";
145     insertMigratedBranch(migratedBranch);
146     insertMeasure(migratedBranch, nclocMetricUuid, Map.of("value", 3684));
147
148     underTest.execute();
149
150     assertBranchMigrated(branch1);
151     assertBranchMigrated(branch2);
152     assertThat(db.countRowsOfTable("measures")).isEqualTo(3);
153
154     assertThat(db.select(format(SELECT_MEASURE, component1)))
155       .hasSize(1)
156       .extracting(t -> t.get("component_uuid"), t -> t.get("branch_uuid"), t -> t.get("json_value"), t -> t.get("json_value_hash"))
157       .containsOnly(tuple(component1, branch1, "{\"ncloc\":120.0,\"quality_gate_status\":\"ok\"}", 6033012287291512746L));
158
159     assertThat(db.select(format(SELECT_MEASURE, component2)))
160       .hasSize(1)
161       .extracting(t -> t.get("component_uuid"), t -> t.get("branch_uuid"), t -> t.get("json_value"), t -> t.get("json_value_hash"))
162       .containsOnly(tuple(component2, branch1, "{\"metric_with_data\":\"some data\"}", -4524184678167636687L));
163   }
164
165   @Test
166   void should_not_migrate_measures_planned_for_deletion() throws SQLException {
167     String nclocMetricUuid = insertMetric("ncloc", "INT");
168     Set<String> deletedMetricUuid = DeleteSoftwareQualityRatingFromProjectMeasures.SOFTWARE_QUALITY_METRICS_TO_DELETE.stream().map(e -> insertMetric(e, "INT"))
169       .collect(Collectors.toSet());
170
171     String branch1 = "branch_4";
172     insertNotMigratedBranch(branch1);
173     String component1 = uuidFactory.create();
174     String component2 = uuidFactory.create();
175     insertMeasure(branch1, component1, nclocMetricUuid, Map.of("value", 120));
176     deletedMetricUuid.forEach(metricUuid -> insertMeasure(branch1, component1, metricUuid, Map.of("value", 120)));
177     deletedMetricUuid.forEach(metricUuid -> insertMeasure(branch1, component2, metricUuid, Map.of("value", 120)));
178
179     underTest.execute();
180
181     assertBranchMigrated(branch1);
182     assertThat(db.countRowsOfTable("measures")).isEqualTo(1);
183
184     assertThat(db.select(format(SELECT_MEASURE, component1)))
185       .hasSize(1)
186       .extracting(t -> t.get("component_uuid"), t -> t.get("branch_uuid"), t -> t.get("json_value"), t -> t.get("json_value_hash"))
187       .containsOnly(tuple(component1, branch1, "{\"ncloc\":120.0}", -1557106439558598045L));
188
189     assertThat(db.select(format(SELECT_MEASURE, component2)))
190       .isEmpty();
191   }
192
193   private void assertBranchMigrated(String branch) {
194     List<Map<String, Object>> result = db.select(format("select %s as \"MIGRATED\" from project_branches where uuid = '%s'", MEASURES_MIGRATED_COLUMN, branch));
195     assertThat(result)
196       .hasSize(1)
197       .extracting(t -> t.get("MIGRATED"))
198       .containsOnly(true);
199   }
200
201   private String insertMetric(String metricName, String valueType) {
202     String metricUuid = uuidFactory.create();
203     db.executeInsert("metrics",
204       "uuid", metricUuid,
205       "name", metricName,
206       "val_type", valueType);
207     return metricUuid;
208   }
209
210   private void insertMeasure(String branchUuid, String metricUuid, Map<String, Object> data) {
211     insertMeasure(branchUuid, uuidFactory.create(), metricUuid, data);
212   }
213
214   private void insertMeasure(String branchUuid, String componentUuid, String metricUuid, Map<String, Object> data) {
215     Map<String, Object> dataMap = new HashMap<>(data);
216     dataMap.put("uuid", uuidFactory.create());
217     dataMap.put("component_uuid", componentUuid);
218     dataMap.put("project_uuid", branchUuid);
219     dataMap.put("metric_uuid", metricUuid);
220     dataMap.put("created_at", 12L);
221     dataMap.put("updated_at", 12L);
222
223     db.executeInsert("live_measures", dataMap);
224   }
225
226   private void insertNotMigratedBranch(String branchUuid) {
227     insertBranch(branchUuid, false);
228   }
229
230   private void insertMigratedBranch(String branchUuid) {
231     insertBranch(branchUuid, true);
232   }
233
234   private void insertBranch(String branchUuid, boolean migrated) {
235     db.executeInsert("project_branches",
236       "uuid", branchUuid,
237       "kee", branchUuid,
238       "branch_type", "LONG",
239       "project_uuid", uuidFactory.create(),
240       MEASURES_MIGRATED_COLUMN, migrated,
241       "need_issue_sync", false,
242       "is_main", true,
243       "created_at", 12L,
244       "updated_at", 12L);
245   }
246
247 }