Merge changes I343425ab,Ieaa18566

* changes:
  Do not allow creations of comments with invalid inReplyTo
  Add robot comments creation and retrieval to the test api
This commit is contained in:
Gal Paikin
2020-09-15 17:34:15 +00:00
committed by Gerrit Code Review
27 changed files with 1499 additions and 124 deletions

View File

@@ -14,9 +14,11 @@
package com.google.gerrit.acceptance.api.revision;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.MoreCollectors.onlyElement;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.PushOneCommit.SUBJECT;
import static com.google.gerrit.entities.Patch.COMMIT_MSG;
import static com.google.gerrit.entities.Patch.PATCHSET_LEVEL;
import static com.google.gerrit.extensions.client.ListChangesOption.MESSAGES;
import static com.google.gerrit.extensions.common.testing.DiffInfoSubject.assertThat;
@@ -32,8 +34,11 @@ import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.UseClockStep;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.change.ChangeOperations;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.extensions.api.changes.PublishChangeEditInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.ReviewInput.RobotCommentInput;
import com.google.gerrit.extensions.client.Comment;
import com.google.gerrit.extensions.client.Side;
@@ -67,6 +72,7 @@ import org.junit.Test;
public class RobotCommentsIT extends AbstractDaemonTest {
@Inject private TestCommentHelper testCommentHelper;
@Inject private ChangeOperations changeOperations;
private static final String PLAIN_TEXT_CONTENT_TYPE = "text/plain";
private static final String GERRIT_COMMIT_MESSAGE_TYPE = "text/x-gerrit-commit-message";
@@ -319,6 +325,58 @@ public class RobotCommentsIT extends AbstractDaemonTest {
assertThat(ex.getMessage()).contains("file path must not be " + PATCHSET_LEVEL);
}
@Test
public void robotCommentInvalidInReplyTo() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
RobotCommentInput input = TestCommentHelper.createRobotCommentInput(PATCHSET_LEVEL);
input.inReplyTo = "invalid";
BadRequestException ex =
assertThrows(
BadRequestException.class, () -> testCommentHelper.addRobotComment(changeId, input));
assertThat(ex.getMessage()).contains("inReplyTo");
}
@Test
public void canCreateRobotCommentWithRobotCommentAsParent() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String parentRobotCommentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().create();
ReviewInput.RobotCommentInput robotCommentInput =
TestCommentHelper.createRobotCommentInputWithMandatoryFields(COMMIT_MSG);
robotCommentInput.message = "comment reply";
robotCommentInput.inReplyTo = parentRobotCommentUuid;
testCommentHelper.addRobotComment(changeId, robotCommentInput);
RobotCommentInfo resultComment =
Iterables.getOnlyElement(
gApi.changes().id(changeId.get()).current().robotCommentsAsList().stream()
.filter(c -> c.message.equals("comment reply"))
.collect(toImmutableSet()));
assertThat(resultComment.inReplyTo).isEqualTo(parentRobotCommentUuid);
}
@Test
public void canCreateRobotCommentWithHumanCommentAsParent() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String changeIdString = changeOperations.change(changeId).get().changeId();
String parentCommentUuid =
changeOperations.change(changeId).currentPatchset().newComment().create();
ReviewInput.RobotCommentInput robotCommentInput =
TestCommentHelper.createRobotCommentInputWithMandatoryFields(COMMIT_MSG);
robotCommentInput.message = "comment reply";
robotCommentInput.inReplyTo = parentCommentUuid;
testCommentHelper.addRobotComment(changeIdString, robotCommentInput);
RobotCommentInfo resultComment =
Iterables.getOnlyElement(
gApi.changes().id(changeIdString).current().robotCommentsAsList().stream()
.filter(c -> c.message.equals("comment reply"))
.collect(toImmutableSet()));
assertThat(resultComment.inReplyTo).isEqualTo(parentCommentUuid);
}
@Test
public void hugeRobotCommentIsRejected() {
int defaultSizeLimit = 1 << 20;

View File

@@ -14,10 +14,12 @@
package com.google.gerrit.acceptance.server.change;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.gerrit.acceptance.PushOneCommit.FILE_NAME;
import static com.google.gerrit.acceptance.PushOneCommit.SUBJECT;
import static com.google.gerrit.entities.Patch.COMMIT_MSG;
import static com.google.gerrit.entities.Patch.PATCHSET_LEVEL;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.google.gerrit.truth.MapSubject.assertThatMap;
@@ -51,7 +53,6 @@ import com.google.gerrit.extensions.client.Comment;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.RobotCommentInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.IdString;
@@ -657,6 +658,34 @@ public class CommentsIT extends AbstractDaemonTest {
}
}
@Test
public void putDraft_humanInReplyTo() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String parentCommentUuid =
changeOperations.change(changeId).currentPatchset().newComment().create();
DraftInput draft = newDraft(COMMIT_MSG, Side.REVISION, 0, "foo");
draft.inReplyTo = parentCommentUuid;
String createdDraftUuid = addDraft(changeId, draft).id;
TestHumanComment actual =
changeOperations.change(changeId).draftComment(createdDraftUuid).get();
assertThat(actual.parentUuid()).hasValue(parentCommentUuid);
}
@Test
public void putDraft_robotInReplyTo() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String parentRobotCommentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().create();
DraftInput draft = newDraft(COMMIT_MSG, Side.REVISION, 0, "foo");
draft.inReplyTo = parentRobotCommentUuid;
String createdDraftUuid = addDraft(changeId, draft).id;
TestHumanComment actual =
changeOperations.change(changeId).draftComment(createdDraftUuid).get();
assertThat(actual.parentUuid()).hasValue(parentRobotCommentUuid);
}
@Test
public void putDraft_idMismatch() throws Exception {
String file = "file";
@@ -701,6 +730,16 @@ public class CommentsIT extends AbstractDaemonTest {
.contains("range endLine must be on the same line as the comment");
}
@Test
public void putDraft_invalidInReplyTo() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
DraftInput draft = newDraft(COMMIT_MSG, Side.REVISION, 0, "foo");
draft.inReplyTo = "invalid";
BadRequestException exception =
assertThrows(BadRequestException.class, () -> addDraft(changeId, draft));
assertThat(exception.getMessage()).contains(String.format("%s not found", draft.inReplyTo));
}
@Test
public void putDraft_updatePath() throws Exception {
PushOneCommit.Result r = createChange();
@@ -715,22 +754,62 @@ public class CommentsIT extends AbstractDaemonTest {
}
@Test
public void putDraft_updateInReplyToAndTag() throws Exception {
PushOneCommit.Result r = createChange();
String changeId = r.getChangeId();
String revId = r.getCommit().getName();
DraftInput draftInput1 = newDraft(FILE_NAME, Side.REVISION, 0, "foo");
CommentInfo commentInfo = addDraft(changeId, revId, draftInput1);
DraftInput draftInput2 = newDraft(FILE_NAME, Side.REVISION, 0, "bar");
String inReplyTo = "in_reply_to";
public void putDraft_updateInvalidInReplyTo() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
DraftInput originalDraftInput = newDraft(FILE_NAME, Side.REVISION, 0, "foo");
CommentInfo originalDraft = addDraft(changeId, originalDraftInput);
DraftInput updatedDraftInput = newDraft(FILE_NAME, Side.REVISION, 0, "bar");
updatedDraftInput.inReplyTo = "invalid";
BadRequestException exception =
assertThrows(
BadRequestException.class,
() -> updateDraft(changeId, updatedDraftInput, originalDraft.id));
assertThat(exception.getMessage()).contains(String.format("Invalid inReplyTo"));
}
@Test
public void putDraft_updateHumanInReplyTo() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String parentCommentUuid =
changeOperations.change(changeId).currentPatchset().newComment().create();
DraftInput originalDraftInput = newDraft(FILE_NAME, Side.REVISION, 0, "foo");
CommentInfo originalDraft = addDraft(changeId, originalDraftInput);
DraftInput updateDraftInput = newDraft(FILE_NAME, Side.REVISION, 0, "bar");
updateDraftInput.inReplyTo = parentCommentUuid;
updateDraft(changeId, updateDraftInput, originalDraft.id);
assertThat(changeOperations.change(changeId).draftComment(originalDraft.id).get().parentUuid())
.hasValue(parentCommentUuid);
}
@Test
public void putDraft_updateRobotInReplyTo() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String parentRobotCommentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().create();
DraftInput originalDraftInput = newDraft(FILE_NAME, Side.REVISION, 0, "foo");
CommentInfo originalDraft = addDraft(changeId, originalDraftInput);
DraftInput updateDraftInput = newDraft(FILE_NAME, Side.REVISION, 0, "bar");
updateDraftInput.inReplyTo = parentRobotCommentUuid;
updateDraft(changeId, updateDraftInput, originalDraft.id);
assertThat(changeOperations.change(changeId).draftComment(originalDraft.id).get().parentUuid())
.hasValue(parentRobotCommentUuid);
}
@Test
public void putDraft_updateTag() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
DraftInput originalDraftInput = newDraft(FILE_NAME, Side.REVISION, 0, "foo");
CommentInfo originalDraft = addDraft(changeId, originalDraftInput);
DraftInput updateDraftInput = newDraft(FILE_NAME, Side.REVISION, 0, "bar");
String tag = "täg";
draftInput2.inReplyTo = inReplyTo;
draftInput2.tag = tag;
updateDraft(changeId, revId, draftInput2, commentInfo.id);
com.google.gerrit.entities.Comment comment =
Iterables.getOnlyElement(commentsUtil.draftByChange(r.getChange().notes()));
assertThat(comment.parentUuid).isEqualTo(inReplyTo);
assertThat(comment.tag).isEqualTo(tag);
updateDraftInput.tag = tag;
updateDraft(changeId, updateDraftInput, originalDraft.id);
assertThat(changeOperations.change(changeId).draftComment(originalDraft.id).get().tag())
.hasValue(tag);
}
@Test
@@ -1474,26 +1553,73 @@ public class CommentsIT extends AbstractDaemonTest {
@Test
public void canCreateHumanCommentWithRobotCommentAsParentAndUnsetUnresolved() throws Exception {
PushOneCommit.Result result = createChange();
String changeId = result.getChangeId();
String ps1 = result.getCommit().name();
Change.Id changeId = changeOperations.newChange().create();
String parentRobotCommentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().create();
testCommentHelper.addRobotComment(
result.getChangeId(),
TestCommentHelper.createRobotCommentInputWithMandatoryFields(FILE_NAME));
RobotCommentInfo robotCommentInfo =
Iterables.getOnlyElement(gApi.changes().id(changeId).current().robotCommentsAsList());
CommentInput createdCommentInput = newComment(COMMIT_MSG, "comment reply");
createdCommentInput.inReplyTo = parentRobotCommentUuid;
createdCommentInput.unresolved = null;
addComments(changeId, createdCommentInput);
CommentInput comment = newComment(FILE_NAME, "comment 1 reply");
comment.inReplyTo = robotCommentInfo.id;
comment.unresolved = null;
addComments(changeId, ps1, comment);
CommentInfo resultNewComment =
Iterables.getOnlyElement(
getPublishedCommentsAsList(changeId).stream()
.filter(c -> c.message.equals("comment reply"))
.collect(toImmutableSet()));
CommentInfo resultComment = Iterables.getOnlyElement(getPublishedCommentsAsList(changeId));
assertThat(resultComment.inReplyTo).isEqualTo(robotCommentInfo.id);
assertThat(resultNewComment.inReplyTo).isEqualTo(parentRobotCommentUuid);
// Default unresolved is false.
assertThat(resultComment.unresolved).isFalse();
assertThat(resultNewComment.unresolved).isFalse();
}
@Test
public void canCreateHumanCommentWithHumanCommentAsParent() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String parentCommentUuid =
changeOperations.change(changeId).currentPatchset().newComment().create();
CommentInput createdCommentInput = newComment(COMMIT_MSG, "comment reply");
createdCommentInput.inReplyTo = parentCommentUuid;
addComments(changeId, createdCommentInput);
CommentInfo resultNewComment =
Iterables.getOnlyElement(
getPublishedCommentsAsList(changeId).stream()
.filter(c -> c.message.equals("comment reply"))
.collect(toImmutableSet()));
assertThat(resultNewComment.inReplyTo).isEqualTo(parentCommentUuid);
}
@Test
public void canCreateHumanCommentWithRobotCommentAsParent() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String parentRobotCommentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().create();
CommentInput createdCommentInput = newComment(COMMIT_MSG, "comment reply");
createdCommentInput.inReplyTo = parentRobotCommentUuid;
addComments(changeId, createdCommentInput);
CommentInfo resultNewComment =
Iterables.getOnlyElement(
getPublishedCommentsAsList(changeId).stream()
.filter(c -> c.message.equals("comment reply"))
.collect(toImmutableSet()));
assertThat(resultNewComment.inReplyTo).isEqualTo(parentRobotCommentUuid);
}
@Test
public void cannotCreateCommentWithInvalidInReplyTo() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
CommentInput comment = newComment(COMMIT_MSG, "comment 1 reply");
comment.inReplyTo = "invalid";
BadRequestException exception =
assertThrows(BadRequestException.class, () -> addComments(changeId, comment));
assertThat(exception.getMessage()).contains(String.format("%s not found", comment.inReplyTo));
}
private List<CommentInfo> getRevisionComments(String changeId, String revId) throws Exception {
@@ -1510,6 +1636,12 @@ public class CommentsIT extends AbstractDaemonTest {
return comment;
}
private void addComments(Change.Id changeId, CommentInput... commentInputs) throws Exception {
ReviewInput input = new ReviewInput();
input.comments = Arrays.stream(commentInputs).collect(groupingBy(c -> c.path));
gApi.changes().id(changeId.get()).current().review(input);
}
private void addComments(String changeId, String revision, CommentInput... commentInputs)
throws Exception {
ReviewInput input = new ReviewInput();
@@ -1517,6 +1649,12 @@ public class CommentsIT extends AbstractDaemonTest {
gApi.changes().id(changeId).revision(revision).review(input);
}
private void addComments(String changeId, CommentInput... commentInputs) throws Exception {
ReviewInput input = new ReviewInput();
input.comments = Arrays.stream(commentInputs).collect(groupingBy(c -> c.path));
gApi.changes().id(changeId).current().review(input);
}
/**
* All the commits, which contain the target comment before, should still contain the comment with
* the updated message. All the other metas of the commits should be exactly the same.
@@ -1610,11 +1748,31 @@ public class CommentsIT extends AbstractDaemonTest {
return gApi.changes().id(changeId).revision(revId).createDraft(in).get();
}
private CommentInfo addDraft(Change.Id changeId, String revId, DraftInput in) throws Exception {
return gApi.changes().id(changeId.get()).revision(revId).createDraft(in).get();
}
private CommentInfo addDraft(String changeId, DraftInput in) throws Exception {
return gApi.changes().id(changeId).current().createDraft(in).get();
}
private CommentInfo addDraft(Change.Id changeId, DraftInput in) throws Exception {
return gApi.changes().id(changeId.get()).current().createDraft(in).get();
}
private void updateDraft(String changeId, String revId, DraftInput in, String uuid)
throws Exception {
gApi.changes().id(changeId).revision(revId).draft(uuid).update(in);
}
private void updateDraft(String changeId, DraftInput in, String uuid) throws Exception {
gApi.changes().id(changeId).current().draft(uuid).update(in);
}
private void updateDraft(Change.Id changeId, DraftInput in, String uuid) throws Exception {
gApi.changes().id(changeId.get()).current().draft(uuid).update(in);
}
private void deleteDraft(String changeId, String revId, String uuid) throws Exception {
gApi.changes().id(changeId).revision(revId).draft(uuid).delete();
}
@@ -1633,6 +1791,10 @@ public class CommentsIT extends AbstractDaemonTest {
return gApi.changes().id(changeId).commentsAsList();
}
private List<CommentInfo> getPublishedCommentsAsList(Change.Id changeId) throws Exception {
return gApi.changes().id(changeId.get()).commentsAsList();
}
private Map<String, List<CommentInfo>> getDraftComments(String changeId, String revId)
throws Exception {
return gApi.changes().id(changeId).revision(revId).drafts();

View File

@@ -1174,6 +1174,39 @@ public class ChangeOperationsImplTest extends AbstractDaemonTest {
assertThat(comment.parentUuid()).value().isEqualTo(parentCommentUuid);
}
@Test
public void tagOfPublishedCommentCanBeRetrieved() {
Change.Id changeId = changeOperations.newChange().create();
String childCommentUuid =
changeOperations.change(changeId).currentPatchset().newComment().tag("tag").create();
TestHumanComment comment = changeOperations.change(changeId).comment(childCommentUuid).get();
assertThat(comment.tag()).value().isEqualTo("tag");
}
@Test
public void unresolvedOfUnresolvedPublishedCommentCanBeRetrieved() {
Change.Id changeId = changeOperations.newChange().create();
String childCommentUuid =
changeOperations.change(changeId).currentPatchset().newComment().unresolved().create();
TestHumanComment comment = changeOperations.change(changeId).comment(childCommentUuid).get();
assertThat(comment.unresolved()).isTrue();
}
@Test
public void unresolvedOfResolvedPublishedCommentCanBeRetrieved() {
Change.Id changeId = changeOperations.newChange().create();
String childCommentUuid =
changeOperations.change(changeId).currentPatchset().newComment().resolved().create();
TestHumanComment comment = changeOperations.change(changeId).comment(childCommentUuid).get();
assertThat(comment.unresolved()).isFalse();
}
@Test
public void draftCommentCanBeRetrieved() {
Change.Id changeId = changeOperations.newChange().create();
@@ -1212,6 +1245,36 @@ public class ChangeOperationsImplTest extends AbstractDaemonTest {
assertThat(comment.parentUuid()).value().isEqualTo(parentCommentUuid);
}
@Test
public void robotCommentCanBeRetrieved() {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().create();
TestRobotComment comment = changeOperations.change(changeId).robotComment(commentUuid).get();
assertThat(comment.uuid()).isEqualTo(commentUuid);
}
@Test
public void parentUuidOfRobotCommentCanBeRetrieved() {
Change.Id changeId = changeOperations.newChange().create();
String parentCommentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().create();
String childCommentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.parentUuid(parentCommentUuid)
.create();
TestRobotComment comment =
changeOperations.change(changeId).robotComment(childCommentUuid).get();
assertThat(comment.parentUuid()).value().isEqualTo(parentCommentUuid);
}
private ChangeInfo getChangeFromServer(Change.Id changeId) throws RestApiException {
return gApi.changes().id(changeId.get()).get();
}

View File

@@ -16,6 +16,8 @@ package com.google.gerrit.acceptance.testsuite.change;
import static com.google.gerrit.extensions.common.testing.CommentInfoSubject.assertThat;
import static com.google.gerrit.extensions.common.testing.CommentInfoSubject.assertThatList;
import static com.google.gerrit.extensions.common.testing.RobotCommentInfoSubject.assertThat;
import static com.google.gerrit.extensions.common.testing.RobotCommentInfoSubject.assertThatList;
import com.google.common.truth.Correspondence;
import com.google.gerrit.acceptance.AbstractDaemonTest;
@@ -27,6 +29,7 @@ import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.RobotCommentInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.truth.NullAwareCorrespondence;
import com.google.inject.Inject;
@@ -44,7 +47,6 @@ public class PatchsetOperationsImplTest extends AbstractDaemonTest {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid = changeOperations.change(changeId).currentPatchset().newComment().create();
List<CommentInfo> comments = getCommentsFromServer(changeId);
assertThatList(comments).comparingElementsUsing(hasUuid()).containsExactly(commentUuid);
}
@@ -643,10 +645,393 @@ public class PatchsetOperationsImplTest extends AbstractDaemonTest {
assertThatList(comments).isEmpty();
}
@Test
public void robotCommentCanBeCreatedWithoutSpecifyingAnyParameters() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().create();
List<RobotCommentInfo> robotComments = getRobotCommentsFromServerFromCurrentPatchset(changeId);
assertThatList(robotComments).comparingElementsUsing(hasUuid()).containsExactly(commentUuid);
}
@Test
public void robotCommentCanBeCreatedOnOlderPatchset() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
PatchSet.Id previousPatchsetId =
changeOperations.change(changeId).currentPatchset().get().patchsetId();
changeOperations.change(changeId).newPatchset().create();
String commentUuid =
changeOperations.change(changeId).patchset(previousPatchsetId).newRobotComment().create();
CommentInfo comment = getRobotCommentFromServer(previousPatchsetId, commentUuid);
assertThat(comment).uuid().isEqualTo(commentUuid);
}
@Test
public void robotCommentIsCreatedWithSpecifiedMessage() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.message("Test comment message")
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).message().isEqualTo("Test comment message");
}
@Test
public void robotCommentCanBeCreatedWithEmptyMessage() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().noMessage().create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).message().isNull();
}
@Test
public void patchsetLevelRobotCommentCanBeCreated() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.onPatchsetLevel()
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).path().isEqualTo(Patch.PATCHSET_LEVEL);
}
@Test
public void fileRobotCommentCanBeCreated() throws Exception {
Change.Id changeId = changeOperations.newChange().file("file1").content("Line 1").create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.onFileLevelOf("file1")
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).path().isEqualTo("file1");
assertThat(comment).line().isNull();
assertThat(comment).range().isNull();
}
@Test
public void lineRobotCommentCanBeCreated() throws Exception {
Change.Id changeId =
changeOperations
.newChange()
.file("file1")
.content("Line 1\nLine 2\nLine 3\nLine 4\n")
.create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.onLine(3)
.ofFile("file1")
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).line().isEqualTo(3);
assertThat(comment).range().isNull();
}
@Test
public void rangeRobotCommentCanBeCreated() throws Exception {
Change.Id changeId =
changeOperations
.newChange()
.file("file1")
.content("Line 1\nLine 2\nLine 3\nLine 4\n")
.create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.fromLine(2)
.charOffset(4)
.toLine(3)
.charOffset(5)
.ofFile("file1")
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).range().startLine().isEqualTo(2);
assertThat(comment).range().startCharacter().isEqualTo(4);
assertThat(comment).range().endLine().isEqualTo(3);
assertThat(comment).range().endCharacter().isEqualTo(5);
// Line is automatically filled from specified range. It's the end line.
assertThat(comment).line().isEqualTo(3);
}
@Test
public void robotCommentCanBeCreatedOnPatchsetCommit() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.onPatchsetCommit()
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
// Null is often used instead of Side.REVISION as Side.REVISION is the default.
assertThat(comment).side().isAnyOf(Side.REVISION, null);
assertThat(comment).parent().isNull();
}
@Test
public void robotCommentCanBeCreatedOnParentCommit() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.onParentCommit()
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).side().isEqualTo(Side.PARENT);
assertThat(comment).parent().isEqualTo(1);
}
@Test
public void robotCommentCanBeCreatedOnSecondParentCommit() throws Exception {
Change.Id parent1ChangeId = changeOperations.newChange().create();
Change.Id parent2ChangeId = changeOperations.newChange().create();
Change.Id changeId =
changeOperations
.newChange()
.mergeOf()
.change(parent1ChangeId)
.and()
.change(parent2ChangeId)
.create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.onSecondParentCommit()
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).side().isEqualTo(Side.PARENT);
assertThat(comment).parent().isEqualTo(2);
}
@Test
public void robotCommentCanBeCreatedOnNonExistingSecondParentCommit() throws Exception {
Change.Id parentChangeId = changeOperations.newChange().create();
Change.Id changeId = changeOperations.newChange().childOf().change(parentChangeId).create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.onSecondParentCommit()
.create();
// We want to be able to create such invalid robot comments for testing purposes (e.g. testing
// error handling or resilience of an endpoint) and hence we need to allow such invalid robot
// comments in the test API.
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).side().isEqualTo(Side.PARENT);
assertThat(comment).parent().isEqualTo(2);
}
@Test
public void robotCommentCanBeCreatedOnAutoMergeCommit() throws Exception {
Change.Id parent1ChangeId = changeOperations.newChange().create();
Change.Id parent2ChangeId = changeOperations.newChange().create();
Change.Id changeId =
changeOperations
.newChange()
.mergeOf()
.change(parent1ChangeId)
.and()
.change(parent2ChangeId)
.create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.onAutoMergeCommit()
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).side().isEqualTo(Side.PARENT);
assertThat(comment).parent().isNull();
}
@Test
public void robotCommentCanBeCreatedAsResolved() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().resolved().create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).unresolved().isFalse();
}
@Test
public void robotCommentCanBeCreatedAsUnresolved() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().unresolved().create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).unresolved().isTrue();
}
@Test
public void replyToRobotCommentCanBeCreated() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String parentCommentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.parentUuid(parentCommentUuid)
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).inReplyTo().isEqualTo(parentCommentUuid);
}
@Test
public void tagCanBeAttachedToARobotComment() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.tag("my special tag")
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).tag().isEqualTo("my special tag");
}
@Test
public void robotCommentIsCreatedWithSpecifiedAuthor() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
Account.Id accountId = accountOperations.newAccount().create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.author(accountId)
.create();
CommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).author().id().isEqualTo(accountId.get());
}
@Test
public void robotCommentIsCreatedWithRobotId() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.robotId("robot-id")
.create();
RobotCommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).robotId().isEqualTo("robot-id");
}
@Test
public void robotCommentIsCreatedWithRobotRunId() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.robotId("robot-run-id")
.create();
RobotCommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).robotId().isEqualTo("robot-run-id");
}
@Test
public void robotCommentIsCreatedWithUrl() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations.change(changeId).currentPatchset().newRobotComment().url("url").create();
RobotCommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).url().isEqualTo("url");
}
@Test
public void robotCommentIsCreatedWithProperty() throws Exception {
Change.Id changeId = changeOperations.newChange().create();
String commentUuid =
changeOperations
.change(changeId)
.currentPatchset()
.newRobotComment()
.addProperty("key", "value")
.create();
RobotCommentInfo comment = getRobotCommentFromServerInCurrentPatchset(changeId, commentUuid);
assertThat(comment).properties().containsExactly("key", "value");
}
private List<CommentInfo> getCommentsFromServer(Change.Id changeId) throws RestApiException {
return gApi.changes().id(changeId.get()).commentsAsList();
}
private List<RobotCommentInfo> getRobotCommentsFromServerFromCurrentPatchset(Change.Id changeId)
throws RestApiException {
return gApi.changes().id(changeId.get()).current().robotCommentsAsList();
}
private List<CommentInfo> getDraftCommentsFromServer(Change.Id changeId) throws RestApiException {
return gApi.changes().id(changeId.get()).draftsAsList();
}
@@ -662,6 +1047,33 @@ public class PatchsetOperationsImplTest extends AbstractDaemonTest {
String.format("Comment %s not found on change %d", uuid, changeId.get())));
}
private RobotCommentInfo getRobotCommentFromServerInCurrentPatchset(
Change.Id changeId, String uuid) throws RestApiException {
return gApi.changes().id(changeId.get()).current().robotCommentsAsList().stream()
.filter(comment -> comment.id.equals(uuid))
.findAny()
.orElseThrow(
() ->
new IllegalStateException(
String.format(
"Robot Comment %s not found on change %d on the latest patchset",
uuid, changeId.get())));
}
private RobotCommentInfo getRobotCommentFromServer(PatchSet.Id patchsetId, String uuid)
throws RestApiException {
return gApi.changes().id(patchsetId.changeId().toString())
.revision(patchsetId.getId().toString()).robotCommentsAsList().stream()
.filter(comment -> comment.id.equals(uuid))
.findAny()
.orElseThrow(
() ->
new IllegalStateException(
String.format(
"Robot Comment %s not found on change %d on patchset %d",
uuid, patchsetId.changeId().get(), patchsetId.get())));
}
private CommentInfo getDraftCommentFromServer(Change.Id changeId, String uuid)
throws RestApiException {
return gApi.changes().id(changeId.get()).draftsAsList().stream()