diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2018-03-29 17:09:18 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-04-05 20:20:48 +0200 |
commit | 492942631b3c2612fd8ed9b03bd7db3261a38e58 (patch) | |
tree | 33059afc664bb0711675eaf563c755e75162d652 /tests | |
parent | 2104453573fa15d1c5c3f8cee703d2cf3ccced55 (diff) | |
download | sonarqube-492942631b3c2612fd8ed9b03bd7db3261a38e58.tar.gz sonarqube-492942631b3c2612fd8ed9b03bd7db3261a38e58.zip |
SONAR-10511 Project key renaming should rename deleted components too
Diffstat (limited to 'tests')
-rw-r--r-- | tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdateTest.java | 241 |
1 files changed, 217 insertions, 24 deletions
diff --git a/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdateTest.java b/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdateTest.java index f77c1d4fb9d..d4f004dd9f1 100644 --- a/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdateTest.java +++ b/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdateTest.java @@ -21,31 +21,43 @@ package org.sonarqube.tests.project; import com.sonar.orchestrator.Orchestrator; import com.sonar.orchestrator.build.SonarScanner; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.stream.Collectors; import javax.annotation.CheckForNull; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringUtils; import org.junit.After; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.DisableOnDebug; +import org.junit.rules.TemporaryFolder; import org.junit.rules.TestRule; import org.junit.rules.Timeout; import org.sonarqube.qa.util.Tester; import org.sonarqube.ws.Components; import org.sonarqube.ws.Organizations; import org.sonarqube.ws.Projects; +import org.sonarqube.ws.Projects.BulkUpdateKeyWsResponse.Key; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.WsResponse; import org.sonarqube.ws.client.components.SearchProjectsRequest; import org.sonarqube.ws.client.components.ShowRequest; +import org.sonarqube.ws.client.components.TreeRequest; +import org.sonarqube.ws.client.projects.BulkUpdateKeyRequest; import org.sonarqube.ws.client.projects.UpdateKeyRequest; -import org.sonarqube.ws.client.projects.CreateRequest; import util.ItUtils; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.groups.Tuple.tuple; import static util.ItUtils.projectDir; public class ProjectKeyUpdateTest { @@ -57,7 +69,8 @@ public class ProjectKeyUpdateTest { @Rule public TestRule safeguard = new DisableOnDebug(Timeout.seconds(300)); - + @Rule + public TemporaryFolder temp = new TemporaryFolder(); @Rule public Tester tester = new Tester(orchestrator).setElasticsearchHttpPort(ProjectSuite.SEARCH_HTTP_PORT); @@ -67,17 +80,18 @@ public class ProjectKeyUpdateTest { } @Test - public void update_key() { - analyzeXooSample(); - String newProjectKey = "another_project_key"; - Components.Component project = tester.wsClient().components().show(new ShowRequest().setComponent(PROJECT_KEY)).getComponent(); - assertThat(project.getKey()).isEqualTo(PROJECT_KEY); + public void update_key() throws IOException { + Organizations.Organization organization = tester.organizations().generate(); + File projectDir = new XooProjectBuilder(PROJECT_KEY) + .build(temp.newFolder()); + analyze(organization, projectDir); + assertThat(tester.projects().exists(PROJECT_KEY)).isTrue(); - tester.wsClient().projects().updateKey(new UpdateKeyRequest() - .setFrom(PROJECT_KEY) - .setTo(newProjectKey)); + String newProjectKey = "renamed"; + updateProjectKey(PROJECT_KEY, newProjectKey, false); - assertThat(tester.wsClient().components().show(new ShowRequest().setComponentId(project.getId())).getComponent().getKey()).isEqualTo(newProjectKey); + assertThat(tester.projects().exists(PROJECT_KEY)).isFalse(); + assertThat(tester.projects().exists(newProjectKey)).isTrue(); } @Test @@ -85,7 +99,7 @@ public class ProjectKeyUpdateTest { Organizations.Organization organization = tester.organizations().generate(); Projects.CreateWsResponse.Project project = createProject(organization, "one", "Foo"); - updateKey(project, "two"); + updateProjectKey(project.getKey(), "two", false); assertThat(isProjectInDatabase("one")).isFalse(); assertThat(isProjectInDatabase("two")).isTrue(); @@ -102,7 +116,7 @@ public class ProjectKeyUpdateTest { lockWritesOnProjectIndices(); - updateKey(project, "two"); + updateProjectKey(project.getKey(), "two", false); assertThat(isProjectInDatabase("one")).isFalse(); @@ -142,7 +156,7 @@ public class ProjectKeyUpdateTest { String initialKey = "com.sonarsource.it.samples:multi-modules-sample:module_a"; String newKey = "com.sonarsource.it.samples:multi-modules-sample:module_c"; - updateKey(initialKey, newKey); + updateModuleKey(initialKey, newKey); assertThat(isComponentInDatabase(initialKey)).isFalse(); assertThat(isComponentInDatabase(newKey)).isTrue(); @@ -168,7 +182,7 @@ public class ProjectKeyUpdateTest { String newKey = "com.sonarsource.it.samples:multi-modules-sample:module_c"; lockWritesOnProjectIndices(); - updateKey(initialKey, newKey); + updateModuleKey(initialKey, newKey); // api/components/search loads keys from db, so results are consistent assertThat(isComponentInDatabase(initialKey)).isFalse(); @@ -193,7 +207,133 @@ public class ProjectKeyUpdateTest { Thread.sleep(1_000L); recovered = keysInComponentSuggestions(newKey).contains(newKey) && keysInComponentSuggestions(initialKey).isEmpty(); } + } + + /** + * SONAR-10511 + */ + @Test + public void update_key_of_disabled_files() throws Exception { + Organizations.Organization organization = tester.organizations().generate(); + // first analysis + File projectWith2Files = new XooProjectBuilder(PROJECT_KEY) + .setFilesPerModule(2) + .build(temp.newFolder()); + analyze(organization, projectWith2Files); + assertThat(countFilesInProject()).isEqualTo(2); + + // second analysis emulates a deletion of file + File projectWith1File = new XooProjectBuilder(PROJECT_KEY) + .setFilesPerModule(1) + .build(temp.newFolder()); + analyze(organization, projectWith1File); + assertThat(countFilesInProject()).isEqualTo(1); + + // update the project key + updateProjectKey(PROJECT_KEY, "renamed", false); + ItUtils.expectNotFoundError(() -> tester.wsClient().components().show(new ShowRequest().setComponent(PROJECT_KEY))); + + // first analysis of the new project, which re-enables the deleted file + analyze(organization, projectWith2Files); + assertThat(countFilesInProject()).isEqualTo(2); + } + + /** + * SONAR-10511 + */ + @Test + public void update_of_project_key_includes_disabled_modules() throws Exception { + Organizations.Organization organization = tester.organizations().generate(); + + // first analysis + File projectWithModulesAB = new XooProjectBuilder(PROJECT_KEY) + .addModules("module_a", "module_b") + .build(temp.newFolder()); + analyze(organization, projectWithModulesAB); + assertThat(countFilesInProject()).isEqualTo(3); + + // second analysis emulates deletion of module_b + File projectWithModuleA = new XooProjectBuilder(PROJECT_KEY) + .addModules("module_a") + .build(temp.newFolder()); + analyze(organization, projectWithModuleA); + assertThat(countFilesInProject()).isEqualTo(2); + + // update the project key + updateProjectKey(PROJECT_KEY, "renamed", false); + assertThat(tester.projects().exists(PROJECT_KEY)).isFalse(); + + // analysis of new project, re-enabling the deleted module + File projectWithModulesBC = new XooProjectBuilder(PROJECT_KEY) + .addModules("module_b", "module_c") + .build(temp.newFolder()); + analyze(organization, projectWithModulesBC); + assertThat(countFilesInProject()).isEqualTo(3); + } + + @Test + public void simulate_update_key_of_modules() throws Exception { + Organizations.Organization organization = tester.organizations().generate(); + + File project = new XooProjectBuilder(PROJECT_KEY) + .addModules("module_a", "module_b") + .build(temp.newFolder()); + analyze(organization, project); + assertThat(tester.projects().exists(PROJECT_KEY)).isTrue(); + + // simulate update of project key + Projects.BulkUpdateKeyWsResponse response = updateProjectKey(PROJECT_KEY, "renamed", true); + + assertThat(tester.projects().exists(PROJECT_KEY)).isTrue(); + assertThat(tester.projects().exists("renamed")).isFalse(); + assertThat(response.getKeysList()) + .extracting(Key::getKey, Key::getNewKey) + .containsExactlyInAnyOrder( + tuple(PROJECT_KEY, "renamed"), + tuple(PROJECT_KEY + ":module_a", "renamed:module_a"), + tuple(PROJECT_KEY + ":module_b", "renamed:module_b")); + } + + @Test + public void simulate_update_key_of_disabled_modules() throws Exception { + Organizations.Organization organization = tester.organizations().generate(); + + // first analysis + File projectWithModulesAB = new XooProjectBuilder(PROJECT_KEY) + .addModules("module_a", "module_b") + .build(temp.newFolder()); + analyze(organization, projectWithModulesAB); + assertThat(countFilesInProject()).isEqualTo(3); + + // second analysis emulates deletion of module_b + File projectWithModuleA = new XooProjectBuilder(PROJECT_KEY) + .addModules("module_a") + .build(temp.newFolder()); + analyze(organization, projectWithModuleA); + assertThat(countFilesInProject()).isEqualTo(2); + + // update the project key + Projects.BulkUpdateKeyWsResponse response = updateProjectKey(PROJECT_KEY, "renamed", true); + + assertThat(tester.projects().exists(PROJECT_KEY)).isTrue(); + assertThat(tester.projects().exists("renamed")).isFalse(); + assertThat(response.getKeysList()) + .extracting(Key::getKey, Key::getNewKey) + .containsExactlyInAnyOrder( + tuple(PROJECT_KEY, "renamed"), + tuple(PROJECT_KEY + ":module_a", "renamed:module_a")); + } + + private int countFilesInProject() { + TreeRequest request = new TreeRequest().setComponent(PROJECT_KEY).setQualifiers(asList("FIL")); + return tester.wsClient().components().tree(request).getComponentsCount(); + } + + private void analyze(Organizations.Organization organization, File projectDir) { + orchestrator.executeBuild(SonarScanner.create(projectDir, + "sonar.organization", organization.getKey(), + "sonar.login", "admin", "sonar.password", "admin")); } private void lockWritesOnProjectIndices() throws Exception { @@ -206,17 +346,20 @@ public class ProjectKeyUpdateTest { tester.elasticsearch().unlockWrites("projectmeasures"); } - private void updateKey(Projects.CreateWsResponse.Project project, String newKey) { - tester.wsClient().projects().updateKey(new UpdateKeyRequest().setFrom(project.getKey()).setTo(newKey)); + private void updateModuleKey(String initialKey, String newKey) { + tester.wsClient().projects().updateKey(new UpdateKeyRequest().setFrom(initialKey).setTo(newKey)); } - private void updateKey(String initialKey, String newKey) { - tester.wsClient().projects().updateKey(new UpdateKeyRequest().setFrom(initialKey).setTo(newKey)); + private Projects.BulkUpdateKeyWsResponse updateProjectKey(String initialKey, String newKey, boolean dryRun) { + return tester.wsClient().projects().bulkUpdateKey(new BulkUpdateKeyRequest() + .setProject(initialKey) + .setFrom(initialKey) + .setTo(newKey) + .setDryRun(String.valueOf(dryRun))); } private Projects.CreateWsResponse.Project createProject(Organizations.Organization organization, String key, String name) { - CreateRequest createRequest = new CreateRequest().setProject(key).setName(name).setOrganization(organization.getKey()); - return tester.wsClient().projects().create(createRequest).getProject(); + return tester.projects().provision(organization, r -> r.setProject(key).setName(name)); } private boolean isProjectInDatabase(String projectKey) { @@ -255,8 +398,58 @@ public class ProjectKeyUpdateTest { .collect(Collectors.toList()); } - private void analyzeXooSample() { - SonarScanner build = SonarScanner.create(projectDir("shared/xoo-sample")); - orchestrator.executeBuild(build); + private static class XooProjectBuilder { + private final String key; + private final List<String> moduleKeys = new ArrayList<>(); + private int filesPerModule = 1; + + XooProjectBuilder(String projectKey) { + this.key = projectKey; + } + + XooProjectBuilder addModules(String key, String... otherKeys) { + this.moduleKeys.add(key); + this.moduleKeys.addAll(asList(otherKeys)); + return this; + } + + XooProjectBuilder setFilesPerModule(int i) { + this.filesPerModule = i; + return this; + } + + File build(File dir) { + for (String moduleKey : moduleKeys) { + generateModule(moduleKey, new File(dir, moduleKey), new Properties()); + } + Properties additionalProps = new Properties(); + additionalProps.setProperty("sonar.modules", StringUtils.join(moduleKeys, ",")); + generateModule(key, dir, additionalProps); + return dir; + } + + private void generateModule(String key, File dir, Properties additionalProps) { + try { + File sourceDir = new File(dir, "src"); + FileUtils.forceMkdir(sourceDir); + for (int i = 0; i < filesPerModule; i++) { + File sourceFile = new File(sourceDir, "File" + i + ".xoo"); + FileUtils.write(sourceFile, "content of " + sourceFile.getName()); + } + Properties props = new Properties(); + props.setProperty("sonar.projectKey", key); + props.setProperty("sonar.projectName", key); + props.setProperty("sonar.projectVersion", "1.0"); + props.setProperty("sonar.sources", sourceDir.getName()); + props.putAll(additionalProps); + File propsFile = new File(dir, "sonar-project.properties"); + try (OutputStream output = FileUtils.openOutputStream(propsFile)) { + props.store(output, "generated"); + } + } catch (IOException e) { + throw new IllegalStateException(e); + } + } } + } |