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.Optional;
27 import javax.annotation.Nullable;
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 import org.sonar.api.server.ws.WebService;
32 import org.sonar.api.utils.System2;
33 import org.sonar.api.web.UserRole;
34 import org.sonar.db.DbClient;
35 import org.sonar.db.DbSession;
36 import org.sonar.db.DbTester;
37 import org.sonar.db.component.BranchDao;
38 import org.sonar.db.component.BranchDto;
39 import org.sonar.db.component.BranchType;
40 import org.sonar.db.component.ComponentDto;
41 import org.sonar.db.component.SnapshotDto;
42 import org.sonar.db.newcodeperiod.NewCodePeriodDto;
43 import org.sonar.db.newcodeperiod.NewCodePeriodType;
44 import org.sonar.server.component.TestComponentFinder;
45 import org.sonar.server.exceptions.ForbiddenException;
46 import org.sonar.server.exceptions.NotFoundException;
47 import org.sonar.server.tester.UserSessionRule;
48 import org.sonar.server.ws.TestRequest;
49 import org.sonar.server.ws.WsActionTester;
51 import static java.util.Optional.ofNullable;
52 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
53 import static org.assertj.core.api.Assertions.assertThat;
54 import static org.assertj.core.api.Assertions.assertThatThrownBy;
55 import static org.sonar.server.projectanalysis.ws.ProjectAnalysesWsParameters.PARAM_BRANCH;
56 import static org.sonar.server.projectanalysis.ws.ProjectAnalysesWsParameters.PARAM_PROJECT;
57 import static org.sonarqube.ws.client.WsRequest.Method.POST;
59 @RunWith(DataProviderRunner.class)
60 public class UnsetBaselineActionTest {
64 public UserSessionRule userSession = UserSessionRule.standalone();
67 public DbTester db = DbTester.create(System2.INSTANCE);
69 private DbClient dbClient = db.getDbClient();
70 private DbSession dbSession = db.getSession();
71 private BranchDao branchDao = db.getDbClient().branchDao();
72 private WsActionTester ws = new WsActionTester(new UnsetBaselineAction(dbClient, userSession, TestComponentFinder.from(db), branchDao));
75 public void does_not_fail_and_has_no_effect_when_there_is_no_baseline_on_main_branch() {
76 ComponentDto project = db.components().insertPublicProject();
77 ComponentDto branch = db.components().insertProjectBranch(project);
78 SnapshotDto analysis = db.components().insertSnapshot(project);
79 logInAsProjectAdministrator(project);
81 call(project.getKey(), null);
83 verifyManualBaseline(project, null);
87 public void does_not_fail_and_has_no_effect_when_there_is_no_baseline_on_non_main_branch() {
88 ComponentDto project = db.components().insertPublicProject();
89 ComponentDto branch = db.components().insertProjectBranch(project);
90 SnapshotDto analysis = db.components().insertSnapshot(project);
91 logInAsProjectAdministrator(project);
93 call(project.getKey(), branch.getBranch());
95 verifyManualBaseline(branch, null);
99 public void unset_baseline_when_it_is_set_on_main_branch() {
100 ComponentDto project = db.components().insertPublicProject();
101 ComponentDto branch = db.components().insertProjectBranch(project);
102 SnapshotDto projectAnalysis = db.components().insertSnapshot(project);
103 SnapshotDto branchAnalysis = db.components().insertSnapshot(project);
104 db.newCodePeriods().insert(project.projectUuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, projectAnalysis.getUuid());
105 logInAsProjectAdministrator(project);
107 call(project.getKey(), null);
109 verifyManualBaseline(project, null);
113 public void unset_baseline_when_it_is_set_non_main_branch() {
114 ComponentDto project = db.components().insertPublicProject();
115 ComponentDto branch = db.components().insertProjectBranch(project);
116 db.components().insertSnapshot(branch);
117 SnapshotDto branchAnalysis = db.components().insertSnapshot(project);
118 db.newCodePeriods().insert(project.projectUuid(), branch.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, branchAnalysis.getUuid());
120 logInAsProjectAdministrator(project);
122 call(project.getKey(), branch.getBranch());
124 verifyManualBaseline(branch, null);
128 public void fail_when_user_is_not_admin_on_project() {
129 ComponentDto project = db.components().insertPublicProject();
130 db.components().insertProjectBranch(project);
132 assertThatThrownBy(() -> call(project.getKey(), null))
133 .isInstanceOf(ForbiddenException.class)
134 .hasMessage("Insufficient privileges");
138 public void fail_when_user_is_not_admin_on_project_of_branch() {
139 ComponentDto project = db.components().insertPublicProject();
140 ComponentDto branch = db.components().insertProjectBranch(project);
142 assertThatThrownBy(() -> call(project.getKey(), branch.getBranch()))
143 .isInstanceOf(ForbiddenException.class)
144 .hasMessage("Insufficient privileges");
148 @UseDataProvider("nullOrEmptyOrValue")
149 public void fail_with_IAE_when_missing_project_parameter(@Nullable String branchParam) {
150 ComponentDto project = db.components().insertPublicProject();
151 db.components().insertProjectBranch(project);
152 logInAsProjectAdministrator(project);
154 assertThatThrownBy(() -> call(null, branchParam))
155 .isInstanceOf(IllegalArgumentException.class)
156 .hasMessage("The 'project' parameter is missing");
160 @UseDataProvider("nullOrEmptyOrValue")
161 public void fail_with_IAE_when_project_parameter_empty(@Nullable String branchParam) {
162 ComponentDto project = db.components().insertPublicProject();
163 db.components().insertProjectBranch(project);
164 logInAsProjectAdministrator(project);
166 assertThatThrownBy(() -> call("", branchParam))
167 .isInstanceOf(IllegalArgumentException.class)
168 .hasMessage("The 'project' parameter is missing");
172 public static Object[][] nullOrEmptyOrValue() {
173 return new Object[][] {
176 {randomAlphabetic(10)},
181 @UseDataProvider("nullOrEmpty")
182 public void does_not_fail_with_IAE_when_missing_branch_parameter(@Nullable String branchParam) {
183 ComponentDto project = db.components().insertPublicProject();
184 db.components().insertProjectBranch(project);
185 logInAsProjectAdministrator(project);
187 call(project.getKey(), branchParam);
191 public static Object[][] nullOrEmpty() {
192 return new Object[][] {
199 public static Object[][] nonexistentParamsAndFailureMessage() {
200 return new Object[][] {
201 {ImmutableMap.of(PARAM_PROJECT, "nonexistent"), "Component 'nonexistent' on branch .* not found"},
202 {ImmutableMap.of(PARAM_BRANCH, "nonexistent"), "Component .* on branch 'nonexistent' not found"}
207 public void fail_when_branch_does_not_belong_to_project() {
208 ComponentDto project = db.components().insertPublicProject();
209 ComponentDto branch = db.components().insertProjectBranch(project);
210 ComponentDto otherProject = db.components().insertPublicProject();
211 ComponentDto otherBranch = db.components().insertProjectBranch(otherProject);
212 logInAsProjectAdministrator(project);
214 assertThatThrownBy(() -> call(project.getKey(), otherBranch.getKey()))
215 .isInstanceOf(NotFoundException.class)
216 .hasMessage(String.format("Branch '%s' in project '%s' not found", otherBranch.getKey(), project.getKey()));
220 public void fail_with_NotFoundException_when_branch_is_pull_request() {
221 ComponentDto project = db.components().insertPrivateProject();
222 ComponentDto pullRequest = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST));
223 logInAsProjectAdministrator(project);
225 assertThatThrownBy(() -> call(project.getKey(), pullRequest.getKey()))
226 .isInstanceOf(NotFoundException.class)
227 .hasMessage(String.format("Branch '%s' in project '%s' not found", pullRequest.getKey(), project.getKey()));
231 public void verify_ws_parameters() {
232 WebService.Action definition = ws.getDef();
234 assertThat(definition.isPost()).isTrue();
235 assertThat(definition.key()).isEqualTo("unset_baseline");
236 assertThat(definition.since()).isEqualTo("7.7");
237 assertThat(definition.isInternal()).isFalse();
240 private void logInAsProjectAdministrator(ComponentDto project) {
241 userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
244 private void call(@Nullable String project, @Nullable String branchName) {
245 TestRequest httpRequest = ws.newRequest().setMethod(POST.name());
246 ofNullable(project).ifPresent(t -> httpRequest.setParam(PARAM_PROJECT, t));
247 ofNullable(branchName).ifPresent(t -> httpRequest.setParam(PARAM_BRANCH, t));
249 httpRequest.execute();
252 private void verifyManualBaseline(ComponentDto project, @Nullable SnapshotDto projectAnalysis) {
253 BranchDto branchDto = db.getDbClient().branchDao().selectByUuid(dbSession, project.uuid()).get();
254 Optional<NewCodePeriodDto> newCodePeriod = db.getDbClient().newCodePeriodDao().selectByBranch(dbSession, branchDto.getProjectUuid(), branchDto.getUuid());
255 if (projectAnalysis == null) {
256 assertThat(newCodePeriod).isNotNull();
257 assertThat(newCodePeriod).isEmpty();
259 assertThat(newCodePeriod).isNotNull();
260 assertThat(newCodePeriod).isNotEmpty();
261 assertThat(newCodePeriod.get().getValue()).isEqualTo(projectAnalysis.getUuid());