blob: 4669900dd3f77289152086e042c27452bae6a5a4 [file] [log] [blame]
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.googlesource.gerrit.plugins.renameproject;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.common.cache.Cache;
import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit.Result;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.acceptance.UseLocalDisk;
import com.google.gerrit.acceptance.UseSsh;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.Change.Id;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
import com.google.gerrit.extensions.client.ProjectWatchInfo;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.renameproject.RenameProject.Input;
import java.io.OutputStream;
import java.util.List;
import javax.inject.Named;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.transport.URIish;
import org.junit.Test;
@TestPlugin(
name = "rename-project",
sysModule = "com.googlesource.gerrit.plugins.renameproject.Module",
sshModule = "com.googlesource.gerrit.plugins.renameproject.SshModule")
@UseSsh
public class RenameIT extends LightweightPluginDaemonTest {
private static final String PLUGIN_NAME = "rename-project";
private static final String NEW_PROJECT_NAME = "newProject";
private static final String NON_EXISTING_NAME = "nonExistingProject";
private static final String CACHE_NAME = "changeid_project";
private static final String REPLICATION_OPTION = "--replication";
private static final String URL = "ssh://localhost:29418";
private static final String RENAME_REGEX = "[a-zA-Z]+";
@Inject private RequestScopeOperations requestScopeOperations;
@Inject
@Named(CACHE_NAME)
private Cache<Id, String> changeIdProjectCache;
@Test
@UseLocalDisk
public void testRenameViaSshSuccessful() throws Exception {
createChange();
adminSshSession.exec(PLUGIN_NAME + " " + project.get() + " " + NEW_PROJECT_NAME);
adminSshSession.assertSuccess();
ProjectState projectState = projectCache.get(Project.nameKey(NEW_PROJECT_NAME));
assertThat(projectState).isNotNull();
assertThat(queryProvider.get().byProject(project)).isEmpty();
assertThat(queryProvider.get().byProject(Project.nameKey(NEW_PROJECT_NAME))).isNotEmpty();
}
@Test
@UseLocalDisk
public void testRenameReplicationViaSshNotAdminUser() throws Exception {
createChange();
userSshSession.exec(
PLUGIN_NAME + " " + project.get() + " " + NEW_PROJECT_NAME + " " + REPLICATION_OPTION);
userSshSession.assertFailure();
assertThat(userSshSession.getError()).contains("Not allowed to replicate rename");
}
@Test
@UseLocalDisk
public void testRenameReplicationViaSshAdminUser() throws Exception {
createChange();
adminSshSession.exec(
PLUGIN_NAME + " " + project.get() + " " + NEW_PROJECT_NAME + " " + REPLICATION_OPTION);
adminSshSession.assertSuccess();
ProjectState projectState = projectCache.get(Project.nameKey(NEW_PROJECT_NAME));
assertThat(projectState).isNotNull();
}
@Test
@UseLocalDisk
public void testRenameViaSshWithEmptyNewName() throws Exception {
createChange();
String newProjectName = "";
adminSshSession.exec(PLUGIN_NAME + " " + project.get() + " " + newProjectName);
adminSshSession.assertFailure();
ProjectState projectState = projectCache.get(Project.nameKey(newProjectName));
assertThat(projectState).isNull();
}
@Test
@UseLocalDisk
public void testRenameAllProjectsFail() throws Exception {
createChange();
adminSshSession.exec(PLUGIN_NAME + " " + allProjects.get() + " " + NEW_PROJECT_NAME);
adminSshSession.assertFailure();
ProjectState projectState = projectCache.get(Project.nameKey(NEW_PROJECT_NAME));
assertThat(projectState).isNull();
}
@Test
@UseLocalDisk
public void testRenameExistingProjectFail() throws Exception {
createChange();
adminSshSession.exec(PLUGIN_NAME + " " + project.get() + " " + project.get());
adminSshSession.assertFailure();
}
@Test
@UseLocalDisk
public void testRenameReplicationViaSshOnNonExisting() throws Exception {
createChange();
adminSshSession.exec(
PLUGIN_NAME + " " + NON_EXISTING_NAME + " " + project.get() + " " + REPLICATION_OPTION);
assertThat(adminSshSession.getError()).contains("project " + NON_EXISTING_NAME + " not found");
adminSshSession.assertFailure();
}
@Test
@UseLocalDisk
public void testRenameNonExistingProjectFail() throws Exception {
createChange();
adminSshSession.exec(PLUGIN_NAME + " " + NON_EXISTING_NAME + " " + project.get());
assertThat(adminSshSession.getError()).contains("project " + NON_EXISTING_NAME + " not found");
adminSshSession.assertFailure();
}
@Test
@UseLocalDisk
public void testRenameSubscribedFail() throws Exception {
NameKey superProject = createProjectOverAPI("super-project", null, true, null);
TestRepository<?> superRepo = cloneProject(superProject);
NameKey subProject = createProjectOverAPI("subscribed-to-project", null, true, null);
SubmoduleUtil.allowSubmoduleSubscription(
metaDataUpdateFactory,
projectCache,
projectConfigFactory,
subProject,
"refs/heads/master",
superProject,
"refs/heads/master",
true);
SubmoduleUtil.createSubmoduleSubscription(cfg, superRepo, "master", subProject.get(), "master");
adminSshSession.exec(PLUGIN_NAME + " " + subProject.get() + " " + NEW_PROJECT_NAME);
adminSshSession.assertFailure();
}
@Test
@UseLocalDisk
public void testRenameWatchedProject() throws Exception {
String oldProject = project.get();
watch(oldProject);
List<ProjectWatchInfo> watchedProjects = gApi.accounts().self().getWatchedProjects();
assertThat(watchedProjects.stream().allMatch(pwi -> pwi.project.equals(oldProject))).isTrue();
adminSshSession.exec(PLUGIN_NAME + " " + oldProject + " " + NEW_PROJECT_NAME);
adminSshSession.assertSuccess();
watchedProjects = gApi.accounts().self().getWatchedProjects();
assertThat(watchedProjects.stream().allMatch(pwi -> pwi.project.equals(NEW_PROJECT_NAME)))
.isTrue();
assertThat(watchedProjects.size()).isEqualTo(1);
}
@Test
@UseLocalDisk
public void testRenameClearedOldChangeIdLinkInCaches() throws Exception {
Result result = createChange();
String oldProject = project.get();
Id changeID = result.getChange().getId();
changeIdProjectCache.put(changeID, oldProject);
adminSshSession.exec(PLUGIN_NAME + " " + oldProject + " " + NEW_PROJECT_NAME);
adminSshSession.assertSuccess();
assertThat(changeIdProjectCache.getIfPresent(changeID)).isNull();
}
@Test
@UseLocalDisk
@GerritConfig(name = "plugin.rename-project.url", value = URL)
public void testReplicateRename() throws Exception {
RenameProject renameProject = plugin.getSysInjector().getInstance(RenameProject.class);
SshHelper sshHelper = mock(SshHelper.class);
OutputStream errStream = mock(OutputStream.class);
Input input = new Input();
input.name = NEW_PROJECT_NAME;
String expectedCommand =
PLUGIN_NAME + " " + project.get() + " " + NEW_PROJECT_NAME + " " + REPLICATION_OPTION;
when(sshHelper.newErrorBufferStream()).thenReturn(errStream);
when(errStream.toString()).thenReturn("");
renameProject.replicateRename(sshHelper, input, project);
verify(sshHelper, atLeastOnce())
.executeRemoteSsh(eq(new URIish(URL)), eq(expectedCommand), eq(errStream));
}
@Test
@UseLocalDisk
public void testRenameViaHttpSuccessful() throws Exception {
createChange();
RestResponse r = renameProjectTo(NEW_PROJECT_NAME);
r.assertOK();
ProjectState projectState = projectCache.get(Project.nameKey(NEW_PROJECT_NAME));
assertThat(projectState).isNotNull();
assertThat(queryProvider.get().byProject(project)).isEmpty();
assertThat(queryProvider.get().byProject(Project.nameKey(NEW_PROJECT_NAME))).isNotEmpty();
}
@Test
@UseLocalDisk
public void testRenameViaHttpWithEmptyNewName() throws Exception {
createChange();
String newProjectName = "";
RestResponse r = renameProjectTo(newProjectName);
r.assertBadRequest();
ProjectState projectState = projectCache.get(Project.nameKey(newProjectName));
assertThat(projectState).isNull();
}
@Test
@UseLocalDisk
@GerritConfig(name = "plugin.rename-project.renameRegex", value = RENAME_REGEX)
public void testRenameViaHttpWithNonMatchingNameFail() throws Exception {
createChange();
RestResponse r = renameProjectTo(NEW_PROJECT_NAME + "1");
r.assertBadRequest();
ProjectState projectState = projectCache.get(Project.nameKey(NEW_PROJECT_NAME));
assertThat(projectState).isNull();
}
@Test
@UseLocalDisk
@GerritConfig(name = "plugin.rename-project.renameRegex", value = RENAME_REGEX)
public void testRenameViaHttpWithMatchingNameSuccess() throws Exception {
createChange();
RestResponse r = renameProjectTo(NEW_PROJECT_NAME);
r.assertOK();
ProjectState projectState = projectCache.get(Project.nameKey(NEW_PROJECT_NAME));
assertThat(projectState).isNotNull();
assertThat(queryProvider.get().byProject(project)).isEmpty();
assertThat(queryProvider.get().byProject(Project.nameKey(NEW_PROJECT_NAME))).isNotEmpty();
}
private RestResponse renameProjectTo(String newName) throws Exception {
requestScopeOperations.setApiUser(user.id());
sender.clear();
String endPoint = "/projects/" + project.get() + "/" + PLUGIN_NAME + "~rename";
Input i = new Input();
i.name = newName;
i.continueWithRename = true;
return adminRestSession.post(endPoint, i);
}
}