diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/RestResponse.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/RestResponse.java index 9f93489e17..9e5d7020e6 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/RestResponse.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/RestResponse.java @@ -16,11 +16,16 @@ package com.google.gerrit.acceptance; import static com.google.gerrit.httpd.restapi.RestApiServlet.JSON_MAGIC; +import com.google.common.base.Preconditions; + import org.apache.http.HttpResponse; +import org.eclipse.jgit.util.IO; +import org.eclipse.jgit.util.RawParseUtils; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.nio.ByteBuffer; public class RestResponse { @@ -49,4 +54,19 @@ public class RestResponse { public int getStatusCode() { return response.getStatusLine().getStatusCode(); } + + public String getEntityContent() throws IOException { + Preconditions.checkNotNull(response, + "Response is not initialized."); + Preconditions.checkNotNull(response.getEntity(), + "Response.Entity is not initialized."); + ByteBuffer buf = IO.readWholeStream( + response.getEntity().getContent(), + 1024); + return RawParseUtils.decode( + buf.array(), + buf.arrayOffset(), + buf.limit()) + .trim(); + } } diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/BUCK b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/BUCK index af3070582b..b9c2d08836 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/BUCK +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/BUCK @@ -1,7 +1,8 @@ include_defs('//gerrit-acceptance-tests/tests.defs') acceptance_tests( - srcs = ['ChangeMessagesIT.java'], + srcs = ['ChangeMessagesIT.java', 'DeleteDraftChangeIT.java', + 'DeleteDraftPatchSetIT.java'], deps = [ ':util', '//gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git:util', diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeInfo.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeInfo.java index 27d74c06d5..fe8737e665 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeInfo.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeInfo.java @@ -19,6 +19,9 @@ import com.google.gerrit.reviewdb.client.Change; import java.util.List; public class ChangeInfo { + String id; + String project; + String branch; List messages; Change.Status status; } diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DeleteDraftChangeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DeleteDraftChangeIT.java new file mode 100644 index 0000000000..7d4aa3e6eb --- /dev/null +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DeleteDraftChangeIT.java @@ -0,0 +1,170 @@ +// 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.change; + +import static com.google.gerrit.acceptance.git.GitUtil.cloneProject; +import static com.google.gerrit.acceptance.git.GitUtil.createProject; +import static com.google.gerrit.acceptance.git.GitUtil.initSsh; +import static org.junit.Assert.assertEquals; + +import com.google.common.collect.Iterables; +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.SshSession; +import com.google.gerrit.acceptance.TestAccount; +import com.google.gerrit.acceptance.git.PushOneCommit; +import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; +import com.google.gerrit.reviewdb.server.ReviewDb; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.google.gwtorm.server.OrmException; +import com.google.gwtorm.server.SchemaFactory; +import com.google.inject.Inject; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + +public class DeleteDraftChangeIT extends AbstractDaemonTest { + + @Inject + private AccountCreator accounts; + + @Inject + private SchemaFactory reviewDbProvider; + + private TestAccount admin; + + private RestSession session; + private Git git; + private ReviewDb db; + + @Before + public void setUp() throws Exception { + admin = accounts.create("admin", "admin@example.com", "Administrator", + "Administrators"); + session = new RestSession(server, admin); + initSsh(admin); + Project.NameKey project = new Project.NameKey("p"); + SshSession sshSession = new SshSession(server, admin); + createProject(sshSession, project.get()); + git = cloneProject(sshSession.getUrl() + "/" + project.get()); + sshSession.close(); + db = reviewDbProvider.open(); + } + + @After + public void cleanup() { + db.close(); + } + + @Test + public void deleteChange() throws GitAPIException, + IOException { + String changeId = createChange(); + ChangeInfo c = getChange(changeId); + assertEquals("p~master~" + changeId, c.id); + assertEquals(Change.Status.NEW, c.status); + RestResponse r = deleteChange(changeId, session); + assertEquals("Change is not a draft", r.getEntityContent()); + assertEquals(409, r.getStatusCode()); + } + + @Test + public void deleteDraftChange() throws GitAPIException, + IOException, OrmException { + String changeId = createDraftChange(); + ChangeInfo c = getChange(changeId); + assertEquals("p~master~" + changeId, c.id); + assertEquals(Change.Status.DRAFT, c.status); + RestResponse r = deleteChange(changeId, session); + assertEquals(204, r.getStatusCode()); + } + + @Test + public void publishDraftChange() throws GitAPIException, + IOException { + String changeId = createDraftChange(); + ChangeInfo c = getChange(changeId); + assertEquals("p~master~" + changeId, c.id); + assertEquals(Change.Status.DRAFT, c.status); + RestResponse r = publishChange(changeId); + assertEquals(204, r.getStatusCode()); + c = getChange(changeId); + assertEquals(Change.Status.NEW, c.status); + } + + @Test + public void publishDraftPatchSet() throws GitAPIException, + IOException, OrmException { + String changeId = createDraftChange(); + ChangeInfo c = getChange(changeId); + assertEquals("p~master~" + changeId, c.id); + assertEquals(Change.Status.DRAFT, c.status); + RestResponse r = publishPatchSet(changeId); + assertEquals(204, r.getStatusCode()); + c = getChange(changeId); + assertEquals(Change.Status.NEW, c.status); + } + + private ChangeInfo getChange(String changeId) throws IOException { + RestResponse r = session.get("/changes/?q=" + changeId); + List c = (new Gson()).fromJson(r.getReader(), + new TypeToken>() {}.getType()); + return c.get(0); + } + + private String createChange() throws GitAPIException, + IOException { + PushOneCommit push = new PushOneCommit(db, admin.getIdent()); + return push.to(git, "refs/for/master").getChangeId(); + } + + private String createDraftChange() throws GitAPIException, IOException { + PushOneCommit push = new PushOneCommit(db, admin.getIdent()); + return push.to(git, "refs/drafts/master").getChangeId(); + } + + private static RestResponse deleteChange(String changeId, + RestSession s) throws IOException { + return s.delete("/changes/" + changeId); + } + + private RestResponse publishChange(String changeId) throws IOException { + return session.post("/changes/" + changeId + "/publish"); + } + + private RestResponse publishPatchSet(String changeId) throws IOException, + OrmException { + PatchSet patchSet = db.patchSets() + .get(Iterables.getOnlyElement(db.changes() + .byKey(new Change.Key(changeId))) + .currentPatchSetId()); + return session.post("/changes/" + + changeId + + "/revisions/" + + patchSet.getRevision().get() + + "/publish"); + } +} diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DeleteDraftPatchSetIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DeleteDraftPatchSetIT.java new file mode 100644 index 0000000000..834b7c3588 --- /dev/null +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DeleteDraftPatchSetIT.java @@ -0,0 +1,164 @@ +// 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.change; + +import static com.google.gerrit.acceptance.git.GitUtil.cloneProject; +import static com.google.gerrit.acceptance.git.GitUtil.createProject; +import static com.google.gerrit.acceptance.git.GitUtil.initSsh; +import static org.junit.Assert.assertEquals; + +import com.google.common.collect.Iterables; +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.SshSession; +import com.google.gerrit.acceptance.TestAccount; +import com.google.gerrit.acceptance.git.PushOneCommit; +import com.google.gerrit.acceptance.git.PushOneCommit.Result; +import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; +import com.google.gerrit.reviewdb.server.ReviewDb; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.google.gwtorm.server.OrmException; +import com.google.gwtorm.server.SchemaFactory; +import com.google.inject.Inject; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + +public class DeleteDraftPatchSetIT extends AbstractDaemonTest { + + @Inject + private AccountCreator accounts; + + @Inject + private SchemaFactory reviewDbProvider; + + private TestAccount admin; + private TestAccount user; + + private RestSession session; + private RestSession userSession; + private Git git; + private ReviewDb db; + + @Before + public void setUp() throws Exception { + admin = accounts.create("admin", "admin@example.com", "Administrator", + "Administrators"); + user = accounts.create("user", "user@example.com", "User"); + session = new RestSession(server, admin); + userSession = new RestSession(server, user); + initSsh(admin); + Project.NameKey project = new Project.NameKey("p"); + SshSession sshSession = new SshSession(server, admin); + createProject(sshSession, project.get()); + git = cloneProject(sshSession.getUrl() + "/" + project.get()); + sshSession.close(); + db = reviewDbProvider.open(); + } + + @After + public void cleanup() { + db.close(); + } + + @Test + public void deletePatchSet() throws GitAPIException, + IOException, OrmException { + String changeId = createChangeWith2PS("refs/for/master"); + PatchSet ps = getCurrentPatchSet(changeId); + ChangeInfo c = getChange(changeId); + assertEquals("p~master~" + changeId, c.id); + assertEquals(Change.Status.NEW, c.status); + RestResponse r = deletePatchSet(changeId, ps, session); + assertEquals("Patch set is not a draft.", r.getEntityContent()); + assertEquals(409, r.getStatusCode()); + } + + @Test + public void deleteDraftPatchSetNoACL() throws GitAPIException, + IOException, OrmException { + String changeId = createChangeWith2PS("refs/drafts/master"); + PatchSet ps = getCurrentPatchSet(changeId); + ChangeInfo c = getChange(changeId); + assertEquals("p~master~" + changeId, c.id); + assertEquals(Change.Status.DRAFT, c.status); + RestResponse r = deletePatchSet(changeId, ps, userSession); + assertEquals("Not found", r.getEntityContent()); + assertEquals(404, r.getStatusCode()); + } + + @Test + public void deleteDraftPatchSetAndChange() throws GitAPIException, + IOException, OrmException { + String changeId = createChangeWith2PS("refs/drafts/master"); + PatchSet ps = getCurrentPatchSet(changeId); + ChangeInfo c = getChange(changeId); + assertEquals("p~master~" + changeId, c.id); + assertEquals(Change.Status.DRAFT, c.status); + RestResponse r = deletePatchSet(changeId, ps, session); + assertEquals(204, r.getStatusCode()); + Change change = Iterables.getOnlyElement(db.changes().byKey( + new Change.Key(changeId)).toList()); + assertEquals(1, db.patchSets().byChange(change.getId()) + .toList().size()); + ps = getCurrentPatchSet(changeId); + r = deletePatchSet(changeId, ps, session); + assertEquals(204, r.getStatusCode()); + assertEquals(0, db.changes().byKey(new Change.Key(changeId)) + .toList().size()); + } + + private String createChangeWith2PS(String ref) throws GitAPIException, + IOException { + PushOneCommit push = new PushOneCommit(db, admin.getIdent()); + Result result = push.to(git, ref); + push = new PushOneCommit(db, admin.getIdent(), PushOneCommit.SUBJECT, + "b.txt", "4711", result.getChangeId()); + return push.to(git, ref).getChangeId(); + } + + private ChangeInfo getChange(String changeId) throws IOException { + RestResponse r = session.get("/changes/?q=" + changeId); + List c = (new Gson()).fromJson(r.getReader(), + new TypeToken>() {}.getType()); + return c.get(0); + } + + private PatchSet getCurrentPatchSet(String changeId) throws OrmException { + return db.patchSets() + .get(Iterables.getOnlyElement(db.changes() + .byKey(new Change.Key(changeId))) + .currentPatchSetId()); + } + + private static RestResponse deletePatchSet(String changeId, + PatchSet ps, RestSession s) throws IOException { + return s.delete("/changes/" + + changeId + + "/revisions/" + + ps.getRevision().get()); + } +}