3 * Copyright (C) 2009-2022 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.projectanalysis.ws;
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;
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;
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;
62 @RunWith(DataProviderRunner.class)
63 public class SetBaselineActionTest {
67 public UserSessionRule userSession = UserSessionRule.standalone();
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));
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);
84 call(project.getKey(), branchName, analysis.getUuid());
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);
92 public static Object[][] nullOrEmpty() {
93 return new Object[][] {
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);
108 call(project.getKey(), branch.getKey(), analysis.getUuid());
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);
116 public void fail_when_user_is_not_admin() {
117 ComponentDto project = tester.insertPrivateProject();
118 SnapshotDto analysis = db.components().insertSnapshot(project);
120 assertThatThrownBy(() -> call(project.getKey(), DEFAULT_PROJECT_MAIN_BRANCH_NAME, analysis.getUuid()))
121 .isInstanceOf(ForbiddenException.class)
122 .hasMessage("Insufficient privileges");
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);
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");
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"},
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);
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);
161 assertThatThrownBy(() -> call(params))
162 .isInstanceOf(NotFoundException.class);
166 public static Object[][] nonexistentParamsAndFailureMessage() {
167 MapBuilder builder = new MapBuilder();
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"},
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);
182 ComponentDto otherProject = tester.insertPrivateProjectWithCustomBranch("develop");
183 BranchDto branchOfOtherProject = branchDao.selectByUuid(dbSession, otherProject.uuid()).get();
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()));
191 public void fail_when_analysis_does_not_belong_to_main_branch_of_project() {
192 ComponentDto project = tester.insertPrivateProjectWithCustomBranch("branch1");
193 logInAsProjectAdministrator(project);
195 ComponentDto otherProject = ComponentTesting.newPrivateProjectDto();
196 SnapshotDto otherAnalysis = db.components().insertProjectAndSnapshot(otherProject);
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()));
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);
210 ComponentDto otherProject = ComponentTesting.newPrivateProjectDto();
211 SnapshotDto otherAnalysis = db.components().insertProjectAndSnapshot(otherProject);
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()));
220 public void ws_parameters() {
221 WebService.Action definition = ws.getDef();
223 assertThat(definition.isPost()).isTrue();
224 assertThat(definition.key()).isEqualTo("set_baseline");
225 assertThat(definition.since()).isEqualTo("7.7");
226 assertThat(definition.isInternal()).isFalse();
229 private void logInAsProjectAdministrator(ComponentDto project) {
230 userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
233 private void call(Map<String, String> params) {
234 TestRequest httpRequest = ws.newRequest().setMethod(POST.name());
236 for (Map.Entry<String, String> param : params.entrySet()) {
237 httpRequest.setParam(param.getKey(), param.getValue());
240 httpRequest.execute();
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));
249 call(ImmutableMap.of(
250 PARAM_PROJECT, projectKey,
251 PARAM_BRANCH, branchKey,
252 PARAM_ANALYSIS, analysisUuid));
256 private static class MapBuilder {
257 private final Map<String, String> map;
259 private MapBuilder() {
260 this.map = Collections.emptyMap();
263 private MapBuilder(Map<String, String> map) {
267 public MapBuilder put(String key, @Nullable String value) {
268 Map<String, String> copy = new HashMap<>(map);
272 copy.put(key, value);
274 return new MapBuilder(copy);