
Currently Submission Id is constructed by the change-id of the change that triggered the submission, the timestamp, and a random alphanumeric string. This is not pretty. Since we recently revealed the submission id via ChangeInfo in Ic557e0c94 and via queries in I337f7f8ae, it's a good idea to change the submission id to be more user friendly. Submission Id is now constructed of "<numeric-id>-<topic>" or "<numeric-id>" if topic doesn't exist for that change. The change id is used because it makes the submission id unique (a change can only be submitted once). The topic is used mostly since this is currently one of the main use cases for Revert Submission. Change-Id: Iec8b0db66adf9a7ff2809994acaedef09e4e885c
3144 lines
104 KiB
Java
3144 lines
104 KiB
Java
// 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.server.notedb;
|
|
|
|
import static com.google.common.collect.ImmutableList.toImmutableList;
|
|
import static com.google.common.truth.Truth.assertThat;
|
|
import static com.google.common.truth.Truth.assertWithMessage;
|
|
import static com.google.common.truth.Truth8.assertThat;
|
|
import static com.google.gerrit.entities.RefNames.changeMetaRef;
|
|
import static com.google.gerrit.entities.RefNames.refsDraftComments;
|
|
import static com.google.gerrit.server.notedb.ReviewerStateInternal.CC;
|
|
import static com.google.gerrit.server.notedb.ReviewerStateInternal.REMOVED;
|
|
import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
|
|
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
|
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
|
import static java.util.Comparator.comparing;
|
|
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
|
|
|
|
import com.google.common.base.Throwables;
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.google.common.collect.ImmutableListMultimap;
|
|
import com.google.common.collect.ImmutableSet;
|
|
import com.google.common.collect.ImmutableTable;
|
|
import com.google.common.collect.Iterables;
|
|
import com.google.common.collect.ListMultimap;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.gerrit.common.data.SubmitRecord;
|
|
import com.google.gerrit.entities.Account;
|
|
import com.google.gerrit.entities.BranchNameKey;
|
|
import com.google.gerrit.entities.Change;
|
|
import com.google.gerrit.entities.ChangeMessage;
|
|
import com.google.gerrit.entities.Comment;
|
|
import com.google.gerrit.entities.CommentRange;
|
|
import com.google.gerrit.entities.PatchSet;
|
|
import com.google.gerrit.entities.PatchSetApproval;
|
|
import com.google.gerrit.entities.SubmissionId;
|
|
import com.google.gerrit.exceptions.StorageException;
|
|
import com.google.gerrit.mail.Address;
|
|
import com.google.gerrit.server.AssigneeStatusUpdate;
|
|
import com.google.gerrit.server.CurrentUser;
|
|
import com.google.gerrit.server.IdentifiedUser;
|
|
import com.google.gerrit.server.ReviewerSet;
|
|
import com.google.gerrit.server.config.GerritServerId;
|
|
import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk;
|
|
import com.google.gerrit.server.util.time.TimeUtil;
|
|
import com.google.gerrit.testing.TestChanges;
|
|
import com.google.inject.Inject;
|
|
import java.sql.Timestamp;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import org.eclipse.jgit.errors.ConfigInvalidException;
|
|
import org.eclipse.jgit.lib.ObjectId;
|
|
import org.eclipse.jgit.lib.Ref;
|
|
import org.eclipse.jgit.lib.Repository;
|
|
import org.eclipse.jgit.notes.NoteMap;
|
|
import org.eclipse.jgit.revwalk.RevCommit;
|
|
import org.eclipse.jgit.revwalk.RevWalk;
|
|
import org.junit.Test;
|
|
|
|
public class ChangeNotesTest extends AbstractChangeNotesTest {
|
|
@Inject private DraftCommentNotes.Factory draftNotesFactory;
|
|
|
|
@Inject private ChangeNoteJson changeNoteJson;
|
|
|
|
@Inject private @GerritServerId String serverId;
|
|
|
|
@Test
|
|
public void tagChangeMessage() throws Exception {
|
|
String tag = "jenkins";
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setChangeMessage("verification from jenkins");
|
|
update.setTag(tag);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
|
|
assertThat(notes.getChangeMessages()).hasSize(1);
|
|
assertThat(notes.getChangeMessages().get(0).getTag()).isEqualTo(tag);
|
|
}
|
|
|
|
@Test
|
|
public void patchSetDescription() throws Exception {
|
|
String description = "descriptive";
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setPsDescription(description);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getCurrentPatchSet().description()).hasValue(description);
|
|
|
|
description = "new, now more descriptive!";
|
|
update = newUpdate(c, changeOwner);
|
|
update.setPsDescription(description);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getCurrentPatchSet().description()).hasValue(description);
|
|
}
|
|
|
|
@Test
|
|
public void tagInlineComments() throws Exception {
|
|
String tag = "jenkins";
|
|
Change c = newChange();
|
|
RevCommit commit = tr.commit().message("PS2").create();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putComment(
|
|
Comment.Status.PUBLISHED,
|
|
newComment(
|
|
c.currentPatchSetId(),
|
|
"a.txt",
|
|
"uuid1",
|
|
new CommentRange(1, 2, 3, 4),
|
|
1,
|
|
changeOwner,
|
|
null,
|
|
TimeUtil.nowTs(),
|
|
"Comment",
|
|
(short) 1,
|
|
commit,
|
|
false));
|
|
update.setTag(tag);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
|
|
ImmutableListMultimap<ObjectId, Comment> comments = notes.getComments();
|
|
assertThat(comments).hasSize(1);
|
|
assertThat(comments.entries().asList().get(0).getValue().tag).isEqualTo(tag);
|
|
}
|
|
|
|
@Test
|
|
public void tagApprovals() throws Exception {
|
|
String tag1 = "jenkins";
|
|
String tag2 = "ip";
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putApproval("Verified", (short) -1);
|
|
update.setTag(tag1);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putApproval("Verified", (short) 1);
|
|
update.setTag(tag2);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
|
|
ImmutableListMultimap<PatchSet.Id, PatchSetApproval> approvals = notes.getApprovals();
|
|
assertThat(approvals).hasSize(1);
|
|
assertThat(approvals.entries().asList().get(0).getValue().tag()).hasValue(tag2);
|
|
}
|
|
|
|
@Test
|
|
public void multipleTags() throws Exception {
|
|
String ipTag = "ip";
|
|
String coverageTag = "coverage";
|
|
String integrationTag = "integration";
|
|
Change c = newChange();
|
|
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putApproval("Verified", (short) -1);
|
|
update.setChangeMessage("integration verification");
|
|
update.setTag(integrationTag);
|
|
update.commit();
|
|
|
|
RevCommit commit = tr.commit().message("PS2").create();
|
|
update = newUpdate(c, changeOwner);
|
|
update.putComment(
|
|
Comment.Status.PUBLISHED,
|
|
newComment(
|
|
c.currentPatchSetId(),
|
|
"a.txt",
|
|
"uuid1",
|
|
new CommentRange(1, 2, 3, 4),
|
|
1,
|
|
changeOwner,
|
|
null,
|
|
TimeUtil.nowTs(),
|
|
"Comment",
|
|
(short) 1,
|
|
commit,
|
|
false));
|
|
update.setChangeMessage("coverage verification");
|
|
update.setTag(coverageTag);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setChangeMessage("ip clear");
|
|
update.setTag(ipTag);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
|
|
ImmutableListMultimap<PatchSet.Id, PatchSetApproval> approvals = notes.getApprovals();
|
|
assertThat(approvals).hasSize(1);
|
|
PatchSetApproval approval = approvals.entries().asList().get(0).getValue();
|
|
assertThat(approval.tag()).hasValue(integrationTag);
|
|
assertThat(approval.value()).isEqualTo(-1);
|
|
|
|
ImmutableListMultimap<ObjectId, Comment> comments = notes.getComments();
|
|
assertThat(comments).hasSize(1);
|
|
assertThat(comments.entries().asList().get(0).getValue().tag).isEqualTo(coverageTag);
|
|
|
|
ImmutableList<ChangeMessage> messages = notes.getChangeMessages();
|
|
assertThat(messages).hasSize(3);
|
|
assertThat(messages.get(0).getTag()).isEqualTo(integrationTag);
|
|
assertThat(messages.get(1).getTag()).isEqualTo(coverageTag);
|
|
assertThat(messages.get(2).getTag()).isEqualTo(ipTag);
|
|
}
|
|
|
|
@Test
|
|
public void approvalsOnePatchSet() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putApproval("Verified", (short) 1);
|
|
update.putApproval("Code-Review", (short) -1);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getApprovals().keySet()).containsExactly(c.currentPatchSetId());
|
|
List<PatchSetApproval> psas = notes.getApprovals().get(c.currentPatchSetId());
|
|
assertThat(psas).hasSize(2);
|
|
|
|
assertThat(psas.get(0).patchSetId()).isEqualTo(c.currentPatchSetId());
|
|
assertThat(psas.get(0).accountId().get()).isEqualTo(1);
|
|
assertThat(psas.get(0).label()).isEqualTo("Code-Review");
|
|
assertThat(psas.get(0).value()).isEqualTo((short) -1);
|
|
assertThat(psas.get(0).granted()).isEqualTo(truncate(after(c, 2000)));
|
|
|
|
assertThat(psas.get(1).patchSetId()).isEqualTo(c.currentPatchSetId());
|
|
assertThat(psas.get(1).accountId().get()).isEqualTo(1);
|
|
assertThat(psas.get(1).label()).isEqualTo("Verified");
|
|
assertThat(psas.get(1).value()).isEqualTo((short) 1);
|
|
assertThat(psas.get(1).granted()).isEqualTo(psas.get(0).granted());
|
|
}
|
|
|
|
@Test
|
|
public void approvalsMultiplePatchSets() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) -1);
|
|
update.commit();
|
|
PatchSet.Id ps1 = c.currentPatchSetId();
|
|
|
|
incrementPatchSet(c);
|
|
update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) 1);
|
|
update.commit();
|
|
PatchSet.Id ps2 = c.currentPatchSetId();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
ListMultimap<PatchSet.Id, PatchSetApproval> psas = notes.getApprovals();
|
|
assertThat(psas).hasSize(2);
|
|
|
|
PatchSetApproval psa1 = Iterables.getOnlyElement(psas.get(ps1));
|
|
assertThat(psa1.patchSetId()).isEqualTo(ps1);
|
|
assertThat(psa1.accountId().get()).isEqualTo(1);
|
|
assertThat(psa1.label()).isEqualTo("Code-Review");
|
|
assertThat(psa1.value()).isEqualTo((short) -1);
|
|
assertThat(psa1.granted()).isEqualTo(truncate(after(c, 2000)));
|
|
|
|
PatchSetApproval psa2 = Iterables.getOnlyElement(psas.get(ps2));
|
|
assertThat(psa2.patchSetId()).isEqualTo(ps2);
|
|
assertThat(psa2.accountId().get()).isEqualTo(1);
|
|
assertThat(psa2.label()).isEqualTo("Code-Review");
|
|
assertThat(psa2.value()).isEqualTo((short) +1);
|
|
assertThat(psa2.granted()).isEqualTo(truncate(after(c, 4000)));
|
|
}
|
|
|
|
@Test
|
|
public void approvalsMultipleApprovals() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) -1);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
PatchSetApproval psa =
|
|
Iterables.getOnlyElement(notes.getApprovals().get(c.currentPatchSetId()));
|
|
assertThat(psa.label()).isEqualTo("Code-Review");
|
|
assertThat(psa.value()).isEqualTo((short) -1);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) 1);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
psa = Iterables.getOnlyElement(notes.getApprovals().get(c.currentPatchSetId()));
|
|
assertThat(psa.label()).isEqualTo("Code-Review");
|
|
assertThat(psa.value()).isEqualTo((short) 1);
|
|
}
|
|
|
|
@Test
|
|
public void approvalsMultipleUsers() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) -1);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
update.putApproval("Code-Review", (short) 1);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getApprovals().keySet()).containsExactly(c.currentPatchSetId());
|
|
List<PatchSetApproval> psas = notes.getApprovals().get(c.currentPatchSetId());
|
|
assertThat(psas).hasSize(2);
|
|
|
|
assertThat(psas.get(0).patchSetId()).isEqualTo(c.currentPatchSetId());
|
|
assertThat(psas.get(0).accountId().get()).isEqualTo(1);
|
|
assertThat(psas.get(0).label()).isEqualTo("Code-Review");
|
|
assertThat(psas.get(0).value()).isEqualTo((short) -1);
|
|
assertThat(psas.get(0).granted()).isEqualTo(truncate(after(c, 2000)));
|
|
|
|
assertThat(psas.get(1).patchSetId()).isEqualTo(c.currentPatchSetId());
|
|
assertThat(psas.get(1).accountId().get()).isEqualTo(2);
|
|
assertThat(psas.get(1).label()).isEqualTo("Code-Review");
|
|
assertThat(psas.get(1).value()).isEqualTo((short) 1);
|
|
assertThat(psas.get(1).granted()).isEqualTo(truncate(after(c, 3000)));
|
|
}
|
|
|
|
@Test
|
|
public void approvalsTombstone() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putApproval("Not-For-Long", (short) 1);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
PatchSetApproval psa =
|
|
Iterables.getOnlyElement(notes.getApprovals().get(c.currentPatchSetId()));
|
|
assertThat(psa.accountId().get()).isEqualTo(1);
|
|
assertThat(psa.label()).isEqualTo("Not-For-Long");
|
|
assertThat(psa.value()).isEqualTo((short) 1);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.removeApproval("Not-For-Long");
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getApprovals())
|
|
.containsExactlyEntriesIn(
|
|
ImmutableListMultimap.of(
|
|
psa.patchSetId(),
|
|
PatchSetApproval.builder()
|
|
.key(psa.key())
|
|
.value(0)
|
|
.granted(update.getWhen())
|
|
.build()));
|
|
}
|
|
|
|
@Test
|
|
public void removeOtherUsersApprovals() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
update.putApproval("Not-For-Long", (short) 1);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
PatchSetApproval psa =
|
|
Iterables.getOnlyElement(notes.getApprovals().get(c.currentPatchSetId()));
|
|
assertThat(psa.accountId()).isEqualTo(otherUserId);
|
|
assertThat(psa.label()).isEqualTo("Not-For-Long");
|
|
assertThat(psa.value()).isEqualTo((short) 1);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.removeApprovalFor(otherUserId, "Not-For-Long");
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getApprovals())
|
|
.containsExactlyEntriesIn(
|
|
ImmutableListMultimap.of(
|
|
psa.patchSetId(),
|
|
PatchSetApproval.builder()
|
|
.key(psa.key())
|
|
.value(0)
|
|
.granted(update.getWhen())
|
|
.build()));
|
|
|
|
// Add back approval on same label.
|
|
update = newUpdate(c, otherUser);
|
|
update.putApproval("Not-For-Long", (short) 2);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
psa = Iterables.getOnlyElement(notes.getApprovals().get(c.currentPatchSetId()));
|
|
assertThat(psa.accountId()).isEqualTo(otherUserId);
|
|
assertThat(psa.label()).isEqualTo("Not-For-Long");
|
|
assertThat(psa.value()).isEqualTo((short) 2);
|
|
}
|
|
|
|
@Test
|
|
public void putOtherUsersApprovals() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) 1);
|
|
update.putApprovalFor(otherUser.getAccountId(), "Code-Review", (short) -1);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
ImmutableList<PatchSetApproval> approvals =
|
|
notes.getApprovals().get(c.currentPatchSetId()).stream()
|
|
.sorted(comparing(a -> a.accountId().get()))
|
|
.collect(toImmutableList());
|
|
assertThat(approvals).hasSize(2);
|
|
|
|
assertThat(approvals.get(0).accountId()).isEqualTo(changeOwner.getAccountId());
|
|
assertThat(approvals.get(0).label()).isEqualTo("Code-Review");
|
|
assertThat(approvals.get(0).value()).isEqualTo((short) 1);
|
|
|
|
assertThat(approvals.get(1).accountId()).isEqualTo(otherUser.getAccountId());
|
|
assertThat(approvals.get(1).label()).isEqualTo("Code-Review");
|
|
assertThat(approvals.get(1).value()).isEqualTo((short) -1);
|
|
}
|
|
|
|
@Test
|
|
public void approvalsPostSubmit() throws Exception {
|
|
Change c = newChange();
|
|
SubmissionId submissionId = new SubmissionId(c);
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) 1);
|
|
update.putApproval("Verified", (short) 1);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.merge(
|
|
submissionId,
|
|
ImmutableList.of(
|
|
submitRecord(
|
|
"NOT_READY",
|
|
null,
|
|
submitLabel("Verified", "OK", changeOwner.getAccountId()),
|
|
submitLabel("Code-Review", "NEED", null))));
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) 2);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
List<PatchSetApproval> approvals = Lists.newArrayList(notes.getApprovals().values());
|
|
assertThat(approvals).hasSize(2);
|
|
assertThat(approvals.get(0).label()).isEqualTo("Verified");
|
|
assertThat(approvals.get(0).value()).isEqualTo((short) 1);
|
|
assertThat(approvals.get(0).postSubmit()).isFalse();
|
|
assertThat(approvals.get(1).label()).isEqualTo("Code-Review");
|
|
assertThat(approvals.get(1).value()).isEqualTo((short) 2);
|
|
assertThat(approvals.get(1).postSubmit()).isTrue();
|
|
}
|
|
|
|
@Test
|
|
public void approvalsDuringSubmit() throws Exception {
|
|
Change c = newChange();
|
|
SubmissionId submissionId = new SubmissionId(c);
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) 1);
|
|
update.putApproval("Verified", (short) 1);
|
|
update.commit();
|
|
|
|
Account.Id ownerId = changeOwner.getAccountId();
|
|
Account.Id otherId = otherUser.getAccountId();
|
|
update = newUpdate(c, otherUser);
|
|
update.merge(
|
|
submissionId,
|
|
ImmutableList.of(
|
|
submitRecord(
|
|
"NOT_READY",
|
|
null,
|
|
submitLabel("Verified", "OK", ownerId),
|
|
submitLabel("Code-Review", "NEED", null))));
|
|
update.putApproval("Other-Label", (short) 1);
|
|
update.putApprovalFor(ownerId, "Code-Review", (short) 2);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
update.putApproval("Other-Label", (short) 2);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
|
|
List<PatchSetApproval> approvals = Lists.newArrayList(notes.getApprovals().values());
|
|
assertThat(approvals).hasSize(3);
|
|
assertThat(approvals.get(0).accountId()).isEqualTo(ownerId);
|
|
assertThat(approvals.get(0).label()).isEqualTo("Verified");
|
|
assertThat(approvals.get(0).value()).isEqualTo(1);
|
|
assertThat(approvals.get(0).postSubmit()).isFalse();
|
|
assertThat(approvals.get(1).accountId()).isEqualTo(ownerId);
|
|
assertThat(approvals.get(1).label()).isEqualTo("Code-Review");
|
|
assertThat(approvals.get(1).value()).isEqualTo(2);
|
|
assertThat(approvals.get(1).postSubmit()).isFalse(); // During submit.
|
|
assertThat(approvals.get(2).accountId()).isEqualTo(otherId);
|
|
assertThat(approvals.get(2).label()).isEqualTo("Other-Label");
|
|
assertThat(approvals.get(2).value()).isEqualTo(2);
|
|
assertThat(approvals.get(2).postSubmit()).isTrue();
|
|
}
|
|
|
|
@Test
|
|
public void multipleReviewers() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewer(changeOwner.getAccount().id(), REVIEWER);
|
|
update.putReviewer(otherUser.getAccount().id(), REVIEWER);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
Timestamp ts = new Timestamp(update.getWhen().getTime());
|
|
assertThat(notes.getReviewers())
|
|
.isEqualTo(
|
|
ReviewerSet.fromTable(
|
|
ImmutableTable.<ReviewerStateInternal, Account.Id, Timestamp>builder()
|
|
.put(REVIEWER, Account.id(1), ts)
|
|
.put(REVIEWER, Account.id(2), ts)
|
|
.build()));
|
|
}
|
|
|
|
@Test
|
|
public void reviewerTypes() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewer(changeOwner.getAccount().id(), REVIEWER);
|
|
update.putReviewer(otherUser.getAccount().id(), CC);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
Timestamp ts = new Timestamp(update.getWhen().getTime());
|
|
assertThat(notes.getReviewers())
|
|
.isEqualTo(
|
|
ReviewerSet.fromTable(
|
|
ImmutableTable.<ReviewerStateInternal, Account.Id, Timestamp>builder()
|
|
.put(REVIEWER, Account.id(1), ts)
|
|
.put(CC, Account.id(2), ts)
|
|
.build()));
|
|
}
|
|
|
|
@Test
|
|
public void oneReviewerMultipleTypes() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewer(otherUser.getAccount().id(), REVIEWER);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
Timestamp ts = new Timestamp(update.getWhen().getTime());
|
|
assertThat(notes.getReviewers())
|
|
.isEqualTo(ReviewerSet.fromTable(ImmutableTable.of(REVIEWER, Account.id(2), ts)));
|
|
|
|
update = newUpdate(c, otherUser);
|
|
update.putReviewer(otherUser.getAccount().id(), CC);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
ts = new Timestamp(update.getWhen().getTime());
|
|
assertThat(notes.getReviewers())
|
|
.isEqualTo(ReviewerSet.fromTable(ImmutableTable.of(CC, Account.id(2), ts)));
|
|
}
|
|
|
|
@Test
|
|
public void removeReviewer() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewer(otherUser.getAccount().id(), REVIEWER);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) 1);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
update.putApproval("Code-Review", (short) 1);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
List<PatchSetApproval> psas = notes.getApprovals().get(c.currentPatchSetId());
|
|
assertThat(psas).hasSize(2);
|
|
assertThat(psas.get(0).accountId()).isEqualTo(changeOwner.getAccount().id());
|
|
assertThat(psas.get(1).accountId()).isEqualTo(otherUser.getAccount().id());
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.removeReviewer(otherUser.getAccount().id());
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
psas = notes.getApprovals().get(c.currentPatchSetId());
|
|
assertThat(psas).hasSize(1);
|
|
assertThat(psas.get(0).accountId()).isEqualTo(changeOwner.getAccount().id());
|
|
}
|
|
|
|
@Test
|
|
public void submitRecords() throws Exception {
|
|
Change c = newChange();
|
|
SubmissionId submissionId = new SubmissionId(c);
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setSubjectForCommit("Submit patch set 1");
|
|
|
|
update.merge(
|
|
submissionId,
|
|
ImmutableList.of(
|
|
submitRecord(
|
|
"NOT_READY",
|
|
null,
|
|
submitLabel("Verified", "OK", changeOwner.getAccountId()),
|
|
submitLabel("Code-Review", "NEED", null)),
|
|
submitRecord(
|
|
"NOT_READY",
|
|
null,
|
|
submitLabel("Verified", "OK", changeOwner.getAccountId()),
|
|
submitLabel("Alternative-Code-Review", "NEED", null))));
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
List<SubmitRecord> recs = notes.getSubmitRecords();
|
|
assertThat(recs).hasSize(2);
|
|
assertThat(recs.get(0))
|
|
.isEqualTo(
|
|
submitRecord(
|
|
"NOT_READY",
|
|
null,
|
|
submitLabel("Verified", "OK", changeOwner.getAccountId()),
|
|
submitLabel("Code-Review", "NEED", null)));
|
|
assertThat(recs.get(1))
|
|
.isEqualTo(
|
|
submitRecord(
|
|
"NOT_READY",
|
|
null,
|
|
submitLabel("Verified", "OK", changeOwner.getAccountId()),
|
|
submitLabel("Alternative-Code-Review", "NEED", null)));
|
|
assertThat(notes.getChange().getSubmissionId()).isEqualTo(submissionId.toString());
|
|
}
|
|
|
|
@Test
|
|
public void latestSubmitRecordsOnly() throws Exception {
|
|
Change c = newChange();
|
|
SubmissionId submissionId = new SubmissionId(c);
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setSubjectForCommit("Submit patch set 1");
|
|
update.merge(
|
|
submissionId,
|
|
ImmutableList.of(
|
|
submitRecord("OK", null, submitLabel("Code-Review", "OK", otherUser.getAccountId()))));
|
|
update.commit();
|
|
|
|
incrementPatchSet(c);
|
|
update = newUpdate(c, changeOwner);
|
|
update.setSubjectForCommit("Submit patch set 2");
|
|
update.merge(
|
|
submissionId,
|
|
ImmutableList.of(
|
|
submitRecord(
|
|
"OK", null, submitLabel("Code-Review", "OK", changeOwner.getAccountId()))));
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getSubmitRecords())
|
|
.containsExactly(
|
|
submitRecord("OK", null, submitLabel("Code-Review", "OK", changeOwner.getAccountId())));
|
|
assertThat(notes.getChange().getSubmissionId()).isEqualTo(submissionId.toString());
|
|
}
|
|
|
|
@Test
|
|
public void emptyChangeUpdate() throws Exception {
|
|
Change c = newChange();
|
|
Ref initial = repo.exactRef(changeMetaRef(c.getId()));
|
|
assertThat(initial).isNotNull();
|
|
|
|
// Empty update doesn't create a new commit.
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.commit();
|
|
assertThat(update.getResult()).isNull();
|
|
|
|
Ref updated = repo.exactRef(changeMetaRef(c.getId()));
|
|
assertThat(updated.getObjectId()).isEqualTo(initial.getObjectId());
|
|
}
|
|
|
|
@Test
|
|
public void assigneeCommit() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setAssignee(otherUserId);
|
|
ObjectId result = update.commit();
|
|
assertThat(result).isNotNull();
|
|
try (RevWalk rw = new RevWalk(repo)) {
|
|
RevCommit commit = rw.parseCommit(update.getResult());
|
|
rw.parseBody(commit);
|
|
String strIdent = "Gerrit User " + otherUserId + " <" + otherUserId + "@" + serverId + ">";
|
|
assertThat(commit.getFullMessage()).contains("Assignee: " + strIdent);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void assigneeChangeNotes() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setAssignee(otherUserId);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getChange().getAssignee()).isEqualTo(otherUserId);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setAssignee(changeOwner.getAccountId());
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().getAssignee()).isEqualTo(changeOwner.getAccountId());
|
|
}
|
|
|
|
@Test
|
|
public void pastAssigneesChangeNotes() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setAssignee(otherUserId);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setAssignee(changeOwner.getAccountId());
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setAssignee(otherUserId);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.removeAssignee();
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getPastAssignees()).hasSize(2);
|
|
}
|
|
|
|
@Test
|
|
public void assigneeStatusUpdateChangeNotes() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
update.setAssignee(otherUserId);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.removeAssignee();
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setAssignee(changeOwner.getAccountId());
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setAssignee(otherUserId);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
ImmutableList<AssigneeStatusUpdate> statusUpdates = notes.getAssigneeUpdates();
|
|
assertThat(statusUpdates).hasSize(4);
|
|
assertThat(statusUpdates.get(3).updatedBy()).isEqualTo(otherUserId);
|
|
assertThat(statusUpdates.get(3).currentAssignee()).hasValue(otherUserId);
|
|
assertThat(statusUpdates.get(2).currentAssignee()).isEmpty();
|
|
assertThat(statusUpdates.get(1).currentAssignee()).hasValue(changeOwner.getAccountId());
|
|
assertThat(statusUpdates.get(0).currentAssignee()).hasValue(otherUserId);
|
|
}
|
|
|
|
@Test
|
|
public void hashtagCommit() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
LinkedHashSet<String> hashtags = new LinkedHashSet<>();
|
|
hashtags.add("tag1");
|
|
hashtags.add("tag2");
|
|
update.setHashtags(hashtags);
|
|
update.commit();
|
|
try (RevWalk walk = new RevWalk(repo)) {
|
|
RevCommit commit = walk.parseCommit(update.getResult());
|
|
walk.parseBody(commit);
|
|
assertThat(commit.getFullMessage()).contains("Hashtags: tag1,tag2\n");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void hashtagChangeNotes() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
LinkedHashSet<String> hashtags = new LinkedHashSet<>();
|
|
hashtags.add("tag1");
|
|
hashtags.add("tag2");
|
|
update.setHashtags(hashtags);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getHashtags()).isEqualTo(hashtags);
|
|
}
|
|
|
|
@Test
|
|
public void topicChangeNotes() throws Exception {
|
|
Change c = newChange();
|
|
|
|
// initially topic is not set
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getChange().getTopic()).isNull();
|
|
|
|
// set topic
|
|
String topic = "myTopic";
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setTopic(topic);
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().getTopic()).isEqualTo(topic);
|
|
|
|
// clear topic by setting empty string
|
|
update = newUpdate(c, changeOwner);
|
|
update.setTopic("");
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().getTopic()).isNull();
|
|
|
|
// set other topic
|
|
topic = "otherTopic";
|
|
update = newUpdate(c, changeOwner);
|
|
update.setTopic(topic);
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().getTopic()).isEqualTo(topic);
|
|
|
|
// clear topic by setting null
|
|
update = newUpdate(c, changeOwner);
|
|
update.setTopic(null);
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().getTopic()).isNull();
|
|
}
|
|
|
|
@Test
|
|
public void changeIdChangeNotes() throws Exception {
|
|
Change c = newChange();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getChange().getKey()).isEqualTo(c.getKey());
|
|
|
|
// An update doesn't affect the Change-Id
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setTopic("topic"); // Change something to get a new commit.
|
|
update.commit();
|
|
assertThat(notes.getChange().getKey()).isEqualTo(c.getKey());
|
|
|
|
// Trying to set another Change-Id fails
|
|
String otherChangeId = "I577fb248e474018276351785930358ec0450e9f7";
|
|
ChangeUpdate failingUpdate = newUpdate(c, changeOwner);
|
|
IllegalArgumentException thrown =
|
|
assertThrows(
|
|
IllegalArgumentException.class, () -> failingUpdate.setChangeId(otherChangeId));
|
|
assertThat(thrown)
|
|
.hasMessageThat()
|
|
.contains(
|
|
"The Change-Id was already set to "
|
|
+ c.getKey()
|
|
+ ", so we cannot set this Change-Id: "
|
|
+ otherChangeId);
|
|
}
|
|
|
|
@Test
|
|
public void branchChangeNotes() throws Exception {
|
|
Change c = newChange();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
BranchNameKey expectedBranch = BranchNameKey.create(project, "refs/heads/master");
|
|
assertThat(notes.getChange().getDest()).isEqualTo(expectedBranch);
|
|
|
|
// An update doesn't affect the branch
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setTopic("topic"); // Change something to get a new commit.
|
|
update.commit();
|
|
assertThat(newNotes(c).getChange().getDest()).isEqualTo(expectedBranch);
|
|
|
|
// Set another branch
|
|
String otherBranch = "refs/heads/stable";
|
|
update = newUpdate(c, changeOwner);
|
|
update.setBranch(otherBranch);
|
|
update.commit();
|
|
assertThat(newNotes(c).getChange().getDest())
|
|
.isEqualTo(BranchNameKey.create(project, otherBranch));
|
|
}
|
|
|
|
@Test
|
|
public void ownerChangeNotes() throws Exception {
|
|
Change c = newChange();
|
|
|
|
assertThat(newNotes(c).getChange().getOwner()).isEqualTo(changeOwner.getAccountId());
|
|
|
|
// An update doesn't affect the owner
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
update.setTopic("topic"); // Change something to get a new commit.
|
|
update.commit();
|
|
assertThat(newNotes(c).getChange().getOwner()).isEqualTo(changeOwner.getAccountId());
|
|
}
|
|
|
|
@Test
|
|
public void createdOnChangeNotes() throws Exception {
|
|
Change c = newChange();
|
|
|
|
Timestamp createdOn = newNotes(c).getChange().getCreatedOn();
|
|
assertThat(createdOn).isNotNull();
|
|
|
|
// An update doesn't affect the createdOn timestamp.
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setTopic("topic"); // Change something to get a new commit.
|
|
update.commit();
|
|
assertThat(newNotes(c).getChange().getCreatedOn()).isEqualTo(createdOn);
|
|
}
|
|
|
|
@Test
|
|
public void lastUpdatedOnChangeNotes() throws Exception {
|
|
Change c = newChange();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
Timestamp ts1 = notes.getChange().getLastUpdatedOn();
|
|
assertThat(ts1).isEqualTo(notes.getChange().getCreatedOn());
|
|
|
|
// Various kinds of updates that update the timestamp.
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setTopic("topic"); // Change something to get a new commit.
|
|
update.commit();
|
|
Timestamp ts2 = newNotes(c).getChange().getLastUpdatedOn();
|
|
assertThat(ts2).isGreaterThan(ts1);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setChangeMessage("Some message");
|
|
update.commit();
|
|
Timestamp ts3 = newNotes(c).getChange().getLastUpdatedOn();
|
|
assertThat(ts3).isGreaterThan(ts2);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setHashtags(ImmutableSet.of("foo"));
|
|
update.commit();
|
|
Timestamp ts4 = newNotes(c).getChange().getLastUpdatedOn();
|
|
assertThat(ts4).isGreaterThan(ts3);
|
|
|
|
incrementPatchSet(c);
|
|
Timestamp ts5 = newNotes(c).getChange().getLastUpdatedOn();
|
|
assertThat(ts5).isGreaterThan(ts4);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) 1);
|
|
update.commit();
|
|
Timestamp ts6 = newNotes(c).getChange().getLastUpdatedOn();
|
|
assertThat(ts6).isGreaterThan(ts5);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setStatus(Change.Status.ABANDONED);
|
|
update.commit();
|
|
Timestamp ts7 = newNotes(c).getChange().getLastUpdatedOn();
|
|
assertThat(ts7).isGreaterThan(ts6);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putReviewer(otherUser.getAccountId(), ReviewerStateInternal.REVIEWER);
|
|
update.commit();
|
|
Timestamp ts8 = newNotes(c).getChange().getLastUpdatedOn();
|
|
assertThat(ts8).isGreaterThan(ts7);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setGroups(ImmutableList.of("a", "b"));
|
|
update.commit();
|
|
Timestamp ts9 = newNotes(c).getChange().getLastUpdatedOn();
|
|
assertThat(ts9).isGreaterThan(ts8);
|
|
|
|
// Finish off by merging the change.
|
|
update = newUpdate(c, changeOwner);
|
|
update.merge(
|
|
new SubmissionId(c),
|
|
ImmutableList.of(
|
|
submitRecord(
|
|
"NOT_READY",
|
|
null,
|
|
submitLabel("Verified", "OK", changeOwner.getAccountId()),
|
|
submitLabel("Alternative-Code-Review", "NEED", null))));
|
|
update.commit();
|
|
Timestamp ts10 = newNotes(c).getChange().getLastUpdatedOn();
|
|
assertThat(ts10).isGreaterThan(ts9);
|
|
}
|
|
|
|
@Test
|
|
public void subjectLeadingWhitespaceChangeNotes() throws Exception {
|
|
Change c = TestChanges.newChange(project, changeOwner.getAccountId());
|
|
String trimmedSubj = c.getSubject();
|
|
c.setCurrentPatchSet(c.currentPatchSetId(), " " + trimmedSubj, c.getOriginalSubject());
|
|
ChangeUpdate update = newUpdateForNewChange(c, changeOwner);
|
|
update.setChangeId(c.getKey().get());
|
|
update.setBranch(c.getDest().branch());
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getChange().getSubject()).isEqualTo(trimmedSubj);
|
|
|
|
String tabSubj = "\t\t" + trimmedSubj;
|
|
|
|
c = TestChanges.newChange(project, changeOwner.getAccountId());
|
|
c.setCurrentPatchSet(c.currentPatchSetId(), tabSubj, c.getOriginalSubject());
|
|
update = newUpdateForNewChange(c, changeOwner);
|
|
update.setChangeId(c.getKey().get());
|
|
update.setBranch(c.getDest().branch());
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().getSubject()).isEqualTo(tabSubj);
|
|
}
|
|
|
|
@Test
|
|
public void commitChangeNotesUnique() throws Exception {
|
|
// PatchSetId -> ObjectId must be a one to one mapping
|
|
Change c = newChange();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
PatchSet ps = notes.getCurrentPatchSet();
|
|
assertThat(ps).isNotNull();
|
|
|
|
// new revId for the same patch set, ps1
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
RevCommit commit = tr.commit().message("PS1 again").create();
|
|
update.setCommit(rw, commit);
|
|
update.commit();
|
|
|
|
StorageException e = assertThrows(StorageException.class, () -> newNotes(c));
|
|
assertCause(
|
|
e,
|
|
ConfigInvalidException.class,
|
|
"Multiple revisions parsed for patch set 1:"
|
|
+ " "
|
|
+ commit.name()
|
|
+ " and "
|
|
+ ps.commitId().name());
|
|
}
|
|
|
|
@Test
|
|
public void patchSetChangeNotes() throws Exception {
|
|
Change c = newChange();
|
|
|
|
// ps1 created by newChange()
|
|
ChangeNotes notes = newNotes(c);
|
|
PatchSet ps1 = notes.getCurrentPatchSet();
|
|
assertThat(notes.getChange().currentPatchSetId()).isEqualTo(ps1.id());
|
|
assertThat(notes.getChange().getSubject()).isEqualTo("Change subject");
|
|
assertThat(notes.getChange().getOriginalSubject()).isEqualTo("Change subject");
|
|
assertThat(ps1.id()).isEqualTo(PatchSet.id(c.getId(), 1));
|
|
assertThat(ps1.uploader()).isEqualTo(changeOwner.getAccountId());
|
|
|
|
// ps2 by other user
|
|
RevCommit commit = incrementPatchSet(c, otherUser);
|
|
notes = newNotes(c);
|
|
PatchSet ps2 = notes.getCurrentPatchSet();
|
|
assertThat(ps2.id()).isEqualTo(PatchSet.id(c.getId(), 2));
|
|
assertThat(notes.getChange().getSubject()).isEqualTo("PS2");
|
|
assertThat(notes.getChange().getOriginalSubject()).isEqualTo("Change subject");
|
|
assertThat(notes.getChange().currentPatchSetId()).isEqualTo(ps2.id());
|
|
assertThat(ps2.commitId()).isNotEqualTo(ps1.commitId());
|
|
assertThat(ps2.commitId()).isEqualTo(commit);
|
|
assertThat(ps2.uploader()).isEqualTo(otherUser.getAccountId());
|
|
assertThat(ps2.createdOn()).isEqualTo(notes.getChange().getLastUpdatedOn());
|
|
|
|
// comment on ps1, current patch set is still ps2
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setPatchSetId(ps1.id());
|
|
update.setChangeMessage("Comment on old patch set.");
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().currentPatchSetId()).isEqualTo(ps2.id());
|
|
}
|
|
|
|
@Test
|
|
public void patchSetStates() throws Exception {
|
|
Change c = newChange();
|
|
PatchSet.Id psId1 = c.currentPatchSetId();
|
|
|
|
incrementCurrentPatchSetFieldOnly(c);
|
|
PatchSet.Id psId2 = c.currentPatchSetId();
|
|
RevCommit commit = tr.commit().message("PS2").create();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setCommit(rw, commit);
|
|
update.putApproval("Code-Review", (short) 1);
|
|
update.setChangeMessage("This is a message");
|
|
update.putComment(
|
|
Comment.Status.PUBLISHED,
|
|
newComment(
|
|
c.currentPatchSetId(),
|
|
"a.txt",
|
|
"uuid1",
|
|
new CommentRange(1, 2, 3, 4),
|
|
1,
|
|
changeOwner,
|
|
null,
|
|
TimeUtil.nowTs(),
|
|
"Comment",
|
|
(short) 1,
|
|
commit,
|
|
false));
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getPatchSets().keySet()).containsExactly(psId1, psId2);
|
|
assertThat(notes.getApprovals()).isNotEmpty();
|
|
assertThat(notes.getChangeMessages()).isNotEmpty();
|
|
assertThat(notes.getComments()).isNotEmpty();
|
|
|
|
// publish ps2
|
|
update = newUpdate(c, changeOwner);
|
|
update.setPatchSetState(PatchSetState.PUBLISHED);
|
|
update.commit();
|
|
|
|
// delete ps2
|
|
update = newUpdate(c, changeOwner);
|
|
update.setPatchSetState(PatchSetState.DELETED);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getPatchSets().keySet()).containsExactly(psId1);
|
|
assertThat(notes.getApprovals()).isEmpty();
|
|
assertThat(notes.getChangeMessages()).isEmpty();
|
|
assertThat(notes.getComments()).isEmpty();
|
|
}
|
|
|
|
@Test
|
|
public void patchSetGroups() throws Exception {
|
|
Change c = newChange();
|
|
PatchSet.Id psId1 = c.currentPatchSetId();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getPatchSets().get(psId1).groups()).isEmpty();
|
|
|
|
// ps1
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setGroups(ImmutableList.of("a", "b"));
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getPatchSets().get(psId1).groups()).containsExactly("a", "b").inOrder();
|
|
|
|
incrementCurrentPatchSetFieldOnly(c);
|
|
PatchSet.Id psId2 = c.currentPatchSetId();
|
|
update = newUpdate(c, changeOwner);
|
|
update.setCommit(rw, tr.commit().message("PS2").create());
|
|
update.setGroups(ImmutableList.of("d"));
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getPatchSets().get(psId2).groups()).containsExactly("d");
|
|
assertThat(notes.getPatchSets().get(psId1).groups()).containsExactly("a", "b").inOrder();
|
|
}
|
|
|
|
@Test
|
|
public void pushCertificate() throws Exception {
|
|
String pushCert =
|
|
"certificate version 0.1\n"
|
|
+ "pusher This is not a real push cert\n"
|
|
+ "-----BEGIN PGP SIGNATURE-----\n"
|
|
+ "Version: GnuPG v1\n"
|
|
+ "\n"
|
|
+ "Nor is this a real signature.\n"
|
|
+ "-----END PGP SIGNATURE-----\n";
|
|
|
|
// ps2 with push cert
|
|
Change c = newChange();
|
|
PatchSet.Id psId1 = c.currentPatchSetId();
|
|
incrementCurrentPatchSetFieldOnly(c);
|
|
PatchSet.Id psId2 = c.currentPatchSetId();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setPatchSetId(psId2);
|
|
RevCommit commit = tr.commit().message("PS2").create();
|
|
update.setCommit(rw, commit, pushCert);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
readNote(notes, commit);
|
|
|
|
Map<PatchSet.Id, PatchSet> patchSets = notes.getPatchSets();
|
|
assertThat(patchSets.get(psId1).pushCertificate()).isEmpty();
|
|
assertThat(patchSets.get(psId2).pushCertificate()).hasValue(pushCert);
|
|
assertThat(notes.getComments()).isEmpty();
|
|
|
|
// comment on ps2
|
|
update = newUpdate(c, changeOwner);
|
|
update.setPatchSetId(psId2);
|
|
Timestamp ts = TimeUtil.nowTs();
|
|
update.putComment(
|
|
Comment.Status.PUBLISHED,
|
|
newComment(
|
|
psId2,
|
|
"a.txt",
|
|
"uuid1",
|
|
new CommentRange(1, 2, 3, 4),
|
|
1,
|
|
changeOwner,
|
|
null,
|
|
ts,
|
|
"Comment",
|
|
(short) 1,
|
|
commit,
|
|
false));
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
|
|
patchSets = notes.getPatchSets();
|
|
assertThat(patchSets.get(psId1).pushCertificate()).isEmpty();
|
|
assertThat(patchSets.get(psId2).pushCertificate()).hasValue(pushCert);
|
|
assertThat(notes.getComments()).isNotEmpty();
|
|
}
|
|
|
|
@Test
|
|
public void emptyExceptSubject() throws Exception {
|
|
ChangeUpdate update = newUpdate(newChange(), changeOwner);
|
|
update.setSubjectForCommit("Create change");
|
|
assertThat(update.commit()).isNotNull();
|
|
}
|
|
|
|
@Test
|
|
public void multipleUpdatesInManager() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update1 = newUpdate(c, changeOwner);
|
|
update1.putApproval("Verified", (short) 1);
|
|
|
|
ChangeUpdate update2 = newUpdate(c, otherUser);
|
|
update2.putApproval("Code-Review", (short) 2);
|
|
|
|
try (NoteDbUpdateManager updateManager = updateManagerFactory.create(project)) {
|
|
updateManager.add(update1);
|
|
updateManager.add(update2);
|
|
updateManager.execute();
|
|
}
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
List<PatchSetApproval> psas = notes.getApprovals().get(c.currentPatchSetId());
|
|
assertThat(psas).hasSize(2);
|
|
|
|
assertThat(psas.get(0).accountId()).isEqualTo(changeOwner.getAccount().id());
|
|
assertThat(psas.get(0).label()).isEqualTo("Verified");
|
|
assertThat(psas.get(0).value()).isEqualTo((short) 1);
|
|
|
|
assertThat(psas.get(1).accountId()).isEqualTo(otherUser.getAccount().id());
|
|
assertThat(psas.get(1).label()).isEqualTo("Code-Review");
|
|
assertThat(psas.get(1).value()).isEqualTo((short) 2);
|
|
}
|
|
|
|
@Test
|
|
public void multipleUpdatesIncludingComments() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update1 = newUpdate(c, otherUser);
|
|
String uuid1 = "uuid1";
|
|
String message1 = "comment 1";
|
|
CommentRange range1 = new CommentRange(1, 1, 2, 1);
|
|
Timestamp time1 = TimeUtil.nowTs();
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
RevCommit tipCommit;
|
|
try (NoteDbUpdateManager updateManager = updateManagerFactory.create(project)) {
|
|
Comment comment1 =
|
|
newComment(
|
|
psId,
|
|
"file1",
|
|
uuid1,
|
|
range1,
|
|
range1.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
time1,
|
|
message1,
|
|
(short) 0,
|
|
ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"),
|
|
false);
|
|
update1.setPatchSetId(psId);
|
|
update1.putComment(Comment.Status.PUBLISHED, comment1);
|
|
updateManager.add(update1);
|
|
|
|
ChangeUpdate update2 = newUpdate(c, otherUser);
|
|
update2.putApproval("Code-Review", (short) 2);
|
|
updateManager.add(update2);
|
|
|
|
updateManager.execute();
|
|
}
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
ObjectId tip = notes.getRevision();
|
|
tipCommit = rw.parseCommit(tip);
|
|
|
|
RevCommit commitWithApprovals = tipCommit;
|
|
assertThat(commitWithApprovals).isNotNull();
|
|
RevCommit commitWithComments = commitWithApprovals.getParent(0);
|
|
assertThat(commitWithComments).isNotNull();
|
|
|
|
try (ChangeNotesRevWalk rw = ChangeNotesCommit.newRevWalk(repo)) {
|
|
ChangeNotesParser notesWithComments =
|
|
new ChangeNotesParser(
|
|
c.getId(), commitWithComments.copy(), rw, changeNoteJson, args.metrics);
|
|
ChangeNotesState state = notesWithComments.parseAll();
|
|
assertThat(state.approvals()).isEmpty();
|
|
assertThat(state.publishedComments()).hasSize(1);
|
|
}
|
|
|
|
try (ChangeNotesRevWalk rw = ChangeNotesCommit.newRevWalk(repo)) {
|
|
ChangeNotesParser notesWithApprovals =
|
|
new ChangeNotesParser(
|
|
c.getId(), commitWithApprovals.copy(), rw, changeNoteJson, args.metrics);
|
|
|
|
ChangeNotesState state = notesWithApprovals.parseAll();
|
|
assertThat(state.approvals()).hasSize(1);
|
|
assertThat(state.publishedComments()).hasSize(1);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void multipleUpdatesAcrossRefs() throws Exception {
|
|
Change c1 = newChange();
|
|
ChangeUpdate update1 = newUpdate(c1, changeOwner);
|
|
update1.putApproval("Verified", (short) 1);
|
|
|
|
Change c2 = newChange();
|
|
ChangeUpdate update2 = newUpdate(c2, otherUser);
|
|
update2.putApproval("Code-Review", (short) 2);
|
|
|
|
Ref initial1 = repo.exactRef(update1.getRefName());
|
|
assertThat(initial1).isNotNull();
|
|
Ref initial2 = repo.exactRef(update2.getRefName());
|
|
assertThat(initial2).isNotNull();
|
|
|
|
try (NoteDbUpdateManager updateManager = updateManagerFactory.create(project)) {
|
|
updateManager.add(update1);
|
|
updateManager.add(update2);
|
|
updateManager.execute();
|
|
}
|
|
|
|
Ref ref1 = repo.exactRef(update1.getRefName());
|
|
assertThat(ref1.getObjectId()).isEqualTo(update1.getResult());
|
|
assertThat(ref1.getObjectId()).isNotEqualTo(initial1.getObjectId());
|
|
Ref ref2 = repo.exactRef(update2.getRefName());
|
|
assertThat(ref2.getObjectId()).isEqualTo(update2.getResult());
|
|
assertThat(ref2.getObjectId()).isNotEqualTo(initial2.getObjectId());
|
|
|
|
PatchSetApproval approval1 =
|
|
newNotes(c1).getApprovals().get(c1.currentPatchSetId()).iterator().next();
|
|
assertThat(approval1.label()).isEqualTo("Verified");
|
|
|
|
PatchSetApproval approval2 =
|
|
newNotes(c2).getApprovals().get(c2.currentPatchSetId()).iterator().next();
|
|
assertThat(approval2.label()).isEqualTo("Code-Review");
|
|
}
|
|
|
|
@Test
|
|
public void changeMessageOnePatchSet() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewer(changeOwner.getAccount().id(), REVIEWER);
|
|
update.setChangeMessage("Just a little code change.\n");
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
ChangeMessage cm = Iterables.getOnlyElement(notes.getChangeMessages());
|
|
assertThat(cm.getMessage()).isEqualTo("Just a little code change.\n");
|
|
assertThat(cm.getAuthor()).isEqualTo(changeOwner.getAccount().id());
|
|
assertThat(cm.getPatchSetId()).isEqualTo(c.currentPatchSetId());
|
|
}
|
|
|
|
@Test
|
|
public void noChangeMessage() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewer(changeOwner.getAccount().id(), REVIEWER);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getChangeMessages()).isEmpty();
|
|
}
|
|
|
|
@Test
|
|
public void changeMessageWithTrailingDoubleNewline() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setChangeMessage("Testing trailing double newline\n\n");
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
ChangeMessage cm1 = Iterables.getOnlyElement(notes.getChangeMessages());
|
|
assertThat(cm1.getMessage()).isEqualTo("Testing trailing double newline\n\n");
|
|
assertThat(cm1.getAuthor()).isEqualTo(changeOwner.getAccount().id());
|
|
}
|
|
|
|
@Test
|
|
public void changeMessageWithMultipleParagraphs() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setChangeMessage("Testing paragraph 1\n\nTesting paragraph 2\n\nTesting paragraph 3");
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
ChangeMessage cm1 = Iterables.getOnlyElement(notes.getChangeMessages());
|
|
assertThat(cm1.getMessage())
|
|
.isEqualTo(
|
|
"Testing paragraph 1\n"
|
|
+ "\n"
|
|
+ "Testing paragraph 2\n"
|
|
+ "\n"
|
|
+ "Testing paragraph 3");
|
|
assertThat(cm1.getAuthor()).isEqualTo(changeOwner.getAccount().id());
|
|
}
|
|
|
|
@Test
|
|
public void changeMessagesMultiplePatchSets() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewer(changeOwner.getAccount().id(), REVIEWER);
|
|
update.setChangeMessage("This is the change message for the first PS.");
|
|
update.commit();
|
|
PatchSet.Id ps1 = c.currentPatchSetId();
|
|
|
|
incrementPatchSet(c);
|
|
update = newUpdate(c, changeOwner);
|
|
|
|
update.setChangeMessage("This is the change message for the second PS.");
|
|
update.commit();
|
|
PatchSet.Id ps2 = c.currentPatchSetId();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getChangeMessages()).hasSize(2);
|
|
|
|
ChangeMessage cm1 = notes.getChangeMessages().get(0);
|
|
assertThat(cm1.getPatchSetId()).isEqualTo(ps1);
|
|
assertThat(cm1.getMessage()).isEqualTo("This is the change message for the first PS.");
|
|
assertThat(cm1.getAuthor()).isEqualTo(changeOwner.getAccount().id());
|
|
|
|
ChangeMessage cm2 = notes.getChangeMessages().get(1);
|
|
assertThat(cm2.getPatchSetId()).isEqualTo(ps2);
|
|
assertThat(cm2.getMessage()).isEqualTo("This is the change message for the second PS.");
|
|
assertThat(cm2.getAuthor()).isEqualTo(changeOwner.getAccount().id());
|
|
assertThat(cm2.getPatchSetId()).isEqualTo(ps2);
|
|
}
|
|
|
|
@Test
|
|
public void changeMessageMultipleInOnePatchSet() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewer(changeOwner.getAccount().id(), REVIEWER);
|
|
update.setChangeMessage("First change message.\n");
|
|
update.commit();
|
|
|
|
PatchSet.Id ps1 = c.currentPatchSetId();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putReviewer(changeOwner.getAccount().id(), REVIEWER);
|
|
update.setChangeMessage("Second change message.\n");
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
|
|
List<ChangeMessage> cm = notes.getChangeMessages();
|
|
assertThat(cm).hasSize(2);
|
|
assertThat(cm.get(0).getMessage()).isEqualTo("First change message.\n");
|
|
assertThat(cm.get(0).getAuthor()).isEqualTo(changeOwner.getAccount().id());
|
|
assertThat(cm.get(0).getPatchSetId()).isEqualTo(ps1);
|
|
assertThat(cm.get(1).getMessage()).isEqualTo("Second change message.\n");
|
|
assertThat(cm.get(1).getAuthor()).isEqualTo(changeOwner.getAccount().id());
|
|
assertThat(cm.get(1).getPatchSetId()).isEqualTo(ps1);
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentsFileComment() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
|
|
Comment comment =
|
|
newComment(
|
|
psId,
|
|
"file1",
|
|
"uuid",
|
|
null,
|
|
0,
|
|
otherUser,
|
|
null,
|
|
TimeUtil.nowTs(),
|
|
"message",
|
|
(short) 1,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentsZeroColumns() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
CommentRange range = new CommentRange(1, 0, 2, 0);
|
|
|
|
Comment comment =
|
|
newComment(
|
|
psId,
|
|
"file1",
|
|
"uuid",
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
TimeUtil.nowTs(),
|
|
"message",
|
|
(short) 1,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentZeroRange() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
CommentRange range = new CommentRange(0, 0, 0, 0);
|
|
|
|
Comment comment =
|
|
newComment(
|
|
psId,
|
|
"file",
|
|
"uuid",
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
TimeUtil.nowTs(),
|
|
"message",
|
|
(short) 1,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentEmptyFilename() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
CommentRange range = new CommentRange(1, 2, 3, 4);
|
|
|
|
Comment comment =
|
|
newComment(
|
|
psId,
|
|
"",
|
|
"uuid",
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
TimeUtil.nowTs(),
|
|
"message",
|
|
(short) 1,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentNotesFormatMultiplePatchSetsSameCommitId() throws Exception {
|
|
Change c = newChange();
|
|
PatchSet.Id psId1 = c.currentPatchSetId();
|
|
incrementPatchSet(c);
|
|
PatchSet.Id psId2 = c.currentPatchSetId();
|
|
String uuid1 = "uuid1";
|
|
String uuid2 = "uuid2";
|
|
String uuid3 = "uuid3";
|
|
String message1 = "comment 1";
|
|
String message2 = "comment 2";
|
|
String message3 = "comment 3";
|
|
CommentRange range1 = new CommentRange(1, 1, 2, 1);
|
|
CommentRange range2 = new CommentRange(2, 1, 3, 1);
|
|
Timestamp time = TimeUtil.nowTs();
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
|
|
Comment comment1 =
|
|
newComment(
|
|
psId1,
|
|
"file1",
|
|
uuid1,
|
|
range1,
|
|
range1.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
time,
|
|
message1,
|
|
(short) 0,
|
|
commitId,
|
|
false);
|
|
Comment comment2 =
|
|
newComment(
|
|
psId1,
|
|
"file1",
|
|
uuid2,
|
|
range2,
|
|
range2.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
time,
|
|
message2,
|
|
(short) 0,
|
|
commitId,
|
|
false);
|
|
Comment comment3 =
|
|
newComment(
|
|
psId2,
|
|
"file1",
|
|
uuid3,
|
|
range1,
|
|
range1.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
time,
|
|
message3,
|
|
(short) 0,
|
|
commitId,
|
|
false);
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(psId2);
|
|
update.putComment(Comment.Status.PUBLISHED, comment3);
|
|
update.putComment(Comment.Status.PUBLISHED, comment2);
|
|
update.putComment(Comment.Status.PUBLISHED, comment1);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getComments())
|
|
.isEqualTo(
|
|
ImmutableListMultimap.of(
|
|
commitId, comment1,
|
|
commitId, comment2,
|
|
commitId, comment3));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentNotesFormatRealAuthor() throws Exception {
|
|
Change c = newChange();
|
|
CurrentUser ownerAsOtherUser = userFactory.runAs(null, otherUserId, changeOwner);
|
|
ChangeUpdate update = newUpdate(c, ownerAsOtherUser);
|
|
String uuid = "uuid";
|
|
String message = "comment";
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
Timestamp time = TimeUtil.nowTs();
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
|
|
Comment comment =
|
|
newComment(
|
|
psId,
|
|
"file",
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
time,
|
|
message,
|
|
(short) 1,
|
|
commitId,
|
|
false);
|
|
comment.setRealAuthor(changeOwner.getAccountId());
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
|
|
assertThat(notes.getComments()).isEqualTo(ImmutableListMultimap.of(commitId, comment));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentNotesFormatWeirdUser() throws Exception {
|
|
Account.Builder account = Account.builder(Account.id(3), TimeUtil.nowTs());
|
|
account.setFullName("Weird\n\u0002<User>\n");
|
|
account.setPreferredEmail(" we\r\nird@ex>ample<.com");
|
|
accountCache.put(account.build());
|
|
IdentifiedUser user = userFactory.create(Account.id(3));
|
|
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, user);
|
|
String uuid = "uuid";
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
Timestamp time = TimeUtil.nowTs();
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
|
|
Comment comment =
|
|
newComment(
|
|
psId,
|
|
"file1",
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
user,
|
|
null,
|
|
time,
|
|
"comment",
|
|
(short) 1,
|
|
ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"),
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
|
|
assertThat(notes.getComments())
|
|
.isEqualTo(ImmutableListMultimap.of(comment.getCommitId(), comment));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentMultipleOnePatchsetOneFileBothSides() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
String uuid1 = "uuid1";
|
|
String uuid2 = "uuid2";
|
|
ObjectId commitId1 = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
ObjectId commitId2 = ObjectId.fromString("abcd4567abcd4567abcd4567abcd4567abcd4567");
|
|
String messageForBase = "comment for base";
|
|
String messageForPS = "comment for ps";
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
Timestamp now = TimeUtil.nowTs();
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
|
|
Comment commentForBase =
|
|
newComment(
|
|
psId,
|
|
"filename",
|
|
uuid1,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
messageForBase,
|
|
(short) 0,
|
|
commitId1,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, commentForBase);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
Comment commentForPS =
|
|
newComment(
|
|
psId,
|
|
"filename",
|
|
uuid2,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
messageForPS,
|
|
(short) 1,
|
|
commitId2,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, commentForPS);
|
|
update.commit();
|
|
|
|
assertThat(newNotes(c).getComments())
|
|
.containsExactlyEntriesIn(
|
|
ImmutableListMultimap.of(
|
|
commitId1, commentForBase,
|
|
commitId2, commentForPS));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentMultipleOnePatchsetOneFile() throws Exception {
|
|
Change c = newChange();
|
|
String uuid1 = "uuid1";
|
|
String uuid2 = "uuid2";
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
String filename = "filename";
|
|
short side = (short) 1;
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
Timestamp timeForComment1 = TimeUtil.nowTs();
|
|
Timestamp timeForComment2 = TimeUtil.nowTs();
|
|
Comment comment1 =
|
|
newComment(
|
|
psId,
|
|
filename,
|
|
uuid1,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
timeForComment1,
|
|
"comment 1",
|
|
side,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment1);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
Comment comment2 =
|
|
newComment(
|
|
psId,
|
|
filename,
|
|
uuid2,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
timeForComment2,
|
|
"comment 2",
|
|
side,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment2);
|
|
update.commit();
|
|
|
|
assertThat(newNotes(c).getComments())
|
|
.containsExactlyEntriesIn(
|
|
ImmutableListMultimap.of(
|
|
commitId, comment1,
|
|
commitId, comment2))
|
|
.inOrder();
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentMultipleOnePatchsetMultipleFiles() throws Exception {
|
|
Change c = newChange();
|
|
String uuid = "uuid";
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
String filename1 = "filename1";
|
|
String filename2 = "filename2";
|
|
short side = (short) 1;
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
Timestamp now = TimeUtil.nowTs();
|
|
Comment comment1 =
|
|
newComment(
|
|
psId,
|
|
filename1,
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment 1",
|
|
side,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment1);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
Comment comment2 =
|
|
newComment(
|
|
psId,
|
|
filename2,
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment 2",
|
|
side,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment2);
|
|
update.commit();
|
|
|
|
assertThat(newNotes(c).getComments())
|
|
.containsExactlyEntriesIn(
|
|
ImmutableListMultimap.of(
|
|
commitId, comment1,
|
|
commitId, comment2))
|
|
.inOrder();
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentMultiplePatchsets() throws Exception {
|
|
Change c = newChange();
|
|
String uuid = "uuid";
|
|
ObjectId commitId1 = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
ObjectId commitId2 = ObjectId.fromString("abcd4567abcd4567abcd4567abcd4567abcd4567");
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
PatchSet.Id ps1 = c.currentPatchSetId();
|
|
String filename = "filename1";
|
|
short side = (short) 1;
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
Timestamp now = TimeUtil.nowTs();
|
|
Comment comment1 =
|
|
newComment(
|
|
ps1,
|
|
filename,
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps1",
|
|
side,
|
|
commitId1,
|
|
false);
|
|
update.setPatchSetId(ps1);
|
|
update.putComment(Comment.Status.PUBLISHED, comment1);
|
|
update.commit();
|
|
|
|
incrementPatchSet(c);
|
|
PatchSet.Id ps2 = c.currentPatchSetId();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
now = TimeUtil.nowTs();
|
|
Comment comment2 =
|
|
newComment(
|
|
ps2,
|
|
filename,
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps2",
|
|
side,
|
|
commitId2,
|
|
false);
|
|
update.setPatchSetId(ps2);
|
|
update.putComment(Comment.Status.PUBLISHED, comment2);
|
|
update.commit();
|
|
|
|
assertThat(newNotes(c).getComments())
|
|
.containsExactlyEntriesIn(
|
|
ImmutableListMultimap.of(
|
|
commitId1, comment1,
|
|
commitId2, comment2));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentSingleDraftToPublished() throws Exception {
|
|
Change c = newChange();
|
|
String uuid = "uuid";
|
|
ObjectId commitId = ObjectId.fromString("abcd4567abcd4567abcd4567abcd4567abcd4567");
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
PatchSet.Id ps1 = c.currentPatchSetId();
|
|
String filename = "filename1";
|
|
short side = (short) 1;
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
Timestamp now = TimeUtil.nowTs();
|
|
Comment comment1 =
|
|
newComment(
|
|
ps1,
|
|
filename,
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps1",
|
|
side,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(ps1);
|
|
update.putComment(Comment.Status.DRAFT, comment1);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId))
|
|
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment1));
|
|
assertThat(notes.getComments()).isEmpty();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(ps1);
|
|
update.putComment(Comment.Status.PUBLISHED, comment1);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId)).isEmpty();
|
|
assertThat(notes.getComments())
|
|
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment1));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentMultipleDraftsSameSidePublishOne() throws Exception {
|
|
Change c = newChange();
|
|
String uuid1 = "uuid1";
|
|
String uuid2 = "uuid2";
|
|
ObjectId commitId = ObjectId.fromString("abcd4567abcd4567abcd4567abcd4567abcd4567");
|
|
CommentRange range1 = new CommentRange(1, 1, 2, 2);
|
|
CommentRange range2 = new CommentRange(2, 2, 3, 3);
|
|
String filename = "filename1";
|
|
short side = (short) 1;
|
|
Timestamp now = TimeUtil.nowTs();
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
|
|
// Write two drafts on the same side of one patch set.
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(psId);
|
|
Comment comment1 =
|
|
newComment(
|
|
psId,
|
|
filename,
|
|
uuid1,
|
|
range1,
|
|
range1.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps1",
|
|
side,
|
|
commitId,
|
|
false);
|
|
Comment comment2 =
|
|
newComment(
|
|
psId,
|
|
filename,
|
|
uuid2,
|
|
range2,
|
|
range2.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"other on ps1",
|
|
side,
|
|
commitId,
|
|
false);
|
|
update.putComment(Comment.Status.DRAFT, comment1);
|
|
update.putComment(Comment.Status.DRAFT, comment2);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId))
|
|
.containsExactlyEntriesIn(
|
|
ImmutableListMultimap.of(
|
|
commitId, comment1,
|
|
commitId, comment2))
|
|
.inOrder();
|
|
assertThat(notes.getComments()).isEmpty();
|
|
|
|
// Publish first draft.
|
|
update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment1);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId))
|
|
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment2));
|
|
assertThat(notes.getComments())
|
|
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment1));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentsMultipleDraftsBothSidesPublishAll() throws Exception {
|
|
Change c = newChange();
|
|
String uuid1 = "uuid1";
|
|
String uuid2 = "uuid2";
|
|
ObjectId commitId1 = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
ObjectId commitId2 = ObjectId.fromString("abcd4567abcd4567abcd4567abcd4567abcd4567");
|
|
CommentRange range1 = new CommentRange(1, 1, 2, 2);
|
|
CommentRange range2 = new CommentRange(2, 2, 3, 3);
|
|
String filename = "filename1";
|
|
Timestamp now = TimeUtil.nowTs();
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
|
|
// Write two drafts, one on each side of the patchset.
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(psId);
|
|
Comment baseComment =
|
|
newComment(
|
|
psId,
|
|
filename,
|
|
uuid1,
|
|
range1,
|
|
range1.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on base",
|
|
(short) 0,
|
|
commitId1,
|
|
false);
|
|
Comment psComment =
|
|
newComment(
|
|
psId,
|
|
filename,
|
|
uuid2,
|
|
range2,
|
|
range2.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps",
|
|
(short) 1,
|
|
commitId2,
|
|
false);
|
|
|
|
update.putComment(Comment.Status.DRAFT, baseComment);
|
|
update.putComment(Comment.Status.DRAFT, psComment);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId))
|
|
.containsExactlyEntriesIn(
|
|
ImmutableListMultimap.of(
|
|
commitId1, baseComment,
|
|
commitId2, psComment));
|
|
assertThat(notes.getComments()).isEmpty();
|
|
|
|
// Publish both comments.
|
|
update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(psId);
|
|
|
|
update.putComment(Comment.Status.PUBLISHED, baseComment);
|
|
update.putComment(Comment.Status.PUBLISHED, psComment);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId)).isEmpty();
|
|
assertThat(notes.getComments())
|
|
.containsExactlyEntriesIn(
|
|
ImmutableListMultimap.of(
|
|
commitId1, baseComment,
|
|
commitId2, psComment));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentsDeleteAllDrafts() throws Exception {
|
|
Change c = newChange();
|
|
String uuid = "uuid";
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
String filename = "filename";
|
|
short side = (short) 1;
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
Timestamp now = TimeUtil.nowTs();
|
|
Comment comment =
|
|
newComment(
|
|
psId,
|
|
filename,
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps1",
|
|
side,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.DRAFT, comment);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId)).hasSize(1);
|
|
assertThat(notes.getDraftCommentNotes().getNoteMap().contains(commitId)).isTrue();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(psId);
|
|
update.deleteComment(comment);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId)).isEmpty();
|
|
assertThat(notes.getDraftCommentNotes().getNoteMap()).isNull();
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentsDeleteAllDraftsForOneRevision() throws Exception {
|
|
Change c = newChange();
|
|
String uuid = "uuid";
|
|
ObjectId commitId1 = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
ObjectId commitId2 = ObjectId.fromString("abcd4567abcd4567abcd4567abcd4567abcd4567");
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
PatchSet.Id ps1 = c.currentPatchSetId();
|
|
String filename = "filename1";
|
|
short side = (short) 1;
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
Timestamp now = TimeUtil.nowTs();
|
|
Comment comment1 =
|
|
newComment(
|
|
ps1,
|
|
filename,
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps1",
|
|
side,
|
|
commitId1,
|
|
false);
|
|
update.setPatchSetId(ps1);
|
|
update.putComment(Comment.Status.DRAFT, comment1);
|
|
update.commit();
|
|
|
|
incrementPatchSet(c);
|
|
PatchSet.Id ps2 = c.currentPatchSetId();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
now = TimeUtil.nowTs();
|
|
Comment comment2 =
|
|
newComment(
|
|
ps2,
|
|
filename,
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps2",
|
|
side,
|
|
commitId2,
|
|
false);
|
|
update.setPatchSetId(ps2);
|
|
update.putComment(Comment.Status.DRAFT, comment2);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId)).hasSize(2);
|
|
|
|
update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(ps2);
|
|
update.deleteComment(comment2);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId)).hasSize(1);
|
|
NoteMap noteMap = notes.getDraftCommentNotes().getNoteMap();
|
|
assertThat(noteMap.contains(commitId1)).isTrue();
|
|
assertThat(noteMap.contains(commitId2)).isFalse();
|
|
}
|
|
|
|
@Test
|
|
public void addingPublishedCommentDoesNotCreateNoOpCommitOnEmptyDraftRef() throws Exception {
|
|
Change c = newChange();
|
|
String uuid = "uuid";
|
|
ObjectId commitId = ObjectId.fromString("abcd4567abcd4567abcd4567abcd4567abcd4567");
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
PatchSet.Id ps1 = c.currentPatchSetId();
|
|
String filename = "filename1";
|
|
short side = (short) 1;
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
Timestamp now = TimeUtil.nowTs();
|
|
Comment comment =
|
|
newComment(
|
|
ps1,
|
|
filename,
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps1",
|
|
side,
|
|
commitId,
|
|
false);
|
|
update.putComment(Comment.Status.PUBLISHED, comment);
|
|
update.commit();
|
|
|
|
assertThat(repo.exactRef(changeMetaRef(c.getId()))).isNotNull();
|
|
String draftRef = refsDraftComments(c.getId(), otherUser.getAccountId());
|
|
assertThat(exactRefAllUsers(draftRef)).isNull();
|
|
}
|
|
|
|
@Test
|
|
public void addingPublishedCommentDoesNotCreateNoOpCommitOnNonEmptyDraftRef() throws Exception {
|
|
Change c = newChange();
|
|
ObjectId commitId = ObjectId.fromString("abcd4567abcd4567abcd4567abcd4567abcd4567");
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
PatchSet.Id ps1 = c.currentPatchSetId();
|
|
String filename = "filename1";
|
|
short side = (short) 1;
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
Timestamp now = TimeUtil.nowTs();
|
|
Comment draft =
|
|
newComment(
|
|
ps1,
|
|
filename,
|
|
"uuid1",
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"draft comment on ps1",
|
|
side,
|
|
commitId,
|
|
false);
|
|
update.putComment(Comment.Status.DRAFT, draft);
|
|
update.commit();
|
|
|
|
String draftRef = refsDraftComments(c.getId(), otherUser.getAccountId());
|
|
ObjectId old = exactRefAllUsers(draftRef);
|
|
assertThat(old).isNotNull();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
Comment pub =
|
|
newComment(
|
|
ps1,
|
|
filename,
|
|
"uuid2",
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps1",
|
|
side,
|
|
commitId,
|
|
false);
|
|
update.putComment(Comment.Status.PUBLISHED, pub);
|
|
update.commit();
|
|
|
|
assertThat(exactRefAllUsers(draftRef)).isEqualTo(old);
|
|
}
|
|
|
|
@Test
|
|
public void fileComment() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
String uuid = "uuid";
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
String messageForBase = "comment for base";
|
|
Timestamp now = TimeUtil.nowTs();
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
|
|
Comment comment =
|
|
newComment(
|
|
psId,
|
|
"filename",
|
|
uuid,
|
|
null,
|
|
0,
|
|
otherUser,
|
|
null,
|
|
now,
|
|
messageForBase,
|
|
(short) 0,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment);
|
|
update.commit();
|
|
|
|
assertThat(newNotes(c).getComments())
|
|
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment));
|
|
}
|
|
|
|
@Test
|
|
public void patchLineCommentNoRange() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
String uuid = "uuid";
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
String messageForBase = "comment for base";
|
|
Timestamp now = TimeUtil.nowTs();
|
|
PatchSet.Id psId = c.currentPatchSetId();
|
|
|
|
Comment comment =
|
|
newComment(
|
|
psId,
|
|
"filename",
|
|
uuid,
|
|
null,
|
|
1,
|
|
otherUser,
|
|
null,
|
|
now,
|
|
messageForBase,
|
|
(short) 0,
|
|
commitId,
|
|
false);
|
|
update.setPatchSetId(psId);
|
|
update.putComment(Comment.Status.PUBLISHED, comment);
|
|
update.commit();
|
|
|
|
assertThat(newNotes(c).getComments())
|
|
.containsExactlyEntriesIn(ImmutableListMultimap.of(commitId, comment));
|
|
}
|
|
|
|
@Test
|
|
public void putCommentsForMultipleRevisions() throws Exception {
|
|
Change c = newChange();
|
|
String uuid = "uuid";
|
|
ObjectId commitId1 = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
ObjectId commitId2 = ObjectId.fromString("abcd4567abcd4567abcd4567abcd4567abcd4567");
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
PatchSet.Id ps1 = c.currentPatchSetId();
|
|
String filename = "filename1";
|
|
short side = (short) 1;
|
|
|
|
incrementPatchSet(c);
|
|
PatchSet.Id ps2 = c.currentPatchSetId();
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(ps2);
|
|
Timestamp now = TimeUtil.nowTs();
|
|
Comment comment1 =
|
|
newComment(
|
|
ps1,
|
|
filename,
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps1",
|
|
side,
|
|
commitId1,
|
|
false);
|
|
Comment comment2 =
|
|
newComment(
|
|
ps2,
|
|
filename,
|
|
uuid,
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps2",
|
|
side,
|
|
commitId2,
|
|
false);
|
|
update.putComment(Comment.Status.DRAFT, comment1);
|
|
update.putComment(Comment.Status.DRAFT, comment2);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId)).hasSize(2);
|
|
assertThat(notes.getComments()).isEmpty();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(ps2);
|
|
update.putComment(Comment.Status.PUBLISHED, comment1);
|
|
update.putComment(Comment.Status.PUBLISHED, comment2);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId)).isEmpty();
|
|
assertThat(notes.getComments()).hasSize(2);
|
|
}
|
|
|
|
@Test
|
|
public void publishSubsetOfCommentsOnRevision() throws Exception {
|
|
Change c = newChange();
|
|
ObjectId commitId1 = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
PatchSet.Id ps1 = c.currentPatchSetId();
|
|
short side = (short) 1;
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(ps1);
|
|
Timestamp now = TimeUtil.nowTs();
|
|
Comment comment1 =
|
|
newComment(
|
|
ps1,
|
|
"file1",
|
|
"uuid1",
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment1",
|
|
side,
|
|
commitId1,
|
|
false);
|
|
Comment comment2 =
|
|
newComment(
|
|
ps1,
|
|
"file2",
|
|
"uuid2",
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment2",
|
|
side,
|
|
commitId1,
|
|
false);
|
|
update.putComment(Comment.Status.DRAFT, comment1);
|
|
update.putComment(Comment.Status.DRAFT, comment2);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId).get(commitId1))
|
|
.containsExactly(comment1, comment2);
|
|
assertThat(notes.getComments()).isEmpty();
|
|
|
|
update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(ps1);
|
|
update.putComment(Comment.Status.PUBLISHED, comment2);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId).get(commitId1)).containsExactly(comment1);
|
|
assertThat(notes.getComments().get(commitId1)).containsExactly(comment2);
|
|
}
|
|
|
|
@Test
|
|
public void updateWithServerIdent() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, internalUser);
|
|
update.setChangeMessage("A message.");
|
|
update.commit();
|
|
|
|
ChangeMessage msg = Iterables.getLast(newNotes(c).getChangeMessages());
|
|
assertThat(msg.getMessage()).isEqualTo("A message.");
|
|
assertThat(msg.getAuthor()).isNull();
|
|
|
|
ChangeUpdate failingUpdate = newUpdate(c, internalUser);
|
|
assertThrows(
|
|
IllegalStateException.class, () -> failingUpdate.putApproval("Code-Review", (short) 1));
|
|
}
|
|
|
|
@Test
|
|
public void filterOutAndFixUpZombieDraftComments() throws Exception {
|
|
Change c = newChange();
|
|
ObjectId commitId1 = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
PatchSet.Id ps1 = c.currentPatchSetId();
|
|
short side = (short) 1;
|
|
|
|
ChangeUpdate update = newUpdate(c, otherUser);
|
|
Timestamp now = TimeUtil.nowTs();
|
|
Comment comment1 =
|
|
newComment(
|
|
ps1,
|
|
"file1",
|
|
"uuid1",
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"comment on ps1",
|
|
side,
|
|
commitId1,
|
|
false);
|
|
Comment comment2 =
|
|
newComment(
|
|
ps1,
|
|
"file2",
|
|
"uuid2",
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
now,
|
|
"another comment",
|
|
side,
|
|
commitId1,
|
|
false);
|
|
update.putComment(Comment.Status.DRAFT, comment1);
|
|
update.putComment(Comment.Status.DRAFT, comment2);
|
|
update.commit();
|
|
|
|
String refName = refsDraftComments(c.getId(), otherUserId);
|
|
ObjectId oldDraftId = exactRefAllUsers(refName);
|
|
|
|
update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(ps1);
|
|
update.putComment(Comment.Status.PUBLISHED, comment2);
|
|
update.commit();
|
|
assertThat(exactRefAllUsers(refName)).isNotNull();
|
|
assertThat(exactRefAllUsers(refName)).isNotEqualTo(oldDraftId);
|
|
|
|
// Re-add draft version of comment2 back to draft ref without updating
|
|
// change ref. Simulates the case where deleting the draft failed
|
|
// non-atomically after adding the published comment succeeded.
|
|
ChangeDraftUpdate draftUpdate = newUpdate(c, otherUser).createDraftUpdateIfNull();
|
|
draftUpdate.putComment(comment2);
|
|
try (NoteDbUpdateManager manager = updateManagerFactory.create(c.getProject())) {
|
|
manager.add(draftUpdate);
|
|
manager.execute();
|
|
}
|
|
|
|
// Looking at drafts directly shows the zombie comment.
|
|
DraftCommentNotes draftNotes = draftNotesFactory.create(c.getId(), otherUserId);
|
|
assertThat(draftNotes.load().getComments().get(commitId1)).containsExactly(comment1, comment2);
|
|
|
|
// Zombie comment is filtered out of drafts via ChangeNotes.
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getDraftComments(otherUserId).get(commitId1)).containsExactly(comment1);
|
|
assertThat(notes.getComments().get(commitId1)).containsExactly(comment2);
|
|
|
|
update = newUpdate(c, otherUser);
|
|
update.setPatchSetId(ps1);
|
|
update.putComment(Comment.Status.PUBLISHED, comment1);
|
|
update.commit();
|
|
|
|
// Updating an unrelated comment causes the zombie comment to get fixed up.
|
|
assertThat(exactRefAllUsers(refName)).isNull();
|
|
}
|
|
|
|
@Test
|
|
public void updateCommentsInSequentialUpdates() throws Exception {
|
|
Change c = newChange();
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
ObjectId commitId = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
|
|
|
|
ChangeUpdate update1 = newUpdate(c, otherUser);
|
|
Comment comment1 =
|
|
newComment(
|
|
c.currentPatchSetId(),
|
|
"filename",
|
|
"uuid1",
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
new Timestamp(update1.getWhen().getTime()),
|
|
"comment 1",
|
|
(short) 1,
|
|
commitId,
|
|
false);
|
|
update1.putComment(Comment.Status.PUBLISHED, comment1);
|
|
|
|
ChangeUpdate update2 = newUpdate(c, otherUser);
|
|
Comment comment2 =
|
|
newComment(
|
|
c.currentPatchSetId(),
|
|
"filename",
|
|
"uuid2",
|
|
range,
|
|
range.getEndLine(),
|
|
otherUser,
|
|
null,
|
|
new Timestamp(update2.getWhen().getTime()),
|
|
"comment 2",
|
|
(short) 1,
|
|
commitId,
|
|
false);
|
|
update2.putComment(Comment.Status.PUBLISHED, comment2);
|
|
|
|
try (NoteDbUpdateManager manager = updateManagerFactory.create(project)) {
|
|
manager.add(update1);
|
|
manager.add(update2);
|
|
manager.execute();
|
|
}
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
List<Comment> comments = notes.getComments().get(commitId);
|
|
assertThat(comments).hasSize(2);
|
|
assertThat(comments.get(0).message).isEqualTo("comment 1");
|
|
assertThat(comments.get(1).message).isEqualTo("comment 2");
|
|
}
|
|
|
|
@Test
|
|
public void realUser() throws Exception {
|
|
Change c = newChange();
|
|
CurrentUser ownerAsOtherUser = userFactory.runAs(null, otherUserId, changeOwner);
|
|
ChangeUpdate update = newUpdate(c, ownerAsOtherUser);
|
|
update.setChangeMessage("Message on behalf of other user");
|
|
update.commit();
|
|
|
|
ChangeMessage msg = Iterables.getLast(newNotes(c).getChangeMessages());
|
|
assertThat(msg.getMessage()).isEqualTo("Message on behalf of other user");
|
|
assertThat(msg.getAuthor()).isEqualTo(otherUserId);
|
|
assertThat(msg.getRealAuthor()).isEqualTo(changeOwner.getAccountId());
|
|
}
|
|
|
|
@Test
|
|
public void ignoreEntitiesBeyondCurrentPatchSet() throws Exception {
|
|
Change c = newChange();
|
|
ChangeNotes notes = newNotes(c);
|
|
int numMessages = notes.getChangeMessages().size();
|
|
int numPatchSets = notes.getPatchSets().size();
|
|
int numApprovals = notes.getApprovals().size();
|
|
int numComments = notes.getComments().size();
|
|
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setPatchSetId(PatchSet.id(c.getId(), c.currentPatchSetId().get() + 1));
|
|
update.setChangeMessage("Should be ignored");
|
|
update.putApproval("Code-Review", (short) 2);
|
|
CommentRange range = new CommentRange(1, 1, 2, 1);
|
|
Comment comment =
|
|
newComment(
|
|
update.getPatchSetId(),
|
|
"filename",
|
|
"uuid",
|
|
range,
|
|
range.getEndLine(),
|
|
changeOwner,
|
|
null,
|
|
new Timestamp(update.getWhen().getTime()),
|
|
"comment",
|
|
(short) 1,
|
|
ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"),
|
|
false);
|
|
update.putComment(Comment.Status.PUBLISHED, comment);
|
|
update.commit();
|
|
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChangeMessages()).hasSize(numMessages);
|
|
assertThat(notes.getPatchSets()).hasSize(numPatchSets);
|
|
assertThat(notes.getApprovals()).hasSize(numApprovals);
|
|
assertThat(notes.getComments()).hasSize(numComments);
|
|
}
|
|
|
|
@Test
|
|
public void currentPatchSet() throws Exception {
|
|
Change c = newChange();
|
|
assertThat(newNotes(c).getChange().currentPatchSetId().get()).isEqualTo(1);
|
|
|
|
incrementPatchSet(c);
|
|
assertThat(newNotes(c).getChange().currentPatchSetId().get()).isEqualTo(2);
|
|
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setPatchSetId(PatchSet.id(c.getId(), 1));
|
|
update.setCurrentPatchSet();
|
|
update.commit();
|
|
assertThat(newNotes(c).getChange().currentPatchSetId().get()).isEqualTo(1);
|
|
|
|
incrementPatchSet(c);
|
|
assertThat(newNotes(c).getChange().currentPatchSetId().get()).isEqualTo(3);
|
|
|
|
// Delete PS3, PS1 becomes current, as the most recent event explicitly set
|
|
// it to current.
|
|
update = newUpdate(c, changeOwner);
|
|
update.setPatchSetState(PatchSetState.DELETED);
|
|
update.commit();
|
|
assertThat(newNotes(c).getChange().currentPatchSetId().get()).isEqualTo(1);
|
|
|
|
// Delete PS1, PS2 becomes current.
|
|
update = newUpdate(c, changeOwner);
|
|
update.setPatchSetId(PatchSet.id(c.getId(), 1));
|
|
update.setPatchSetState(PatchSetState.DELETED);
|
|
update.commit();
|
|
assertThat(newNotes(c).getChange().currentPatchSetId().get()).isEqualTo(2);
|
|
}
|
|
|
|
@Test
|
|
public void privateDefault() throws Exception {
|
|
Change c = newChange();
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getChange().isPrivate()).isFalse();
|
|
}
|
|
|
|
@Test
|
|
public void privateSetPrivate() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setPrivate(true);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getChange().isPrivate()).isTrue();
|
|
}
|
|
|
|
@Test
|
|
public void privateSetPrivateMultipleTimes() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setPrivate(true);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setPrivate(false);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getChange().isPrivate()).isFalse();
|
|
}
|
|
|
|
@Test
|
|
public void defaultReviewersByEmailIsEmpty() throws Exception {
|
|
Change c = newChange();
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getReviewersByEmail().all()).isEmpty();
|
|
}
|
|
|
|
@Test
|
|
public void putReviewerByEmail() throws Exception {
|
|
Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
|
|
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewerByEmail(adr, ReviewerStateInternal.REVIEWER);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getReviewersByEmail().all()).containsExactly(adr);
|
|
}
|
|
|
|
@Test
|
|
public void putAndRemoveReviewerByEmail() throws Exception {
|
|
Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
|
|
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewerByEmail(adr, ReviewerStateInternal.REVIEWER);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.removeReviewerByEmail(adr);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getReviewersByEmail().all()).isEmpty();
|
|
}
|
|
|
|
@Test
|
|
public void putRemoveAndAddBackReviewerByEmail() throws Exception {
|
|
Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
|
|
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewerByEmail(adr, ReviewerStateInternal.REVIEWER);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.removeReviewerByEmail(adr);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putReviewerByEmail(adr, ReviewerStateInternal.CC);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getReviewersByEmail().all()).containsExactly(adr);
|
|
}
|
|
|
|
@Test
|
|
public void putReviewerByEmailAndCcByEmail() throws Exception {
|
|
Address adrReviewer = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
|
|
Address adrCc = new Address("Foo Bor", "foo.bar.2@gerritcodereview.com");
|
|
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewerByEmail(adrReviewer, ReviewerStateInternal.REVIEWER);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putReviewerByEmail(adrCc, ReviewerStateInternal.CC);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getReviewersByEmail().byState(ReviewerStateInternal.REVIEWER))
|
|
.containsExactly(adrReviewer);
|
|
assertThat(notes.getReviewersByEmail().byState(ReviewerStateInternal.CC))
|
|
.containsExactly(adrCc);
|
|
assertThat(notes.getReviewersByEmail().all()).containsExactly(adrReviewer, adrCc);
|
|
}
|
|
|
|
@Test
|
|
public void putReviewerByEmailAndChangeToCc() throws Exception {
|
|
Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
|
|
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewerByEmail(adr, ReviewerStateInternal.REVIEWER);
|
|
update.commit();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putReviewerByEmail(adr, ReviewerStateInternal.CC);
|
|
update.commit();
|
|
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getReviewersByEmail().byState(ReviewerStateInternal.REVIEWER)).isEmpty();
|
|
assertThat(notes.getReviewersByEmail().byState(ReviewerStateInternal.CC)).containsExactly(adr);
|
|
assertThat(notes.getReviewersByEmail().all()).containsExactly(adr);
|
|
}
|
|
|
|
@Test
|
|
public void hasReviewStarted() throws Exception {
|
|
ChangeNotes notes = newNotes(newChange());
|
|
assertThat(notes.getChange().hasReviewStarted()).isTrue();
|
|
|
|
notes = newNotes(newWorkInProgressChange());
|
|
assertThat(notes.getChange().hasReviewStarted()).isFalse();
|
|
|
|
Change c = newWorkInProgressChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().hasReviewStarted()).isFalse();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setWorkInProgress(true);
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().hasReviewStarted()).isFalse();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setWorkInProgress(false);
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().hasReviewStarted()).isTrue();
|
|
|
|
// Once review is started, setting WIP should have no impact.
|
|
c = newChange();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().hasReviewStarted()).isTrue();
|
|
update = newUpdate(c, changeOwner);
|
|
update.setWorkInProgress(true);
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getChange().hasReviewStarted()).isTrue();
|
|
}
|
|
|
|
@Test
|
|
public void pendingReviewers() throws Exception {
|
|
Address adr1 = new Address("Foo Bar1", "foo.bar1@gerritcodereview.com");
|
|
Address adr2 = new Address("Foo Bar2", "foo.bar2@gerritcodereview.com");
|
|
Account.Id ownerId = changeOwner.getAccount().id();
|
|
Account.Id otherUserId = otherUser.getAccount().id();
|
|
|
|
ChangeNotes notes = newNotes(newChange());
|
|
assertThat(notes.getPendingReviewers().asTable()).isEmpty();
|
|
assertThat(notes.getPendingReviewersByEmail().asTable()).isEmpty();
|
|
|
|
Change c = newWorkInProgressChange();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getPendingReviewers().asTable()).isEmpty();
|
|
assertThat(notes.getPendingReviewersByEmail().asTable()).isEmpty();
|
|
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putReviewer(ownerId, REVIEWER);
|
|
update.putReviewer(otherUserId, CC);
|
|
update.putReviewerByEmail(adr1, REVIEWER);
|
|
update.putReviewerByEmail(adr2, CC);
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getPendingReviewers().byState(REVIEWER)).containsExactly(ownerId);
|
|
assertThat(notes.getPendingReviewers().byState(CC)).containsExactly(otherUserId);
|
|
assertThat(notes.getPendingReviewers().byState(REMOVED)).isEmpty();
|
|
assertThat(notes.getPendingReviewersByEmail().byState(REVIEWER)).containsExactly(adr1);
|
|
assertThat(notes.getPendingReviewersByEmail().byState(CC)).containsExactly(adr2);
|
|
assertThat(notes.getPendingReviewersByEmail().byState(REMOVED)).isEmpty();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.removeReviewer(ownerId);
|
|
update.removeReviewerByEmail(adr1);
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getPendingReviewers().byState(REVIEWER)).isEmpty();
|
|
assertThat(notes.getPendingReviewers().byState(CC)).containsExactly(otherUserId);
|
|
assertThat(notes.getPendingReviewers().byState(REMOVED)).containsExactly(ownerId);
|
|
assertThat(notes.getPendingReviewersByEmail().byState(REVIEWER)).isEmpty();
|
|
assertThat(notes.getPendingReviewersByEmail().byState(CC)).containsExactly(adr2);
|
|
assertThat(notes.getPendingReviewersByEmail().byState(REMOVED)).containsExactly(adr1);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.setWorkInProgress(false);
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getPendingReviewers().asTable()).isEmpty();
|
|
assertThat(notes.getPendingReviewersByEmail().asTable()).isEmpty();
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putReviewer(ownerId, REVIEWER);
|
|
update.putReviewerByEmail(adr1, REVIEWER);
|
|
update.commit();
|
|
notes = newNotes(c);
|
|
assertThat(notes.getPendingReviewers().asTable()).isEmpty();
|
|
assertThat(notes.getPendingReviewersByEmail().asTable()).isEmpty();
|
|
}
|
|
|
|
@Test
|
|
public void revertOfIsNullByDefault() throws Exception {
|
|
Change c = newChange();
|
|
ChangeNotes notes = newNotes(c);
|
|
assertThat(notes.getChange().getRevertOf()).isNull();
|
|
}
|
|
|
|
@Test
|
|
public void setRevertOfPersistsValue() throws Exception {
|
|
Change changeToRevert = newChange();
|
|
Change c = TestChanges.newChange(project, changeOwner.getAccountId());
|
|
ChangeUpdate update = newUpdateForNewChange(c, changeOwner);
|
|
update.setChangeId(c.getKey().get());
|
|
update.setRevertOf(changeToRevert.getId().get());
|
|
update.commit();
|
|
assertThat(newNotes(c).getChange().getRevertOf()).isEqualTo(changeToRevert.getId());
|
|
}
|
|
|
|
@Test
|
|
public void setRevertOfToCurrentChangeFails() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
IllegalArgumentException thrown =
|
|
assertThrows(IllegalArgumentException.class, () -> update.setRevertOf(c.getId().get()));
|
|
assertThat(thrown).hasMessageThat().contains("A change cannot revert itself");
|
|
}
|
|
|
|
@Test
|
|
public void setRevertOfOnChildCommitFails() throws Exception {
|
|
Change c = newChange();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setRevertOf(newChange().getId().get());
|
|
StorageException thrown = assertThrows(StorageException.class, () -> update.commit());
|
|
assertThat(thrown)
|
|
.hasMessageThat()
|
|
.contains("Given ChangeUpdate is only allowed on initial commit");
|
|
}
|
|
|
|
@Test
|
|
public void updateCount() throws Exception {
|
|
Change c = newChange();
|
|
assertThat(newNotes(c).getUpdateCount()).isEqualTo(1);
|
|
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) -1);
|
|
update.commit();
|
|
assertThat(newNotes(c).getUpdateCount()).isEqualTo(2);
|
|
|
|
update = newUpdate(c, changeOwner);
|
|
update.putApproval("Code-Review", (short) 1);
|
|
update.commit();
|
|
assertThat(newNotes(c).getUpdateCount()).isEqualTo(3);
|
|
}
|
|
|
|
@Test
|
|
public void createPatchSetAfterPatchSetDeletion() throws Exception {
|
|
Change c = newChange();
|
|
assertThat(newNotes(c).getChange().currentPatchSetId().get()).isEqualTo(1);
|
|
|
|
// Create PS2.
|
|
incrementCurrentPatchSetFieldOnly(c);
|
|
RevCommit commit = tr.commit().message("PS" + c.currentPatchSetId().get()).create();
|
|
ChangeUpdate update = newUpdate(c, changeOwner);
|
|
update.setCommit(rw, commit);
|
|
update.setGroups(ImmutableList.of(commit.name()));
|
|
update.commit();
|
|
assertThat(newNotes(c).getChange().currentPatchSetId().get()).isEqualTo(2);
|
|
|
|
// Delete PS2.
|
|
update = newUpdate(c, changeOwner);
|
|
update.setPatchSetState(PatchSetState.DELETED);
|
|
update.commit();
|
|
c = newNotes(c).getChange();
|
|
assertThat(c.currentPatchSetId().get()).isEqualTo(1);
|
|
|
|
// Create another PS2
|
|
incrementCurrentPatchSetFieldOnly(c);
|
|
commit = tr.commit().message("PS" + c.currentPatchSetId().get()).create();
|
|
update = newUpdate(c, changeOwner);
|
|
update.setPatchSetState(PatchSetState.PUBLISHED);
|
|
update.setCommit(rw, commit);
|
|
update.setGroups(ImmutableList.of(commit.name()));
|
|
update.commit();
|
|
assertThat(newNotes(c).getChange().currentPatchSetId().get()).isEqualTo(2);
|
|
}
|
|
|
|
private String readNote(ChangeNotes notes, ObjectId noteId) throws Exception {
|
|
ObjectId dataId = notes.revisionNoteMap.noteMap.getNote(noteId).getData();
|
|
return new String(rw.getObjectReader().open(dataId, OBJ_BLOB).getCachedBytes(), UTF_8);
|
|
}
|
|
|
|
private ObjectId exactRefAllUsers(String refName) throws Exception {
|
|
try (Repository allUsersRepo = repoManager.openRepository(allUsers)) {
|
|
Ref ref = allUsersRepo.exactRef(refName);
|
|
return ref != null ? ref.getObjectId() : null;
|
|
}
|
|
}
|
|
|
|
private void assertCause(
|
|
Throwable e, Class<? extends Throwable> expectedClass, String expectedMsg) {
|
|
Throwable cause = null;
|
|
for (Throwable t : Throwables.getCausalChain(e)) {
|
|
if (expectedClass.isAssignableFrom(t.getClass())) {
|
|
cause = t;
|
|
break;
|
|
}
|
|
}
|
|
assertWithMessage(
|
|
expectedClass.getSimpleName()
|
|
+ " in causal chain of:\n"
|
|
+ Throwables.getStackTraceAsString(e))
|
|
.that(cause)
|
|
.isNotNull();
|
|
assertThat(cause.getMessage()).isEqualTo(expectedMsg);
|
|
}
|
|
|
|
private void incrementCurrentPatchSetFieldOnly(Change c) {
|
|
TestChanges.incrementPatchSet(c);
|
|
}
|
|
|
|
private RevCommit incrementPatchSet(Change c) throws Exception {
|
|
return incrementPatchSet(c, userFactory.create(c.getOwner()));
|
|
}
|
|
|
|
private RevCommit incrementPatchSet(Change c, IdentifiedUser user) throws Exception {
|
|
incrementCurrentPatchSetFieldOnly(c);
|
|
RevCommit commit = tr.commit().message("PS" + c.currentPatchSetId().get()).create();
|
|
ChangeUpdate update = newUpdate(c, user);
|
|
update.setCommit(rw, commit);
|
|
update.commit();
|
|
return tr.parseBody(commit);
|
|
}
|
|
}
|