summaryrefslogtreecommitdiffstats
path: root/javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java
diff options
context:
space:
mode:
Diffstat (limited to 'javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java')
-rw-r--r--javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java509
1 files changed, 509 insertions, 0 deletions
diff --git a/javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java
new file mode 100644
index 0000000000..c00c2aad40
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java
@@ -0,0 +1,509 @@
+// 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.google.gerrit.acceptance.rest;
+
+import static com.google.common.truth.TruthJUnit.assume;
+import static com.google.gerrit.acceptance.rest.AbstractRestApiBindingsTest.Method.GET;
+import static com.google.gerrit.extensions.common.testing.RobotCommentInfoSubject.assertThatList;
+import static java.util.stream.Collectors.toList;
+import static org.apache.http.HttpStatus.SC_NOT_FOUND;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.gerrit.extensions.api.changes.AddReviewerInput;
+import com.google.gerrit.extensions.api.changes.DraftInput;
+import com.google.gerrit.extensions.api.changes.ReviewInput;
+import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
+import com.google.gerrit.extensions.api.changes.ReviewInput.RobotCommentInput;
+import com.google.gerrit.extensions.client.Comment;
+import com.google.gerrit.extensions.client.Side;
+import com.google.gerrit.extensions.common.CommentInfo;
+import com.google.gerrit.extensions.common.FixReplacementInfo;
+import com.google.gerrit.extensions.common.FixSuggestionInfo;
+import com.google.gerrit.extensions.common.RobotCommentInfo;
+import com.google.gerrit.reviewdb.client.Patch;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.junit.Test;
+
+/**
+ * Tests for checking the bindings of the changes REST API.
+ *
+ * <p>These tests only verify that the change REST endpoints are correctly bound, they do no test
+ * the functionality of the change REST endpoints (for details see JavaDoc on {@link
+ * AbstractRestApiBindingsTest}).
+ */
+public class ChangesRestApiBindingsIT extends AbstractRestApiBindingsTest {
+ /**
+ * Change REST endpoints to be tested, each URL contains a placeholder for the change identifier.
+ */
+ private static final ImmutableList<RestCall> CHANGE_ENDPOINTS =
+ ImmutableList.of(
+ RestCall.get("/changes/%s"),
+ RestCall.get("/changes/%s/detail"),
+ RestCall.get("/changes/%s/topic"),
+ RestCall.put("/changes/%s/topic"),
+ RestCall.delete("/changes/%s/topic"),
+ RestCall.get("/changes/%s/in"),
+ RestCall.get("/changes/%s/hashtags"),
+ RestCall.get("/changes/%s/comments"),
+ RestCall.get("/changes/%s/robotcomments"),
+ RestCall.get("/changes/%s/drafts"),
+ RestCall.get("/changes/%s/assignee"),
+ RestCall.get("/changes/%s/past_assignees"),
+ RestCall.put("/changes/%s/assignee"),
+ RestCall.delete("/changes/%s/assignee"),
+ RestCall.post("/changes/%s/private"),
+ RestCall.post("/changes/%s/private.delete"),
+ RestCall.delete("/changes/%s/private"),
+ RestCall.post("/changes/%s/wip"),
+ RestCall.post("/changes/%s/ready"),
+ RestCall.put("/changes/%s/ignore"),
+ RestCall.put("/changes/%s/unignore"),
+ RestCall.put("/changes/%s/reviewed"),
+ RestCall.put("/changes/%s/unreviewed"),
+ RestCall.get("/changes/%s/messages"),
+ RestCall.put("/changes/%s/message"),
+ RestCall.post("/changes/%s/merge"),
+ RestCall.post("/changes/%s/abandon"),
+ RestCall.post("/changes/%s/move"),
+ RestCall.post("/changes/%s/rebase"),
+ RestCall.post("/changes/%s/restore"),
+ RestCall.post("/changes/%s/revert"),
+ RestCall.get("/changes/%s/pure_revert"),
+ RestCall.post("/changes/%s/submit"),
+ RestCall.get("/changes/%s/submitted_together"),
+ RestCall.post("/changes/%s/index"),
+ RestCall.get("/changes/%s/check"),
+ RestCall.post("/changes/%s/check"),
+ RestCall.get("/changes/%s/reviewers"),
+ RestCall.post("/changes/%s/reviewers"),
+ RestCall.get("/changes/%s/suggest_reviewers"),
+ RestCall.builder(GET, "/changes/%s/revisions")
+ // GET /changes/<change-id>/revisions is not implemented
+ .expectedResponseCode(SC_NOT_FOUND)
+ .build(),
+ RestCall.get("/changes/%s/edit"),
+ RestCall.post("/changes/%s/edit"),
+ RestCall.post("/changes/%s/edit:rebase"),
+ RestCall.get("/changes/%s/edit:message"),
+ RestCall.put("/changes/%s/edit:message"),
+
+ // Publish edit and create a new edit
+ RestCall.post("/changes/%s/edit:publish"),
+ RestCall.put("/changes/%s/edit/a.txt"),
+
+ // Deletion of change edit and change must be tested last
+ RestCall.delete("/changes/%s/edit"),
+ RestCall.delete("/changes/%s"));
+
+ /**
+ * Change REST endpoints to be tested with NoteDb, each URL contains a placeholder for the change
+ * identifier.
+ */
+ private static final ImmutableList<RestCall> CHANGE_ENDPOINTS_NOTEDB =
+ ImmutableList.of(
+ RestCall.post("/changes/%s/hashtags"), RestCall.post("/changes/%s/rebuild.notedb"));
+
+ /**
+ * Reviewer REST endpoints to be tested, each URL contains placeholders for the change identifier
+ * and the reviewer identifier.
+ */
+ private static final ImmutableList<RestCall> REVIEWER_ENDPOINTS =
+ ImmutableList.of(
+ RestCall.get("/changes/%s/reviewers/%s"),
+ RestCall.get("/changes/%s/reviewers/%s/votes"),
+ RestCall.post("/changes/%s/reviewers/%s/delete"),
+ RestCall.delete("/changes/%s/reviewers/%s"));
+
+ /**
+ * Vote REST endpoints to be tested, each URL contains placeholders for the change identifier, the
+ * reviewer identifier and the label identifier.
+ */
+ private static final ImmutableList<RestCall> VOTE_ENDPOINTS =
+ ImmutableList.of(
+ RestCall.post("/changes/%s/reviewers/%s/votes/%s/delete"),
+ RestCall.delete("/changes/%s/reviewers/%s/votes/%s"));
+
+ /**
+ * Revision REST endpoints to be tested, each URL contains placeholders for the change identifier
+ * and the revision identifier.
+ */
+ private static final ImmutableList<RestCall> REVISION_ENDPOINTS =
+ ImmutableList.of(
+ RestCall.get("/changes/%s/revisions/%s/actions"),
+ RestCall.post("/changes/%s/revisions/%s/cherrypick"),
+ RestCall.get("/changes/%s/revisions/%s/commit"),
+ RestCall.get("/changes/%s/revisions/%s/mergeable"),
+ RestCall.get("/changes/%s/revisions/%s/related"),
+ RestCall.get("/changes/%s/revisions/%s/review"),
+ RestCall.post("/changes/%s/revisions/%s/review"),
+ RestCall.get("/changes/%s/revisions/%s/preview_submit"),
+ RestCall.post("/changes/%s/revisions/%s/submit"),
+ RestCall.get("/changes/%s/revisions/%s/submit_type"),
+ RestCall.post("/changes/%s/revisions/%s/test.submit_rule"),
+ RestCall.post("/changes/%s/revisions/%s/test.submit_type"),
+ RestCall.post("/changes/%s/revisions/%s/rebase"),
+ RestCall.get("/changes/%s/revisions/%s/description"),
+ RestCall.put("/changes/%s/revisions/%s/description"),
+ RestCall.get("/changes/%s/revisions/%s/patch"),
+ RestCall.get("/changes/%s/revisions/%s/archive"),
+ RestCall.get("/changes/%s/revisions/%s/mergelist"),
+ RestCall.get("/changes/%s/revisions/%s/reviewers"),
+ RestCall.get("/changes/%s/revisions/%s/drafts"),
+ RestCall.put("/changes/%s/revisions/%s/drafts"),
+ RestCall.get("/changes/%s/revisions/%s/comments"),
+ RestCall.get("/changes/%s/revisions/%s/robotcomments"),
+ RestCall.builder(GET, "/changes/%s/revisions/%s/fixes")
+ // GET /changes/<change>/revisions/<revision>/fixes is not implemented
+ .expectedResponseCode(SC_NOT_FOUND)
+ .build(),
+ RestCall.get("/changes/%s/revisions/%s/files"));
+
+ /**
+ * Revision reviewer REST endpoints to be tested, each URL contains placeholders for the change
+ * identifier, the revision identifier and the reviewer identifier.
+ */
+ private static final ImmutableList<RestCall> REVISION_REVIEWER_ENDPOINTS =
+ ImmutableList.of(
+ RestCall.get("/changes/%s/revisions/%s/reviewers/%s"),
+ RestCall.get("/changes/%s/revisions/%s/reviewers/%s/votes"),
+ RestCall.post("/changes/%s/revisions/%s/reviewers/%s/delete"),
+ RestCall.delete("/changes/%s/revisions/%s/reviewers/%s"));
+
+ /**
+ * Revision vote REST endpoints to be tested, each URL contains placeholders for the change
+ * identifier, the revision identifier, the reviewer identifier and the label identifier.
+ */
+ private static final ImmutableList<RestCall> REVISION_VOTE_ENDPOINTS =
+ ImmutableList.of(
+ RestCall.post("/changes/%s/revisions/%s/reviewers/%s/votes/%s/delete"),
+ RestCall.delete("/changes/%s/revisions/%s/reviewers/%s/votes/%s"));
+
+ /**
+ * Draft comment REST endpoints to be tested, each URL contains placeholders for the change
+ * identifier, the revision identifier and the draft comment identifier.
+ */
+ private static final ImmutableList<RestCall> DRAFT_COMMENT_ENDPOINTS =
+ ImmutableList.of(
+ RestCall.get("/changes/%s/revisions/%s/drafts/%s"),
+ RestCall.put("/changes/%s/revisions/%s/drafts/%s"),
+ RestCall.delete("/changes/%s/revisions/%s/drafts/%s"));
+
+ /**
+ * Comment REST endpoints to be tested, each URL contains placeholders for the change identifier,
+ * the revision identifier and the comment identifier.
+ */
+ private static final ImmutableList<RestCall> COMMENT_ENDPOINTS =
+ ImmutableList.of(
+ RestCall.get("/changes/%s/revisions/%s/comments/%s"),
+ RestCall.delete("/changes/%s/revisions/%s/comments/%s"),
+ RestCall.post("/changes/%s/revisions/%s/comments/%s/delete"));
+
+ /**
+ * Robot comment REST endpoints to be tested, each URL contains placeholders for the change
+ * identifier, the revision identifier and the robot comment identifier.
+ */
+ private static final ImmutableList<RestCall> ROBOT_COMMENT_ENDPOINTS =
+ ImmutableList.of(RestCall.get("/changes/%s/revisions/%s/robotcomments/%s"));
+
+ /**
+ * Fix REST endpoints to be tested, each URL contains placeholders for the change identifier, the
+ * revision identifier and the fix identifier.
+ */
+ private static final ImmutableList<RestCall> FIX_ENDPOINTS =
+ ImmutableList.of(RestCall.post("/changes/%s/revisions/%s/fixes/%s/apply"));
+
+ /**
+ * Revision file REST endpoints to be tested, each URL contains placeholders for the change
+ * identifier, the revision identifier and the file identifier.
+ */
+ private static final ImmutableList<RestCall> REVISION_FILE_ENDPOINTS =
+ ImmutableList.of(
+ RestCall.put("/changes/%s/revisions/%s/files/%s/reviewed"),
+ RestCall.delete("/changes/%s/revisions/%s/files/%s/reviewed"),
+ RestCall.get("/changes/%s/revisions/%s/files/%s/content"),
+ RestCall.get("/changes/%s/revisions/%s/files/%s/download"),
+ RestCall.get("/changes/%s/revisions/%s/files/%s/diff"),
+ RestCall.get("/changes/%s/revisions/%s/files/%s/blame"));
+
+ /**
+ * Change message REST endpoints to be tested, each URL contains placeholders for the change
+ * identifier and the change message identifier.
+ */
+ private static final ImmutableList<RestCall> CHANGE_MESSAGE_ENDPOINTS =
+ ImmutableList.of(RestCall.get("/changes/%s/messages/%s"));
+
+ /**
+ * Change edit REST endpoints that create an edit to be tested, each URL contains placeholders for
+ * the change identifier and the change edit identifier.
+ */
+ private static final ImmutableList<RestCall> CHANGE_EDIT_CREATE_ENDPOINTS =
+ ImmutableList.of(
+ // Create change edit by editing an existing file.
+ RestCall.put("/changes/%s/edit/%s"),
+
+ // Create change edit by deleting an existing file.
+ RestCall.delete("/changes/%s/edit/%s"));
+
+ /**
+ * Change edit REST endpoints to be tested, each URL contains placeholders for the change
+ * identifier and the change edit identifier.
+ */
+ private static final ImmutableList<RestCall> CHANGE_EDIT_ENDPOINTS =
+ ImmutableList.of(
+ // Calls on existing change edit.
+ RestCall.get("/changes/%s/edit/%s"),
+ RestCall.put("/changes/%s/edit/%s"),
+ RestCall.get("/changes/%s/edit/%s/meta"),
+
+ // Delete content of a file in an existing change edit.
+ RestCall.delete("/changes/%s/edit/%s"));
+
+ private static final String FILENAME = "test.txt";
+
+ @Test
+ public void changeEndpoints() throws Exception {
+ String changeId = createChange().getChangeId();
+ gApi.changes().id(changeId).edit().create();
+ execute(CHANGE_ENDPOINTS, changeId);
+ }
+
+ @Test
+ public void changeEndpointsNoteDb() throws Exception {
+ assume().that(notesMigration.readChanges()).isTrue();
+
+ String changeId = createChange().getChangeId();
+ execute(CHANGE_ENDPOINTS_NOTEDB, changeId);
+ }
+
+ @Test
+ public void reviewerEndpoints() throws Exception {
+ String changeId = createChange().getChangeId();
+
+ AddReviewerInput addReviewerInput = new AddReviewerInput();
+ addReviewerInput.reviewer = user.email;
+
+ execute(
+ REVIEWER_ENDPOINTS,
+ () -> gApi.changes().id(changeId).addReviewer(addReviewerInput),
+ changeId,
+ addReviewerInput.reviewer);
+ }
+
+ @Test
+ public void voteEndpoints() throws Exception {
+ String changeId = createChange().getChangeId();
+
+ execute(
+ VOTE_ENDPOINTS,
+ () -> gApi.changes().id(changeId).current().review(ReviewInput.approve()),
+ changeId,
+ admin.email,
+ "Code-Review");
+ }
+
+ @Test
+ public void revisionEndpoints() throws Exception {
+ String changeId = createChange().getChangeId();
+ execute(REVISION_ENDPOINTS, changeId, "current");
+ }
+
+ @Test
+ public void revisionReviewerEndpoints() throws Exception {
+ String changeId = createChange().getChangeId();
+
+ AddReviewerInput addReviewerInput = new AddReviewerInput();
+ addReviewerInput.reviewer = user.email;
+
+ execute(
+ REVISION_REVIEWER_ENDPOINTS,
+ () -> gApi.changes().id(changeId).addReviewer(addReviewerInput),
+ changeId,
+ "current",
+ addReviewerInput.reviewer);
+ }
+
+ @Test
+ public void revisionVoteEndpoints() throws Exception {
+ String changeId = createChange().getChangeId();
+
+ execute(
+ REVISION_VOTE_ENDPOINTS,
+ () -> gApi.changes().id(changeId).current().review(ReviewInput.approve()),
+ changeId,
+ "current",
+ admin.email,
+ "Code-Review");
+ }
+
+ @Test
+ public void draftCommentEndpoints() throws Exception {
+ String changeId = createChange().getChangeId();
+
+ for (RestCall restCall : DRAFT_COMMENT_ENDPOINTS) {
+ DraftInput draftInput = new DraftInput();
+ draftInput.path = Patch.COMMIT_MSG;
+ draftInput.side = Side.REVISION;
+ draftInput.line = 1;
+ draftInput.message = "draft comment";
+ CommentInfo draftInfo = gApi.changes().id(changeId).current().createDraft(draftInput).get();
+
+ execute(restCall, changeId, "current", draftInfo.id);
+ }
+ }
+
+ @Test
+ public void commentEndpoints() throws Exception {
+ String changeId = createChange().getChangeId();
+
+ for (RestCall restCall : COMMENT_ENDPOINTS) {
+ DraftInput draftInput = new DraftInput();
+ draftInput.path = Patch.COMMIT_MSG;
+ draftInput.side = Side.REVISION;
+ draftInput.line = 1;
+ draftInput.message = "draft comment";
+ CommentInfo commentInfo = gApi.changes().id(changeId).current().createDraft(draftInput).get();
+
+ ReviewInput reviewInput = new ReviewInput();
+ reviewInput.drafts = DraftHandling.PUBLISH;
+ gApi.changes().id(changeId).current().review(reviewInput);
+
+ execute(restCall, changeId, "current", commentInfo.id);
+ }
+ }
+
+ @Test
+ public void robotCommentEndpoints() throws Exception {
+ assume().that(notesMigration.readChanges()).isTrue();
+
+ String changeId = createChange().getChangeId();
+
+ RobotCommentInput robotCommentInput = new RobotCommentInput();
+ robotCommentInput.robotId = "happyRobot";
+ robotCommentInput.robotRunId = "1";
+ robotCommentInput.line = 1;
+ robotCommentInput.message = "nit: trailing whitespace";
+ robotCommentInput.path = Patch.COMMIT_MSG;
+
+ ReviewInput reviewInput = new ReviewInput();
+ reviewInput.robotComments =
+ Collections.singletonMap(robotCommentInput.path, ImmutableList.of(robotCommentInput));
+ reviewInput.message = "robot comment test";
+ gApi.changes().id(changeId).current().review(reviewInput);
+
+ List<RobotCommentInfo> robotCommentInfos =
+ gApi.changes().id(changeId).current().robotCommentsAsList();
+ RobotCommentInfo robotCommentInfo = Iterables.getOnlyElement(robotCommentInfos);
+
+ execute(ROBOT_COMMENT_ENDPOINTS, changeId, "current", robotCommentInfo.id);
+ }
+
+ @Test
+ public void fixEndpoints() throws Exception {
+ assume().that(notesMigration.readChanges()).isTrue();
+
+ String changeId = createChange("Subject", FILENAME, "content").getChangeId();
+
+ RobotCommentInput robotCommentInput = new RobotCommentInput();
+ robotCommentInput.robotId = "happyRobot";
+ robotCommentInput.robotRunId = "1";
+ robotCommentInput.line = 1;
+ robotCommentInput.message = "nit: trailing whitespace";
+ robotCommentInput.path = FILENAME;
+
+ FixReplacementInfo fixReplacementInfo = new FixReplacementInfo();
+ fixReplacementInfo.path = FILENAME;
+ fixReplacementInfo.replacement = "some replacement code";
+ fixReplacementInfo.range = createRange(1, 1, 1, 2);
+
+ FixSuggestionInfo fixSuggestionInfo = new FixSuggestionInfo();
+ fixSuggestionInfo.fixId = "An ID which must be overwritten.";
+ fixSuggestionInfo.description = "A description for a suggested fix.";
+ fixSuggestionInfo.replacements = ImmutableList.of(fixReplacementInfo);
+
+ robotCommentInput.fixSuggestions = ImmutableList.of(fixSuggestionInfo);
+
+ ReviewInput reviewInput = new ReviewInput();
+ reviewInput.robotComments =
+ Collections.singletonMap(robotCommentInput.path, ImmutableList.of(robotCommentInput));
+ reviewInput.message = "robot comment test";
+ gApi.changes().id(changeId).current().review(reviewInput);
+
+ List<RobotCommentInfo> robotCommentInfos =
+ gApi.changes().id(changeId).current().robotCommentsAsList();
+
+ List<String> fixIds = getFixIds(robotCommentInfos);
+ String fixId = Iterables.getOnlyElement(fixIds);
+
+ execute(FIX_ENDPOINTS, changeId, "current", fixId);
+ }
+
+ @Test
+ public void revisionFileEndpoints() throws Exception {
+ String changeId = createChange("Subject", FILENAME, "content").getChangeId();
+ execute(REVISION_FILE_ENDPOINTS, changeId, "current", FILENAME);
+ }
+
+ @Test
+ public void changeMessageEndpoints() throws Exception {
+ String changeId = createChange().getChangeId();
+
+ // A change message is created on change creation.
+ String changeMessageId = Iterables.getOnlyElement(gApi.changes().id(changeId).messages()).id;
+
+ execute(CHANGE_MESSAGE_ENDPOINTS, changeId, changeMessageId);
+ }
+
+ @Test
+ public void changeEditCreateEndpoints() throws Exception {
+ String changeId = createChange("Subject", FILENAME, "content").getChangeId();
+
+ // Each of the REST calls creates the change edit newly.
+ execute(
+ CHANGE_EDIT_CREATE_ENDPOINTS,
+ () -> adminRestSession.delete("/changes/" + changeId + "/edit"),
+ changeId,
+ FILENAME);
+ }
+
+ @Test
+ public void changeEditEndpoints() throws Exception {
+ String changeId = createChange("Subject", FILENAME, "content").getChangeId();
+ gApi.changes().id(changeId).edit().create();
+ execute(CHANGE_EDIT_ENDPOINTS, changeId, FILENAME);
+ }
+
+ private static Comment.Range createRange(
+ int startLine, int startCharacter, int endLine, int endCharacter) {
+ Comment.Range range = new Comment.Range();
+ range.startLine = startLine;
+ range.startCharacter = startCharacter;
+ range.endLine = endLine;
+ range.endCharacter = endCharacter;
+ return range;
+ }
+
+ private static List<String> getFixIds(List<RobotCommentInfo> robotComments) {
+ assertThatList(robotComments).isNotNull();
+ return robotComments.stream()
+ .map(robotCommentInfo -> robotCommentInfo.fixSuggestions)
+ .filter(Objects::nonNull)
+ .flatMap(List::stream)
+ .map(fixSuggestionInfo -> fixSuggestionInfo.fixId)
+ .collect(toList());
+ }
+}