Add acceptance test for project creation via REST
Change-Id: If5b28a6e4e948c3ef0a3edc61da7a35dda63c8d3 Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
@@ -0,0 +1,275 @@
|
||||
// Copyright (C) 2013 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.google.gerrit.acceptance.rest.project;
|
||||
|
||||
import static com.google.gerrit.acceptance.rest.project.ProjectAssert.assertProjectInfo;
|
||||
import static com.google.gerrit.acceptance.rest.project.ProjectAssert.assertProjectOwners;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.AccountCreator;
|
||||
import com.google.gerrit.acceptance.RestResponse;
|
||||
import com.google.gerrit.acceptance.RestSession;
|
||||
import com.google.gerrit.acceptance.TestAccount;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.Project.InheritableBoolean;
|
||||
import com.google.gerrit.reviewdb.client.Project.SubmitType;
|
||||
import com.google.gerrit.server.account.GroupCache;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.gerrit.server.project.ProjectCache;
|
||||
import com.google.gerrit.server.project.ProjectState;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import com.jcraft.jsch.JSchException;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class CreateProjectIT extends AbstractDaemonTest {
|
||||
|
||||
@Inject
|
||||
private AccountCreator accounts;
|
||||
|
||||
@Inject
|
||||
private ProjectCache projectCache;
|
||||
|
||||
@Inject
|
||||
private GroupCache groupCache;
|
||||
|
||||
@Inject
|
||||
private GitRepositoryManager git;
|
||||
|
||||
private TestAccount admin;
|
||||
private RestSession session;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
admin = accounts.create("admin", "admin@example.com", "Administrator",
|
||||
"Administrators");
|
||||
session = new RestSession(admin);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProject() throws IOException {
|
||||
final String newProjectName = "newProject";
|
||||
RestResponse r = session.put("/projects/" + newProjectName);
|
||||
assertEquals(HttpStatus.SC_CREATED, r.getStatusCode());
|
||||
@SuppressWarnings("serial")
|
||||
ProjectInfo p = (new Gson()).fromJson(r.getReader(), new TypeToken<ProjectInfo>() {}.getType());
|
||||
assertEquals(newProjectName, p.name);
|
||||
ProjectState projectState = projectCache.get(new Project.NameKey(newProjectName));
|
||||
assertNotNull(projectState);
|
||||
assertProjectInfo(projectState.getProject(), p);
|
||||
assertHead(newProjectName, "refs/heads/master");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectWithNameMismatch_BadRequest() throws IOException {
|
||||
ProjectInput in = new ProjectInput();
|
||||
in.name = "otherName";
|
||||
RestResponse r = session.put("/projects/someName", in);
|
||||
assertEquals(HttpStatus.SC_BAD_REQUEST, r.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectWithProperties() throws IOException {
|
||||
final String newProjectName = "newProject";
|
||||
ProjectInput in = new ProjectInput();
|
||||
in.description = "Test description";
|
||||
in.submit_type = SubmitType.CHERRY_PICK;
|
||||
in.use_contributor_agreements = InheritableBoolean.TRUE;
|
||||
in.use_signed_off_by = InheritableBoolean.TRUE;
|
||||
in.use_content_merge = InheritableBoolean.TRUE;
|
||||
in.require_change_id = InheritableBoolean.TRUE;
|
||||
RestResponse r = session.put("/projects/" + newProjectName, in);
|
||||
@SuppressWarnings("serial")
|
||||
ProjectInfo p = (new Gson()).fromJson(r.getReader(), new TypeToken<ProjectInfo>() {}.getType());
|
||||
assertEquals(newProjectName, p.name);
|
||||
Project project = projectCache.get(new Project.NameKey(newProjectName)).getProject();
|
||||
assertProjectInfo(project, p);
|
||||
assertEquals(in.description, project.getDescription());
|
||||
assertEquals(in.submit_type, project.getSubmitType());
|
||||
assertEquals(in.use_contributor_agreements, project.getUseContributorAgreements());
|
||||
assertEquals(in.use_signed_off_by, project.getUseSignedOffBy());
|
||||
assertEquals(in.use_content_merge, project.getUseContentMerge());
|
||||
assertEquals(in.require_change_id, project.getRequireChangeID());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateChildProject() throws IOException {
|
||||
final String parentName = "parent";
|
||||
RestResponse r = session.put("/projects/" + parentName);
|
||||
r.consume();
|
||||
final String childName = "child";
|
||||
ProjectInput in = new ProjectInput();
|
||||
in.parent = parentName;
|
||||
r = session.put("/projects/" + childName, in);
|
||||
Project project = projectCache.get(new Project.NameKey(childName)).getProject();
|
||||
assertEquals(in.parent, project.getParentName());
|
||||
}
|
||||
|
||||
public void testCreateChildProjectUnderNonExistingParent_UnprocessableEntity()
|
||||
throws IOException {
|
||||
ProjectInput in = new ProjectInput();
|
||||
in.parent = "non-existing-project";
|
||||
RestResponse r = session.put("/projects/child", in);
|
||||
assertEquals(HttpStatus.SC_UNPROCESSABLE_ENTITY, r.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectWithOwner() throws IOException {
|
||||
final String newProjectName = "newProject";
|
||||
ProjectInput in = new ProjectInput();
|
||||
in.owners = Lists.newArrayListWithCapacity(3);
|
||||
in.owners.add("Administrators"); // by name
|
||||
in.owners.add(groupUuid("Registered Users").get()); // by group UUID
|
||||
in.owners.add(Integer.toString(groupCache.get(new AccountGroup.NameKey("Anonymous Users"))
|
||||
.getId().get())); // by legacy group ID
|
||||
session.put("/projects/" + newProjectName, in);
|
||||
ProjectState projectState = projectCache.get(new Project.NameKey(newProjectName));
|
||||
Set<AccountGroup.UUID> expectedOwnerIds = Sets.newHashSetWithExpectedSize(3);
|
||||
expectedOwnerIds.add(groupUuid("Administrators"));
|
||||
expectedOwnerIds.add(groupUuid("Registered Users"));
|
||||
expectedOwnerIds.add(groupUuid("Anonymous Users"));
|
||||
assertProjectOwners(expectedOwnerIds, projectState);
|
||||
}
|
||||
|
||||
public void testCreateProjectWithNonExistingOwner_UnprocessableEntity()
|
||||
throws IOException {
|
||||
ProjectInput in = new ProjectInput();
|
||||
in.owners = Collections.singletonList("non-existing-group");
|
||||
RestResponse r = session.put("/projects/newProject", in);
|
||||
assertEquals(HttpStatus.SC_UNPROCESSABLE_ENTITY, r.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePermissionOnlyProject() throws IOException {
|
||||
final String newProjectName = "newProject";
|
||||
ProjectInput in = new ProjectInput();
|
||||
in.permissions_only = true;
|
||||
session.put("/projects/" + newProjectName, in);
|
||||
assertHead(newProjectName, GitRepositoryManager.REF_CONFIG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectWithEmptyCommit() throws IOException {
|
||||
final String newProjectName = "newProject";
|
||||
ProjectInput in = new ProjectInput();
|
||||
in.create_empty_commit = true;
|
||||
session.put("/projects/" + newProjectName, in);
|
||||
assertEmptyCommit(newProjectName, "refs/heads/master");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectWithBranches() throws IOException {
|
||||
final String newProjectName = "newProject";
|
||||
ProjectInput in = new ProjectInput();
|
||||
in.create_empty_commit = true;
|
||||
in.branches = Lists.newArrayListWithCapacity(3);
|
||||
in.branches.add("refs/heads/test");
|
||||
in.branches.add("refs/heads/master");
|
||||
in.branches.add("release"); // without 'refs/heads' prefix
|
||||
session.put("/projects/" + newProjectName, in);
|
||||
assertHead(newProjectName, "refs/heads/test");
|
||||
assertEmptyCommit(newProjectName, "refs/heads/test", "refs/heads/master",
|
||||
"refs/heads/release");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectWithoutCapability_Forbidden() throws OrmException,
|
||||
JSchException, IOException {
|
||||
TestAccount user = accounts.create("user", "user@example.com", "User");
|
||||
RestResponse r = (new RestSession(user)).put("/projects/newProject");
|
||||
assertEquals(HttpStatus.SC_FORBIDDEN, r.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectWhenProjectAlreadyExists_Conflict()
|
||||
throws OrmException, JSchException, IOException {
|
||||
RestResponse r = session.put("/projects/All-Projects");
|
||||
assertEquals(HttpStatus.SC_CONFLICT, r.getStatusCode());
|
||||
}
|
||||
|
||||
private AccountGroup.UUID groupUuid(String groupName) {
|
||||
return groupCache.get(new AccountGroup.NameKey(groupName)).getGroupUUID();
|
||||
}
|
||||
|
||||
private void assertHead(String projectName, String expectedRef)
|
||||
throws RepositoryNotFoundException, IOException {
|
||||
Repository repo = git.openRepository(new Project.NameKey(projectName));
|
||||
try {
|
||||
assertEquals(expectedRef, repo.getRef(Constants.HEAD).getTarget()
|
||||
.getName());
|
||||
} finally {
|
||||
repo.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertEmptyCommit(String projectName, String... refs)
|
||||
throws RepositoryNotFoundException, IOException {
|
||||
Repository repo = git.openRepository(new Project.NameKey(projectName));
|
||||
RevWalk rw = new RevWalk(repo);
|
||||
TreeWalk tw = new TreeWalk(repo);
|
||||
try {
|
||||
for (String ref : refs) {
|
||||
RevCommit commit = rw.lookupCommit(repo.getRef(ref).getObjectId());
|
||||
rw.parseBody(commit);
|
||||
tw.addTree(commit.getTree());
|
||||
assertFalse("ref " + ref + " has non empty commit", tw.next());
|
||||
tw.reset();
|
||||
}
|
||||
} finally {
|
||||
tw.release();
|
||||
rw.release();
|
||||
repo.close();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class ProjectInput {
|
||||
String name;
|
||||
String parent;
|
||||
String description;
|
||||
boolean permissions_only;
|
||||
boolean create_empty_commit;
|
||||
SubmitType submit_type;
|
||||
List<String> branches;
|
||||
List<String> owners;
|
||||
InheritableBoolean use_contributor_agreements;
|
||||
InheritableBoolean use_signed_off_by;
|
||||
InheritableBoolean use_content_merge;
|
||||
InheritableBoolean require_change_id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2013 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.google.gerrit.acceptance.rest.project;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.gerrit.extensions.restapi.Url;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.server.project.ProjectState;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class ProjectAssert {
|
||||
|
||||
public static void assertProjectInfo(Project project, ProjectInfo info) {
|
||||
if (info.name != null) {
|
||||
// 'name' is not set if returned in a map
|
||||
assertEquals(project.getName(), info.name);
|
||||
}
|
||||
assertEquals(project.getName(), Url.decode(info.id));
|
||||
Project.NameKey parentName = project.getParent(new Project.NameKey("All-Projects"));
|
||||
assertEquals(parentName != null ? parentName.get() : null, info.parent);
|
||||
assertEquals(project.getDescription(), Strings.nullToEmpty(info.description));
|
||||
}
|
||||
|
||||
public static void assertProjectOwners(Set<AccountGroup.UUID> expectedOwners,
|
||||
ProjectState state) {
|
||||
for (AccountGroup.UUID g : state.getOwners()) {
|
||||
assertTrue("unexpected owner group " + g, expectedOwners.remove(g));
|
||||
}
|
||||
assertTrue("missing owner groups: " + expectedOwners,
|
||||
expectedOwners.isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2013 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.google.gerrit.acceptance.rest.project;
|
||||
|
||||
public class ProjectInfo {
|
||||
public String id;
|
||||
public String name;
|
||||
public String parent;
|
||||
public String description;
|
||||
}
|
||||
Reference in New Issue
Block a user