]> source.dussan.org Git - sonarqube.git/blob
a4b92076fcab917881d454975dd19f6ac5aa04c5
[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.ws;
21
22 import com.google.gson.Gson;
23 import com.tngtech.java.junit.dataprovider.DataProvider;
24 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
25 import java.sql.SQLException;
26 import java.util.List;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
30 import org.sonar.db.Database;
31 import org.sonar.db.DbTester;
32 import org.sonar.db.component.BranchType;
33 import org.sonar.db.component.ComponentDto;
34 import org.sonar.db.portfolio.PortfolioDto;
35 import org.sonar.db.property.PropertyDto;
36 import org.sonar.server.exceptions.ForbiddenException;
37 import org.sonar.server.platform.db.migration.adhoc.AddMeasuresMigratedColumnToPortfoliosTable;
38 import org.sonar.server.platform.db.migration.adhoc.AddMeasuresMigratedColumnToProjectBranchesTable;
39 import org.sonar.server.platform.db.migration.adhoc.MigrateBranchesLiveMeasuresToMeasures;
40 import org.sonar.server.platform.db.migration.adhoc.MigratePortfoliosLiveMeasuresToMeasures;
41 import org.sonar.server.tester.UserSessionRule;
42 import org.sonar.server.ws.TestRequest;
43 import org.sonar.server.ws.TestResponse;
44 import org.sonar.server.ws.WsActionTester;
45
46 import static org.assertj.core.api.Assertions.assertThat;
47 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
48 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
49 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
50 import static org.mockito.Mockito.mock;
51 import static org.mockito.Mockito.verify;
52 import static org.mockito.Mockito.verifyNoInteractions;
53 import static org.sonar.db.component.BranchType.BRANCH;
54 import static org.sonar.server.platform.ws.MigrateMeasuresAction.SYSTEM_MEASURES_MIGRATION_ENABLED;
55 import static org.sonar.test.JsonAssert.assertJson;
56
57 @RunWith(DataProviderRunner.class)
58 public class MigrateMeasuresActionTest {
59   private static final Gson GSON = new Gson();
60
61   public static final String PARAM_SIZE = "size";
62   @Rule
63   public UserSessionRule userSessionRule = UserSessionRule.standalone().logIn().setSystemAdministrator();
64
65   @Rule
66   public DbTester dbTester = DbTester.create();
67
68   private final MigrateBranchesLiveMeasuresToMeasures measuresMigration = mock();
69   private final MigratePortfoliosLiveMeasuresToMeasures portfoliosMigration = mock();
70   private final MigrateMeasuresAction underTest = new MigrateMeasuresAction(userSessionRule, dbTester.getDbClient(), measuresMigration, portfoliosMigration);
71   private final WsActionTester tester = new WsActionTester(underTest);
72
73   @Test
74   public void should_throw_if_migration_is_not_enabled() {
75     TestRequest request = tester.newRequest();
76
77     assertThatIllegalStateException()
78       .isThrownBy(request::execute)
79       .withMessage("Migration is not enabled. Please call the endpoint /api/system/prepare_migration?enable=true and retry.");
80   }
81
82   @Test
83   @DataProvider(value = {"0", "-1", "-100"})
84   public void should_throws_IAE_if_size_in_invalid(int size) throws SQLException {
85     enableMigration();
86
87     TestRequest request = tester
88       .newRequest()
89       .setParam(PARAM_SIZE, Integer.toString(size));
90
91     assertThatIllegalArgumentException()
92       .isThrownBy(request::execute)
93       .withMessage("Size must be greater than 0");
94   }
95
96   @Test
97   public void verify_example() throws SQLException {
98     enableMigration();
99     // 3 branches, 2 migrated
100     ComponentDto project = dbTester.components().insertPrivateProject();
101     ComponentDto branch1 = dbTester.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH));
102     dbTester.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH));
103     dbTester.getDbClient().branchDao().updateMeasuresMigrated(dbTester.getSession(), project.branchUuid(), true);
104     dbTester.getDbClient().branchDao().updateMeasuresMigrated(dbTester.getSession(), branch1.branchUuid(), true);
105     // 2 portfolios, 1 migrated
106     PortfolioDto portfolio1 = dbTester.components().insertPrivatePortfolioDto("name1");
107     dbTester.components().insertPrivatePortfolioDto("name2");
108     dbTester.getDbClient().portfolioDao().updateMeasuresMigrated(dbTester.getSession(), portfolio1.getUuid(), true);
109     dbTester.getSession().commit();
110
111     TestResponse response = tester.newRequest()
112       .execute();
113
114     assertJson(response.getInput()).isSimilarTo(getClass().getResource("example-migrate_measures.json"));
115   }
116
117   @Test
118   public void does_not_migrate_portfolios_if_measures_are_not_finished() throws SQLException {
119     enableMigration();
120     // 2 branches
121     ComponentDto project = dbTester.components().insertPrivateProject();
122     ComponentDto branch = dbTester.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH));
123     dbTester.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH));
124
125     TestResponse response = tester.newRequest()
126       .setParam(PARAM_SIZE, "2")
127       .execute();
128
129     assertThat(GSON.fromJson(response.getInput(), ActionResponse.class))
130       .isEqualTo(new ActionResponse("success", "2 branches or portfolios migrated", 3, 3, 0, 0));
131     verify(measuresMigration).migrate(List.of(project.uuid(), branch.uuid()));
132     verifyNoInteractions(portfoliosMigration);
133   }
134
135   @Test
136   public void migrate_portfolios_to_reach_the_requested_size() throws SQLException {
137     enableMigration();
138
139     // 1 branch
140     ComponentDto project = dbTester.components().insertPrivateProject();
141     // 2 portfolios
142     PortfolioDto portfolio1 = dbTester.components().insertPrivatePortfolioDto("name1");
143     dbTester.components().insertPrivatePortfolioDto("name2");
144
145     TestResponse response = tester.newRequest()
146       .setParam(PARAM_SIZE, "2")
147       .execute();
148
149     assertThat(GSON.fromJson(response.getInput(), ActionResponse.class))
150       .isEqualTo(new ActionResponse("success", "2 branches or portfolios migrated", 1, 1, 2, 2));
151     verify(measuresMigration).migrate(List.of(project.uuid()));
152     verify(portfoliosMigration).migrate(List.of(portfolio1.getUuid()));
153   }
154
155   @Test
156   public void migrate_portfolios_only_if_measures_are_done() throws SQLException {
157     enableMigration();
158     // 2 branches, all migrated
159     ComponentDto project = dbTester.components().insertPrivateProject();
160     ComponentDto branch1 = dbTester.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH));
161     dbTester.getDbClient().branchDao().updateMeasuresMigrated(dbTester.getSession(), project.branchUuid(), true);
162     dbTester.getDbClient().branchDao().updateMeasuresMigrated(dbTester.getSession(), branch1.branchUuid(), true);
163     // 2 portfolios, 1 migrated
164     PortfolioDto portfolio1 = dbTester.components().insertPrivatePortfolioDto("name1");
165     PortfolioDto portfolio2 = dbTester.components().insertPrivatePortfolioDto("name2");
166     dbTester.getDbClient().portfolioDao().updateMeasuresMigrated(dbTester.getSession(), portfolio1.getUuid(), true);
167     dbTester.commit();
168
169     TestResponse response = tester.newRequest()
170       .setParam(PARAM_SIZE, "2")
171       .execute();
172
173     assertThat(GSON.fromJson(response.getInput(), ActionResponse.class))
174       .isEqualTo(new ActionResponse("success", "1 branches or portfolios migrated", 0, 2, 1, 2));
175     verifyNoInteractions(measuresMigration);
176     verify(portfoliosMigration).migrate(List.of(portfolio2.getUuid()));
177   }
178
179   @Test
180   public void does_nothing_if_migration_is_finished() throws SQLException {
181     enableMigration();
182     // 2 branches, all migrated
183     ComponentDto project = dbTester.components().insertPrivateProject();
184     ComponentDto branch1 = dbTester.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH));
185     dbTester.getDbClient().branchDao().updateMeasuresMigrated(dbTester.getSession(), project.branchUuid(), true);
186     dbTester.getDbClient().branchDao().updateMeasuresMigrated(dbTester.getSession(), branch1.branchUuid(), true);
187     // 2 portfolios, all migrated
188     PortfolioDto portfolio1 = dbTester.components().insertPrivatePortfolioDto("name1");
189     PortfolioDto portfolio2 = dbTester.components().insertPrivatePortfolioDto("name2");
190     dbTester.getDbClient().portfolioDao().updateMeasuresMigrated(dbTester.getSession(), portfolio1.getUuid(), true);
191     dbTester.getDbClient().portfolioDao().updateMeasuresMigrated(dbTester.getSession(), portfolio2.getUuid(), true);
192     dbTester.commit();
193
194     TestResponse response = tester.newRequest()
195       .setParam(PARAM_SIZE, "2")
196       .execute();
197
198     assertThat(GSON.fromJson(response.getInput(), ActionResponse.class))
199       .isEqualTo(new ActionResponse("success", "0 branches or portfolios migrated", 0, 2, 0, 2));
200     verifyNoInteractions(measuresMigration, portfoliosMigration);
201   }
202
203   private void enableMigration() throws SQLException {
204     Database database = dbTester.getDbClient().getDatabase();
205     new AddMeasuresMigratedColumnToProjectBranchesTable(database).execute();
206     new AddMeasuresMigratedColumnToPortfoliosTable(database).execute();
207     dbTester.getDbClient().propertiesDao().saveProperty(new PropertyDto().setKey(SYSTEM_MEASURES_MIGRATION_ENABLED).setValue("true"));
208   }
209
210   @Test
211   public void throws_ForbiddenException_if_user_is_not_logged_in() {
212     userSessionRule.anonymous();
213
214     TestRequest request = tester.newRequest();
215
216     assertThatExceptionOfType(ForbiddenException.class)
217       .isThrownBy(request::execute);
218   }
219
220   @Test
221   public void throws_ForbiddenException_if_user_is_not_system_admin() {
222     userSessionRule.logIn();
223
224     TestRequest request = tester.newRequest();
225
226     assertThatExceptionOfType(ForbiddenException.class)
227       .isThrownBy(request::execute);
228   }
229
230   private record ActionResponse(String status, String message, int remainingBranches, int totalBranches, int remainingPortfolios,
231                                 int totalPortfolios) {
232   }
233 }