3 * Copyright (C) 2009-2024 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.server.platform.db.migration.version.v108;
22 import java.nio.charset.StandardCharsets;
23 import java.sql.SQLException;
24 import java.util.HashMap;
25 import java.util.List;
27 import org.junit.jupiter.api.Test;
28 import org.junit.jupiter.api.extension.RegisterExtension;
29 import org.sonar.api.utils.System2;
30 import org.sonar.core.util.SequenceUuidFactory;
31 import org.sonar.db.MigrationDbTester;
32 import org.sonar.server.platform.db.migration.step.DataChange;
34 import static java.lang.String.format;
35 import static org.assertj.core.api.Assertions.assertThat;
36 import static org.assertj.core.api.Assertions.tuple;
37 import static org.mockito.Mockito.mock;
39 class MigratePortfoliosLiveMeasuresToMeasuresIT {
41 private static final String MEASURES_MIGRATED_COLUMN = "measures_migrated";
42 public static final String SELECT_MEASURE = "select component_uuid, branch_uuid, json_value, json_value_hash, created_at, updated_at " +
43 "from measures where component_uuid = '%s'";
46 public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(MigratePortfoliosLiveMeasuresToMeasures.class);
48 private final SequenceUuidFactory uuidFactory = new SequenceUuidFactory();
49 private final System2 system2 = mock();
50 private final DataChange underTest = new MigratePortfoliosLiveMeasuresToMeasures(db.database(), system2);
53 void shall_complete_when_tables_are_empty() throws SQLException {
56 assertThat(db.countRowsOfTable("measures")).isZero();
60 void shall_not_migrate_when_portfolio_is_already_flagged() throws SQLException {
61 String nclocMetricUuid = insertMetric("ncloc", "INT");
62 String qgStatusMetricUuid = insertMetric("quality_gate_status", "STRING");
63 String metricWithDataUuid = insertMetric("metric_with_data", "DATA");
64 String portfolio1 = "portfolio_1";
65 insertMigratedPortfolio(portfolio1);
66 insertMeasure(portfolio1, nclocMetricUuid, Map.of("value", 120));
67 insertMeasure(portfolio1, qgStatusMetricUuid, Map.of("text_value", "ok"));
68 insertMeasure(portfolio1, metricWithDataUuid, Map.of("measure_data", "some data".getBytes(StandardCharsets.UTF_8)));
70 insertMigratedPortfolio("portfolio_2");
71 insertMeasure("portfolio_2", nclocMetricUuid, Map.of("value", 14220));
75 assertThat(db.countRowsOfTable("measures")).isZero();
79 void should_flag_portfolio_with_no_measures() throws SQLException {
80 String portfolio = "portfolio_3";
81 insertNotMigratedPortfolio(portfolio);
85 assertPortfolioMigrated(portfolio);
86 assertThat(db.countRowsOfTable("measures")).isZero();
90 void should_migrate_portfolio_with_measures() throws SQLException {
91 String nclocMetricUuid = insertMetric("ncloc", "INT");
92 String qgStatusMetricUuid = insertMetric("quality_gate_status", "STRING");
93 String metricWithDataUuid = insertMetric("metric_with_data", "DATA");
95 String portfolio1 = "portfolio_4";
96 insertNotMigratedPortfolio(portfolio1);
97 String component1 = uuidFactory.create();
98 String component2 = uuidFactory.create();
99 insertMeasure(portfolio1, component1, nclocMetricUuid, Map.of("value", 120));
100 insertMeasure(portfolio1, component1, qgStatusMetricUuid, Map.of("text_value", "ok"));
101 insertMeasure(portfolio1, component2, metricWithDataUuid, Map.of("measure_data", "some data".getBytes(StandardCharsets.UTF_8)));
103 String portfolio2 = "portfolio_5";
104 insertNotMigratedPortfolio(portfolio2);
105 insertMeasure(portfolio2, nclocMetricUuid, Map.of("value", 64));
107 String migratedPortfolio = "portfolio_6";
108 insertMigratedPortfolio(migratedPortfolio);
109 insertMeasure(migratedPortfolio, nclocMetricUuid, Map.of("value", 3684));
113 assertPortfolioMigrated(portfolio1);
114 assertPortfolioMigrated(portfolio2);
115 assertThat(db.countRowsOfTable("measures")).isEqualTo(3);
117 assertThat(db.select(format(SELECT_MEASURE, component1)))
119 .extracting(t -> t.get("component_uuid"), t -> t.get("branch_uuid"), t -> t.get("json_value"), t -> t.get("json_value_hash"))
120 .containsOnly(tuple(component1, portfolio1, "{\"ncloc\":120.0,\"quality_gate_status\":\"ok\"}", 6033012287291512746L));
122 assertThat(db.select(format(SELECT_MEASURE, component2)))
124 .extracting(t -> t.get("component_uuid"), t -> t.get("branch_uuid"), t -> t.get("json_value"), t -> t.get("json_value_hash"))
125 .containsOnly(tuple(component2, portfolio1, "{\"metric_with_data\":\"some data\"}", -4524184678167636687L));
128 private void assertPortfolioMigrated(String portfolio) {
129 List<Map<String, Object>> result = db.select(format("select %s as \"MIGRATED\" from portfolios where uuid = '%s'", MEASURES_MIGRATED_COLUMN, portfolio));
132 .extracting(t -> t.get("MIGRATED"))
136 private String insertMetric(String metricName, String valueType) {
137 String metricUuid = uuidFactory.create();
138 db.executeInsert("metrics",
141 "val_type", valueType);
145 private void insertMeasure(String portfolioUuid, String metricUuid, Map<String, Object> data) {
146 insertMeasure(portfolioUuid, uuidFactory.create(), metricUuid, data);
149 private void insertMeasure(String portfolioUuid, String componentUuid, String metricUuid, Map<String, Object> data) {
150 Map<String, Object> dataMap = new HashMap<>(data);
151 dataMap.put("uuid", uuidFactory.create());
152 dataMap.put("component_uuid", componentUuid);
153 dataMap.put("project_uuid", portfolioUuid);
154 dataMap.put("metric_uuid", metricUuid);
155 dataMap.put("created_at", 12L);
156 dataMap.put("updated_at", 12L);
158 db.executeInsert("live_measures", dataMap);
161 private void insertNotMigratedPortfolio(String portfolioUuid) {
162 insertPortfolio(portfolioUuid, false);
165 private void insertMigratedPortfolio(String portfolioUuid) {
166 insertPortfolio(portfolioUuid, true);
169 private void insertPortfolio(String portfolioUuid, boolean migrated) {
170 db.executeInsert("portfolios",
171 "uuid", portfolioUuid,
172 "kee", portfolioUuid,
173 "name", portfolioUuid,
175 "root_uuid", portfolioUuid,
176 "selection_mode", "MANUAL",
177 MEASURES_MIGRATED_COLUMN, migrated,