]> source.dussan.org Git - sonarqube.git/blob
18772de9c9c1c9bf0474a8d3ee8a62a4575ac915
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2020 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.component;
21
22 import com.google.common.collect.ImmutableSet;
23 import org.junit.Rule;
24 import org.junit.Test;
25 import org.junit.rules.ExpectedException;
26 import org.sonar.api.utils.System2;
27 import org.sonar.api.web.UserRole;
28 import org.sonar.db.DbClient;
29 import org.sonar.db.DbSession;
30 import org.sonar.db.DbTester;
31 import org.sonar.db.component.ComponentDbTester;
32 import org.sonar.db.component.ComponentDto;
33 import org.sonar.db.component.ComponentTesting;
34 import org.sonar.server.es.ProjectIndexer;
35 import org.sonar.server.es.TestProjectIndexers;
36 import org.sonar.server.exceptions.BadRequestException;
37 import org.sonar.server.exceptions.ForbiddenException;
38 import org.sonar.server.project.Project;
39 import org.sonar.server.project.ProjectLifeCycleListeners;
40 import org.sonar.server.project.RekeyedProject;
41 import org.sonar.server.tester.UserSessionRule;
42
43 import static java.util.Collections.emptyList;
44 import static org.assertj.core.api.Assertions.assertThat;
45 import static org.mockito.Mockito.mock;
46 import static org.mockito.Mockito.verify;
47 import static org.sonar.db.component.ComponentTesting.newFileDto;
48 import static org.sonar.db.component.ComponentTesting.newModuleDto;
49
50 public class ComponentServiceUpdateKeyTest {
51
52   private System2 system2 = System2.INSTANCE;
53
54   @Rule
55   public UserSessionRule userSession = UserSessionRule.standalone();
56   @Rule
57   public ExpectedException expectedException = ExpectedException.none();
58   @Rule
59   public DbTester db = DbTester.create(system2);
60
61   private ComponentDbTester componentDb = new ComponentDbTester(db);
62   private DbClient dbClient = db.getDbClient();
63   private DbSession dbSession = db.getSession();
64   private TestProjectIndexers projectIndexers = new TestProjectIndexers();
65   private ProjectLifeCycleListeners projectLifeCycleListeners = mock(ProjectLifeCycleListeners.class);
66   private ComponentService underTest = new ComponentService(dbClient, userSession, projectIndexers, projectLifeCycleListeners);
67
68   @Test
69   public void update_project_key() {
70     ComponentDto project = insertSampleProject();
71     ComponentDto file = componentDb.insertComponent(ComponentTesting.newFileDto(project, null).setDbKey("sample:root:src/File.xoo"));
72     ComponentDto inactiveFile = componentDb.insertComponent(ComponentTesting.newFileDto(project, null).setDbKey("sample:root:src/InactiveFile.xoo").setEnabled(false));
73
74     dbSession.commit();
75
76     logInAsProjectAdministrator(project);
77     underTest.updateKey(dbSession, componentDb.getProjectDto(project), "sample2:root");
78     dbSession.commit();
79
80     // Check project key has been updated
81     assertThat(db.getDbClient().componentDao().selectByKey(dbSession, project.getDbKey())).isEmpty();
82     assertThat(db.getDbClient().componentDao().selectByKey(dbSession, "sample2:root")).isNotNull();
83
84     // Check file key has been updated
85     assertThat(db.getDbClient().componentDao().selectByKey(dbSession, file.getDbKey())).isEmpty();
86     assertThat(db.getDbClient().componentDao().selectByKey(dbSession, "sample2:root:src/File.xoo")).isNotNull();
87     assertThat(db.getDbClient().componentDao().selectByKey(dbSession, "sample2:root:src/InactiveFile.xoo")).isNotNull();
88
89     assertThat(dbClient.componentDao().selectByKey(dbSession, inactiveFile.getDbKey())).isEmpty();
90
91     assertThat(projectIndexers.hasBeenCalled(project.uuid(), ProjectIndexer.Cause.PROJECT_KEY_UPDATE)).isTrue();
92   }
93
94   @Test
95   public void update_provisioned_project_key() {
96     ComponentDto provisionedProject = insertProject("provisionedProject");
97
98     dbSession.commit();
99
100     logInAsProjectAdministrator(provisionedProject);
101     underTest.updateKey(dbSession, componentDb.getProjectDto(provisionedProject), "provisionedProject2");
102     dbSession.commit();
103
104     assertComponentKeyHasBeenUpdated(provisionedProject.getDbKey(), "provisionedProject2");
105     assertThat(projectIndexers.hasBeenCalled(provisionedProject.uuid(), ProjectIndexer.Cause.PROJECT_KEY_UPDATE)).isTrue();
106   }
107
108   @Test
109   public void fail_to_update_project_key_without_admin_permission() {
110     expectedException.expect(ForbiddenException.class);
111
112     ComponentDto project = insertSampleProject();
113     userSession.logIn("john").addProjectPermission(UserRole.USER, project);
114
115     underTest.updateKey(dbSession, componentDb.getProjectDto(project), "sample2:root");
116   }
117
118   @Test
119   public void fail_if_old_key_and_new_key_are_the_same() {
120     ComponentDto project = insertSampleProject();
121     ComponentDto anotherProject = componentDb.insertPrivateProject();
122     logInAsProjectAdministrator(project);
123
124     expectedException.expect(IllegalArgumentException.class);
125     expectedException.expectMessage("Impossible to update key: a component with key \"" + anotherProject.getDbKey() + "\" already exists.");
126
127     underTest.updateKey(dbSession, componentDb.getProjectDto(project), anotherProject.getDbKey());
128   }
129
130   @Test
131   public void fail_if_new_key_is_empty() {
132     ComponentDto project = insertSampleProject();
133     logInAsProjectAdministrator(project);
134
135     expectedException.expect(BadRequestException.class);
136     expectedException.expectMessage("Malformed key for ''. It cannot be empty nor contain whitespaces.");
137
138     underTest.updateKey(dbSession, componentDb.getProjectDto(project), "");
139   }
140
141   @Test
142   public void fail_if_new_key_is_invalid() {
143     ComponentDto project = insertSampleProject();
144     logInAsProjectAdministrator(project);
145
146     expectedException.expect(BadRequestException.class);
147     expectedException.expectMessage("Malformed key for 'sample root'. It cannot be empty nor contain whitespaces.");
148
149     underTest.updateKey(dbSession, componentDb.getProjectDto(project), "sample root");
150   }
151
152   @Test
153   public void bulk_update_key() {
154     ComponentDto project = componentDb.insertPublicProject(db.organizations().insert(), c -> c.setDbKey("my_project"));
155     ComponentDto module = componentDb.insertComponent(newModuleDto(project).setDbKey("my_project:root:module"));
156     ComponentDto inactiveModule = componentDb.insertComponent(newModuleDto(project).setDbKey("my_project:root:inactive_module").setEnabled(false));
157     ComponentDto file = componentDb.insertComponent(newFileDto(module, null).setDbKey("my_project:root:module:src/File.xoo"));
158     ComponentDto inactiveFile = componentDb.insertComponent(newFileDto(module, null).setDbKey("my_project:root:module:src/InactiveFile.xoo").setEnabled(false));
159
160     underTest.bulkUpdateKey(dbSession, componentDb.getProjectDto(project), "my_", "your_");
161
162     assertComponentKeyUpdated(project.getDbKey(), "your_project");
163     assertComponentKeyUpdated(module.getDbKey(), "your_project:root:module");
164     assertComponentKeyUpdated(file.getDbKey(), "your_project:root:module:src/File.xoo");
165     assertComponentKeyUpdated(inactiveModule.getDbKey(), "your_project:root:inactive_module");
166     assertComponentKeyUpdated(inactiveFile.getDbKey(), "your_project:root:module:src/InactiveFile.xoo");
167     verify(projectLifeCycleListeners).onProjectsRekeyed(ImmutableSet.of(
168       new RekeyedProject(new Project(project.uuid(), "your_project", project.name(), project.uuid(), emptyList()), "my_project")));
169   }
170
171   @Test
172   public void bulk_update_key_with_branch_and_pr() {
173     ComponentDto project = componentDb.insertPublicProject(db.organizations().insert(), c -> c.setDbKey("my_project"));
174     ComponentDto branch = componentDb.insertProjectBranch(project);
175     ComponentDto module = componentDb.insertComponent(newModuleDto(branch).setDbKey("my_project:root:module"));
176     ComponentDto file = componentDb.insertComponent(newFileDto(module, null).setDbKey("my_project:root:module:src/File.xoo"));
177
178     underTest.bulkUpdateKey(dbSession, componentDb.getProjectDto(project), "my_", "your_");
179
180     assertComponentKeyUpdated(project.getDbKey(), "your_project");
181     assertComponentKeyUpdated(module.getDbKey(), "your_project:root:module");
182     assertComponentKeyUpdated(file.getDbKey(), "your_project:root:module:src/File.xoo");
183     verify(projectLifeCycleListeners).onProjectsRekeyed(ImmutableSet.of(
184       new RekeyedProject(new Project(project.uuid(), "your_project", project.name(), project.uuid(), emptyList()), "my_project")));
185   }
186
187   private void assertComponentKeyUpdated(String oldKey, String newKey) {
188     assertThat(dbClient.componentDao().selectByKey(dbSession, oldKey)).isEmpty();
189     assertThat(dbClient.componentDao().selectByKey(dbSession, newKey)).isPresent();
190   }
191
192   private ComponentDto insertSampleProject() {
193     return insertProject("sample:root");
194   }
195
196   private ComponentDto insertProject(String key) {
197     return componentDb.insertPrivateProject(db.organizations().insert(), c -> c.setDbKey(key));
198   }
199
200   private void assertComponentKeyHasBeenUpdated(String oldKey, String newKey) {
201     assertThat(dbClient.componentDao().selectByKey(dbSession, oldKey)).isEmpty();
202     assertThat(dbClient.componentDao().selectByKey(dbSession, newKey)).isPresent();
203   }
204
205   private void logInAsProjectAdministrator(ComponentDto provisionedProject) {
206     userSession.logIn("john").addProjectPermission(UserRole.ADMIN, provisionedProject);
207   }
208 }