3 * Copyright (C) 2009-2019 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.v76;
22 import java.sql.SQLException;
23 import java.util.List;
25 import javax.annotation.Nullable;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.sonar.api.resources.Qualifiers;
29 import org.sonar.api.resources.Scopes;
30 import org.sonar.api.utils.System2;
31 import org.sonar.api.utils.internal.TestSystem2;
32 import org.sonar.core.util.SequenceUuidFactory;
33 import org.sonar.core.util.UuidFactory;
34 import org.sonar.db.CoreDbTester;
36 import static java.lang.String.valueOf;
37 import static org.assertj.core.api.Assertions.assertThat;
38 import static org.sonar.server.platform.db.migration.version.v76.MigrateModuleProperties.NEW_PROPERTY_NAME;
40 public class MigrateModulePropertiesTest {
41 private static final long NOW = 50_000_000_000L;
44 public CoreDbTester db = CoreDbTester.createForSchema(MigrateModulePropertiesTest.class, "schema.sql");
45 private System2 system2 = new TestSystem2().setNow(NOW);
46 private UuidFactory uuidFactory = new SequenceUuidFactory();
47 private MigrateModuleProperties underTest = new MigrateModuleProperties(db.database(), system2);
50 public void multi_module_project_migration() throws SQLException {
51 setupMultiModuleProject();
55 verifyMultiModuleProjectMigration();
56 assertThat(getRemainingProperties()).hasSize(3);
60 public void migration_is_reentrant() throws SQLException {
61 setupMultiModuleProject();
66 verifyMultiModuleProjectMigration();
67 assertThat(getRemainingProperties()).hasSize(3);
71 public void single_module_project_migration() throws SQLException {
72 String project2Uuid = uuidFactory.create();
73 insertComponent(5, project2Uuid, null, project2Uuid, Qualifiers.PROJECT, "Single module project");
74 insertProperty(9, 5, "sonar.coverage.exclusions", "SingleModuleA.java", null);
75 insertProperty(10, 5, "sonar.cp.exclusions", "SingleModuleB.java", null);
79 List<Map<String, Object>> properties = db.select(String.format("select ID, TEXT_VALUE, CLOB_VALUE " +
81 "where PROP_KEY='%s' and RESOURCE_ID = 5", NEW_PROPERTY_NAME));
82 assertThat(properties).hasSize(0);
83 List<Map<String, Object>> remainingProperties = db.select("select ID from properties");
84 assertThat(remainingProperties).hasSize(2);
88 public void properties_do_not_leak_between_projects() throws SQLException {
89 setupMultiModuleProject();
90 setupSecondMultiModuleProject();
94 verifyMultiModuleProjectMigration();
95 verifySecondMultiModuleProjectMigration();
96 assertThat(getRemainingProperties()).hasSize(5);
99 private List<Map<String, Object>> getRemainingProperties() {
100 return db.select("select ID from properties");
103 private void insertComponent(long id, String uuid, @Nullable String rootUuid, String projectUuid, String qualifier, String name) {
108 "ROOT_UUID", rootUuid,
109 "PROJECT_UUID", projectUuid,
110 "SCOPE", Scopes.PROJECT,
111 "QUALIFIER", qualifier,
115 private void insertProperty(long id, long componentId, String key, String value, Long userId) {
119 "RESOURCE_ID", componentId,
126 private void setupMultiModuleProject() {
127 String projectUuid = uuidFactory.create();
128 String moduleUuid = uuidFactory.create();
129 String subModule1Uuid = uuidFactory.create();
130 String subModule2Uuid = uuidFactory.create();
131 String subModule3Uuid = uuidFactory.create();
132 String subModule4Uuid = uuidFactory.create();
133 String subModule5Uuid = uuidFactory.create();
134 insertComponent(1, projectUuid, null, projectUuid, Qualifiers.PROJECT, "Multi-module project");
135 insertComponent(2, moduleUuid, projectUuid, projectUuid, Qualifiers.MODULE, "Module");
136 insertComponent(3, subModule1Uuid, moduleUuid, projectUuid, Qualifiers.MODULE, "Submodule 1");
137 insertComponent(4, subModule2Uuid, moduleUuid, projectUuid, Qualifiers.MODULE, "Submodule 2");
138 insertComponent(5, subModule3Uuid, moduleUuid, projectUuid, Qualifiers.MODULE, "Submodule with reset property");
139 insertComponent(6, subModule4Uuid, moduleUuid, projectUuid, Qualifiers.MODULE, "Submodule without properties");
140 insertComponent(7, subModule5Uuid, moduleUuid, projectUuid, Qualifiers.MODULE, "Submodule with user property");
141 insertProperty(1, 1, "sonar.coverage.exclusions", "Proj1.java", null);
142 insertProperty(2, 1, "sonar.cpd.exclusions", "Proj2.java", null);
143 insertProperty(3, 2, "sonar.coverage.exclusions", "ModuleA.java", null);
144 insertProperty(4, 2, "sonar.cpd.exclusions", "ModuleB.java", null);
145 insertProperty(5, 3, "sonar.coverage.exclusions", "Module1A.java", null);
146 insertProperty(6, 3, "sonar.cpd.exclusions", "Moddule1B.java", null);
147 insertProperty(7, 4, "sonar.coverage.exclusions", "Module2A.java", null);
148 insertProperty(8, 4, "sonar.cpd.exclusions", "Module2B.java", null);
149 insertProperty(9, 5, "sonar.coverage.exclusions", null, null);
150 insertProperty(10, 7, "favourite", null, 5L);
153 private void verifyMultiModuleProjectMigration() {
154 final String expectedResult = "# Settings from 'Multi-module project::Module'\n" +
155 "sonar.coverage.exclusions=ModuleA.java\n" +
156 "sonar.cpd.exclusions=ModuleB.java\n" +
158 "# Settings from 'Multi-module project::Submodule 1'\n" +
159 "sonar.coverage.exclusions=Module1A.java\n" +
160 "sonar.cpd.exclusions=Moddule1B.java\n" +
162 "# Settings from 'Multi-module project::Submodule 2'\n" +
163 "sonar.coverage.exclusions=Module2A.java\n" +
164 "sonar.cpd.exclusions=Module2B.java\n" +
166 "# Settings from 'Multi-module project::Submodule with reset property'\n" +
167 "sonar.coverage.exclusions=\n";
169 List<Map<String, Object>> properties = db
170 .select(String.format("select ID, TEXT_VALUE, CLOB_VALUE from properties where PROP_KEY='%s' and RESOURCE_ID = 1",
173 assertThat(properties).hasSize(1);
174 Map<String, Object> project1Property = properties.get(0);
175 assertThat(project1Property.get("TEXT_VALUE")).isNull();
176 assertThat(project1Property.get("CLOB_VALUE")).isEqualTo(expectedResult);
179 private void setupSecondMultiModuleProject() {
180 String project3Uuid = uuidFactory.create();
181 String singleModuleUuid = uuidFactory.create();
182 insertComponent(8, project3Uuid, null, project3Uuid, Qualifiers.PROJECT, "Another multi-module project");
183 insertComponent(9, singleModuleUuid, project3Uuid, project3Uuid, Qualifiers.MODULE, "Module X");
184 insertProperty(11, 8, "sonar.coverage.exclusions", "InRoot.java", null);
185 insertProperty(12, 9, "sonar.coverage.exclusions", "InModule.java", null);
188 private void verifySecondMultiModuleProjectMigration() {
189 final String expectedResult = "# Settings from 'Another multi-module project::Module X'\n" +
190 "sonar.coverage.exclusions=InModule.java\n";
192 List<Map<String, Object>> properties = db.select(String.format("select ID, TEXT_VALUE, CLOB_VALUE " +
194 "where PROP_KEY='%s' and RESOURCE_ID = 8", NEW_PROPERTY_NAME));
196 assertThat(properties).hasSize(1);
197 Map<String, Object> project2Property = properties.get(0);
198 assertThat(project2Property.get("TEXT_VALUE")).isNull();
199 assertThat(project2Property.get("CLOB_VALUE")).isEqualTo(expectedResult);