]> source.dussan.org Git - sonarqube.git/blob
664235f34e9274a18dfbb602b33755af77224887
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 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.projectanalysis.ws;
21
22 import com.google.common.collect.ImmutableMap;
23 import com.tngtech.java.junit.dataprovider.DataProvider;
24 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
25 import com.tngtech.java.junit.dataprovider.UseDataProvider;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.Map;
29 import javax.annotation.Nullable;
30 import org.junit.Rule;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 import org.sonar.api.server.ws.WebService;
34 import org.sonar.api.utils.System2;
35 import org.sonar.api.web.UserRole;
36 import org.sonar.db.DbClient;
37 import org.sonar.db.DbSession;
38 import org.sonar.db.DbTester;
39 import org.sonar.db.component.BranchDao;
40 import org.sonar.db.component.BranchDto;
41 import org.sonar.db.component.ComponentDbTester;
42 import org.sonar.db.component.ComponentDto;
43 import org.sonar.db.component.ComponentTesting;
44 import org.sonar.db.component.SnapshotDto;
45 import org.sonar.db.newcodeperiod.NewCodePeriodDto;
46 import org.sonar.server.component.TestComponentFinder;
47 import org.sonar.server.exceptions.ForbiddenException;
48 import org.sonar.server.exceptions.NotFoundException;
49 import org.sonar.server.tester.UserSessionRule;
50 import org.sonar.server.ws.TestRequest;
51 import org.sonar.server.ws.WsActionTester;
52
53 import static org.assertj.core.api.Assertions.assertThat;
54 import static org.assertj.core.api.Assertions.assertThatThrownBy;
55 import static org.sonar.db.component.BranchDto.DEFAULT_PROJECT_MAIN_BRANCH_NAME;
56 import static org.sonar.db.newcodeperiod.NewCodePeriodType.SPECIFIC_ANALYSIS;
57 import static org.sonar.server.projectanalysis.ws.ProjectAnalysesWsParameters.PARAM_ANALYSIS;
58 import static org.sonar.server.projectanalysis.ws.ProjectAnalysesWsParameters.PARAM_BRANCH;
59 import static org.sonar.server.projectanalysis.ws.ProjectAnalysesWsParameters.PARAM_PROJECT;
60 import static org.sonarqube.ws.client.WsRequest.Method.POST;
61
62 @RunWith(DataProviderRunner.class)
63 public class SetBaselineActionTest {
64
65
66   @Rule
67   public UserSessionRule userSession = UserSessionRule.standalone();
68
69   @Rule
70   public DbTester db = DbTester.create(System2.INSTANCE);
71   private DbClient dbClient = db.getDbClient();
72   private DbSession dbSession = db.getSession();
73   private BranchDao branchDao = db.getDbClient().branchDao();
74   private ComponentDbTester tester = new ComponentDbTester(db);
75   private WsActionTester ws = new WsActionTester(new SetBaselineAction(dbClient, userSession, TestComponentFinder.from(db), branchDao));
76
77   @Test
78   @UseDataProvider("nullOrEmpty")
79   public void set_baseline_on_main_branch(@Nullable String branchName) {
80     ComponentDto project = tester.insertPrivateProject();
81     SnapshotDto analysis = db.components().insertSnapshot(project);
82     logInAsProjectAdministrator(project);
83
84     call(project.getKey(), branchName, analysis.getUuid());
85
86     NewCodePeriodDto loaded = dbClient.newCodePeriodDao().selectByBranch(dbSession, project.uuid(), project.uuid()).get();
87     assertThat(loaded.getValue()).isEqualTo(analysis.getUuid());
88     assertThat(loaded.getType()).isEqualTo(SPECIFIC_ANALYSIS);
89   }
90
91   @DataProvider
92   public static Object[][] nullOrEmpty() {
93     return new Object[][] {
94       {null},
95       {""},
96       {"     "},
97     };
98   }
99
100   @Test
101   public void set_baseline_on_non_main_branch() {
102     ComponentDto project = tester.insertPrivateProject();
103     ComponentDto branchComponent = tester.insertProjectBranch(project);
104     SnapshotDto analysis = db.components().insertSnapshot(branchComponent);
105     BranchDto branch = branchDao.selectByUuid(dbSession, branchComponent.uuid()).get();
106     logInAsProjectAdministrator(project);
107
108     call(project.getKey(), branch.getKey(), analysis.getUuid());
109
110     NewCodePeriodDto loaded = dbClient.newCodePeriodDao().selectByBranch(dbSession, project.uuid(), branch.getUuid()).get();
111     assertThat(loaded.getValue()).isEqualTo(analysis.getUuid());
112     assertThat(loaded.getType()).isEqualTo(SPECIFIC_ANALYSIS);
113   }
114
115   @Test
116   public void fail_when_user_is_not_admin() {
117     ComponentDto project = tester.insertPrivateProject();
118     SnapshotDto analysis = db.components().insertSnapshot(project);
119
120     assertThatThrownBy(() -> call(project.getKey(), DEFAULT_PROJECT_MAIN_BRANCH_NAME, analysis.getUuid()))
121       .isInstanceOf(ForbiddenException.class)
122       .hasMessage("Insufficient privileges");
123   }
124
125   @Test
126   @UseDataProvider("missingOrEmptyParamsAndFailureMessage")
127   public void fail_with_IAE_when_required_param_missing_or_empty(Map<String, String> params, String message) {
128     assertThatThrownBy(() -> call(params))
129       .isInstanceOf(IllegalArgumentException.class)
130       .hasMessage(message);
131   }
132
133   @DataProvider
134   public static Object[][] missingOrEmptyParamsAndFailureMessage() {
135     MapBuilder builder = new MapBuilder()
136       .put(PARAM_PROJECT, "project key")
137       .put(PARAM_BRANCH, "branch key")
138       .put(PARAM_ANALYSIS, "analysis uuid");
139
140     return new Object[][] {
141       {builder.put(PARAM_PROJECT, null).map, "The 'project' parameter is missing"},
142       {builder.put(PARAM_PROJECT, "").map, "The 'project' parameter is missing"},
143       {builder.put(PARAM_ANALYSIS, null).map, "The 'analysis' parameter is missing"},
144       {builder.put(PARAM_ANALYSIS, "").map, "The 'analysis' parameter is missing"},
145     };
146   }
147
148   @Test
149   @UseDataProvider("nonexistentParamsAndFailureMessage")
150   public void fail_with_IAE_when_required_param_nonexistent(Map<String, String> nonexistentParams, String regex) {
151     ComponentDto project = tester.insertPrivateProject();
152     SnapshotDto analysis = db.components().insertSnapshot(project);
153     logInAsProjectAdministrator(project);
154
155     Map<String, String> params = new HashMap<>();
156     params.put(PARAM_PROJECT, project.getKey());
157     params.put(PARAM_BRANCH, "master");
158     params.put(PARAM_ANALYSIS, analysis.getUuid());
159     params.putAll(nonexistentParams);
160
161     assertThatThrownBy(() -> call(params))
162       .isInstanceOf(NotFoundException.class);
163   }
164
165   @DataProvider
166   public static Object[][] nonexistentParamsAndFailureMessage() {
167     MapBuilder builder = new MapBuilder();
168
169     return new Object[][] {
170       {builder.put(PARAM_PROJECT, "nonexistent").map, "Project 'nonexistent' not found"},
171       {builder.put(PARAM_BRANCH, "nonexistent").map, "Branch 'nonexistent' in project .* not found"},
172       {builder.put(PARAM_ANALYSIS, "nonexistent").map, "Analysis 'nonexistent' is not found"},
173     };
174   }
175
176   @Test
177   public void fail_when_branch_does_not_belong_to_project() {
178     ComponentDto project = tester.insertPrivateProject();
179     SnapshotDto analysis = db.components().insertSnapshot(project);
180     logInAsProjectAdministrator(project);
181
182     ComponentDto otherProject = tester.insertPrivateProjectWithCustomBranch("develop");
183     BranchDto branchOfOtherProject = branchDao.selectByUuid(dbSession, otherProject.uuid()).get();
184
185     assertThatThrownBy(() -> call(project.getKey(), branchOfOtherProject.getKey(), analysis.getUuid()))
186       .isInstanceOf(NotFoundException.class)
187       .hasMessage(String.format("Branch '%s' in project '%s' not found", branchOfOtherProject.getKey(), project.getKey()));
188   }
189
190   @Test
191   public void fail_when_analysis_does_not_belong_to_main_branch_of_project() {
192     ComponentDto project = tester.insertPrivateProjectWithCustomBranch("branch1");
193     logInAsProjectAdministrator(project);
194
195     ComponentDto otherProject = ComponentTesting.newPrivateProjectDto();
196     SnapshotDto otherAnalysis = db.components().insertProjectAndSnapshot(otherProject);
197
198     assertThatThrownBy(() ->  call(project.getKey(), "branch1", otherAnalysis.getUuid()))
199       .isInstanceOf(IllegalArgumentException.class)
200       .hasMessage(String.format("Analysis '%s' does not belong to branch '%s' of project '%s'",
201         otherAnalysis.getUuid(), "branch1", project.getKey()));
202   }
203
204   @Test
205   public void fail_when_analysis_does_not_belong_to_non_main_branch_of_project() {
206     ComponentDto project = tester.insertPrivateProject();
207     tester.insertProjectBranch(project, b -> b.setKey("branch1"));
208     logInAsProjectAdministrator(project);
209
210     ComponentDto otherProject = ComponentTesting.newPrivateProjectDto();
211     SnapshotDto otherAnalysis = db.components().insertProjectAndSnapshot(otherProject);
212
213     assertThatThrownBy(() -> call(project.getKey(), "branch1", otherAnalysis.getUuid()))
214       .isInstanceOf(IllegalArgumentException.class)
215       .hasMessage(String.format("Analysis '%s' does not belong to branch '%s' of project '%s'",
216         otherAnalysis.getUuid(), "branch1", project.getKey()));
217   }
218
219   @Test
220   public void ws_parameters() {
221     WebService.Action definition = ws.getDef();
222
223     assertThat(definition.isPost()).isTrue();
224     assertThat(definition.key()).isEqualTo("set_baseline");
225     assertThat(definition.since()).isEqualTo("7.7");
226     assertThat(definition.isInternal()).isFalse();
227   }
228
229   private void logInAsProjectAdministrator(ComponentDto project) {
230     userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
231   }
232
233   private void call(Map<String, String> params) {
234     TestRequest httpRequest = ws.newRequest().setMethod(POST.name());
235
236     for (Map.Entry<String, String> param : params.entrySet()) {
237       httpRequest.setParam(param.getKey(), param.getValue());
238     }
239
240     httpRequest.execute();
241   }
242
243   private void call(String projectKey, @Nullable String branchKey, String analysisUuid) {
244     if (branchKey == null) {
245       call(ImmutableMap.of(
246         PARAM_PROJECT, projectKey,
247         PARAM_ANALYSIS, analysisUuid));
248     } else {
249       call(ImmutableMap.of(
250         PARAM_PROJECT, projectKey,
251         PARAM_BRANCH, branchKey,
252         PARAM_ANALYSIS, analysisUuid));
253     }
254   }
255
256   private static class MapBuilder {
257     private final Map<String, String> map;
258
259     private MapBuilder() {
260       this.map = Collections.emptyMap();
261     }
262
263     private MapBuilder(Map<String, String> map) {
264       this.map = map;
265     }
266
267     public MapBuilder put(String key, @Nullable String value) {
268       Map<String, String> copy = new HashMap<>(map);
269       if (value == null) {
270         copy.remove(key);
271       } else {
272         copy.put(key, value);
273       }
274       return new MapBuilder(copy);
275     }
276   }
277 }