blob: eb1d27549818ad10d5804fb194c1d5a1d91f2206 [file] [log] [blame]
// Copyright (C) 2020 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.restapi.change;
import static com.google.common.collect.MoreCollectors.onlyElement;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.CommentsUtil;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class ListChangeCommentsTest {
@Test
public void commentsLinkedToChangeMessagesIgnoreGerritAutoGenTaggedMessages() {
/* Comments should not be linked to Gerrit's autogenerated messages */
List<CommentInfo> comments = createComments("c1", "00", "c2", "10", "c3", "25");
List<ChangeMessage> changeMessages =
createChangeMessages("cm1", "00", "cm2", "16", "cm3", "30");
changeMessages.add(
newChangeMessage("ignore", "cmAutoGenByGerrit", "15", ChangeMessagesUtil.TAG_MERGED));
CommentsUtil.linkCommentsToChangeMessages(comments, changeMessages, true);
assertThat(getComment(comments, "c1").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cm1").getKey().uuid());
/* comment 2 ignored the auto-generated message because it has a Gerrit tag */
assertThat(getComment(comments, "c2").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cm2").getKey().uuid());
assertThat(getComment(comments, "c3").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cm3").getKey().uuid());
// Make sure no comment is linked to the auto-gen message
Set<String> changeMessageIds =
comments.stream().map(c -> c.changeMessageId).collect(Collectors.toSet());
assertThat(changeMessageIds)
.doesNotContain(getChangeMessage(changeMessages, "cmAutoGenByGerrit").getKey().uuid());
}
@Test
public void commentsLinkedToCorrectAccounts() {
List<CommentInfo> comments =
createComments("c0", "10", "c1", "11", "c2", "11", "c3", "11", "c4", "11", "c5", "21");
int accountId1 = 12345;
int accountId2 = 12346;
int accountId3 = 12347;
linkAuthor(comments.get(0), accountId1);
// comments 1-4 have same timestamp
linkAuthor(comments.get(1), accountId2);
linkAuthor(comments.get(2), accountId1);
linkAuthor(comments.get(3), accountId1);
linkAuthor(comments.get(4), accountId2);
linkAuthor(comments.get(5), accountId1);
// Change massages have exactly same timestamps
List<ChangeMessage> changeMessages =
ImmutableList.of(
createChangeMessage("cm0", "10", Account.id(accountId1)),
createChangeMessage("cm1", "11", Account.id(accountId1)),
createChangeMessage("cm2", "11", Account.id(accountId2)),
// unrelated message by other account in-between
createChangeMessage("cm2.2", "15", Account.id(accountId3)),
createChangeMessage("cm3", "21", Account.id(accountId1)));
CommentsUtil.linkCommentsToChangeMessages(comments, changeMessages, true);
assertThat(getComment(comments, "c0").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cm0").getKey().uuid());
// belongs to account2 -assigned to account2
assertThat(getComment(comments, "c1").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cm2").getKey().uuid());
// belongs to account1 -assigned to account1
assertThat(getComment(comments, "c2").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cm1").getKey().uuid());
assertThat(getComment(comments, "c3").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cm1").getKey().uuid());
// belongs to account2 - assigned to account2
assertThat(getComment(comments, "c4").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cm2").getKey().uuid());
// different timestamp - assigned to a different message
assertThat(getComment(comments, "c5").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cm3").getKey().uuid());
// Make sure no comment is linked to the auto-gen message
Set<String> changeMessageIds =
comments.stream().map(c -> c.changeMessageId).collect(Collectors.toSet());
assertThat(changeMessageIds)
.doesNotContain(getChangeMessage(changeMessages, "cm2.2").getKey().uuid());
}
@Test
public void commentsLinkedToCorrectAccountsIfUserNotMatched() {
String tsCm0 = "10";
String tsCm1 = "11";
String tsCm2 = "12";
List<CommentInfo> comments =
createComments(
"commentMessage0", tsCm0, "commentMessage1", tsCm1, "commentMessage2", tsCm2);
int accountId1 = 1;
int accountId2 = 2;
int accountId2Imported = 0;
int accountId3 = 3;
linkAuthor(comments.get(0), accountId1);
linkAuthor(comments.get(1), accountId2Imported);
linkAuthor(comments.get(2), accountId3);
List<ChangeMessage> changeMessages =
ImmutableList.of(
createChangeMessage("changeMessage0", tsCm0, Account.id(accountId1)),
createChangeMessage("changeMessage1", tsCm1, Account.id(accountId2)),
createChangeMessage("changeMessage2", tsCm2, Account.id(accountId3)));
CommentsUtil.linkCommentsToChangeMessages(comments, changeMessages, false);
assertThat(getComment(comments, "commentMessage0").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "changeMessage0").getKey().uuid());
assertThat(getComment(comments, "commentMessage1").changeMessageId).isNull();
assertThat(getComment(comments, "commentMessage2").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "changeMessage2").getKey().uuid());
}
@Test
public void commentsLinkedToChangeMessagesAllowLinkingToAutoGenTaggedMessages() {
/* Human comments are allowed to be linked to autogenerated messages */
List<CommentInfo> comments = createComments("c1", "00", "c2", "10", "c3", "25");
List<ChangeMessage> changeMessages =
createChangeMessages("cm1", "00", "cm2", "16", "cm3", "30");
changeMessages.add(
newChangeMessage(
"cmAutoGen", "cmAutoGen", "15", ChangeMessagesUtil.AUTOGENERATED_TAG_PREFIX));
CommentsUtil.linkCommentsToChangeMessages(comments, changeMessages, true);
assertThat(getComment(comments, "c1").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cm1").getKey().uuid());
/* comment 2 did not ignore the auto-generated change message */
assertThat(getComment(comments, "c2").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cmAutoGen").getKey().uuid());
assertThat(getComment(comments, "c3").changeMessageId)
.isEqualTo(getChangeMessage(changeMessages, "cm3").getKey().uuid());
}
/**
* Create a list of comments from the specified args args should be passed as consecutive pairs of
* messages and timestamps example: (m1, t1, m2, t2, ...)
*/
private static List<CommentInfo> createComments(String... args) {
List<CommentInfo> comments = new ArrayList<>();
for (int i = 0; i < args.length; i += 2) {
String message = args[i];
String ts = args[i + 1];
comments.add(newCommentInfo(message, ts));
}
return comments;
}
private void linkAuthor(CommentInfo commentInfo, int accountId) {
commentInfo.author = new AccountInfo(accountId);
}
/**
* Create a list of change messages from the specified args args should be passed as consecutive
* pairs of messages and timestamps example: (m1, t1, m2, t2, ...). the tag parameter for the
* created change messages will be null.
*/
private static List<ChangeMessage> createChangeMessages(String... args) {
List<ChangeMessage> changeMessages = new ArrayList<>();
for (int i = 0; i < args.length; i += 2) {
String message = args[i];
String ts = args[i + 1];
changeMessages.add(createChangeMessage(message, ts, Optional.empty()));
}
return changeMessages;
}
/** Creates a ChangeMessages with the specified author. */
private static ChangeMessage createChangeMessage(String message, String ts, Account.Id author) {
return createChangeMessage(message, ts, Optional.of(author));
}
private static ChangeMessage createChangeMessage(
String message, String ts, Optional<Account.Id> author) {
String key = message + "Key";
return newChangeMessage(key, author, message, ts, null);
}
/** Create a new CommentInfo with a given message and timestamp */
private static CommentInfo newCommentInfo(String message, String ts) {
CommentInfo c = new CommentInfo();
c.message = message;
c.updated = Timestamp.valueOf("2000-01-01 00:00:" + ts);
return c;
}
/** Create a new change message with an id, message, timestamp and tag */
private static ChangeMessage newChangeMessage(String id, String message, String ts, String tag) {
return newChangeMessage(id, Optional.empty(), message, ts, tag);
}
private static ChangeMessage newChangeMessage(
String id, Optional<Account.Id> accountId, String message, String ts, String tag) {
ChangeMessage.Key key = ChangeMessage.key(Change.id(1), id);
Instant timestamp =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneId.systemDefault())
.parse("2000-01-01 00:00:" + ts, Instant::from);
ChangeMessage cm =
ChangeMessage.create(key, accountId.orElse(null), timestamp, null, message, null, tag);
return cm;
}
/** Return the change message from the list of messages that has specific message text */
private static ChangeMessage getChangeMessage(List<ChangeMessage> messages, String messageText) {
return messages.stream().filter(m -> m.getMessage().equals(messageText)).collect(onlyElement());
}
/** Return the comment from the list of comments that has specific message text */
private CommentInfo getComment(List<CommentInfo> comments, String messageText) {
return comments.stream().filter(c -> c.message.equals(messageText)).collect(onlyElement());
}
}