| // Copyright (C) 2021 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.extensions.common; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.gerrit.extensions.client.ReviewerState; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.ParameterizedType; |
| import java.lang.reflect.Type; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Map; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| @RunWith(JUnit4.class) |
| public final class ChangeInfoDifferTest { |
| |
| private static final String REVISION = "abc123"; |
| |
| @Test |
| public void getDiff_givenEmptyChangeInfos_returnsEmptyDifference() { |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(new ChangeInfo(), new ChangeInfo()); |
| |
| // Spot check a few fields, including collections and maps. |
| assertThat(diff.added()._number).isNull(); |
| assertThat(diff.added().branch).isNull(); |
| assertThat(diff.added().project).isNull(); |
| assertThat(diff.added().currentRevision).isNull(); |
| assertThat(diff.added().actions).isNull(); |
| assertThat(diff.added().messages).isNull(); |
| assertThat(diff.added().reviewers).isNull(); |
| assertThat(diff.added().hashtags).isNull(); |
| assertThat(diff.removed()._number).isNull(); |
| assertThat(diff.removed().branch).isNull(); |
| assertThat(diff.removed().project).isNull(); |
| assertThat(diff.removed().currentRevision).isNull(); |
| assertThat(diff.removed().actions).isNull(); |
| assertThat(diff.removed().messages).isNull(); |
| assertThat(diff.removed().reviewers).isNull(); |
| assertThat(diff.removed().hashtags).isNull(); |
| } |
| |
| @Test |
| public void getDiff_returnsOldAndNewChangeInfos() { |
| ChangeInfo oldChangeInfo = createChangeInfoWithTopic("topic"); |
| ChangeInfo newChangeInfo = createChangeInfoWithTopic(oldChangeInfo.topic); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.oldChangeInfo()).isEqualTo(oldChangeInfo); |
| assertThat(diff.newChangeInfo()).isEqualTo(newChangeInfo); |
| } |
| |
| @Test |
| public void getDiff_givenUnchangedTopic_returnsNullTopics() { |
| ChangeInfo oldChangeInfo = createChangeInfoWithTopic("topic"); |
| ChangeInfo newChangeInfo = createChangeInfoWithTopic(oldChangeInfo.topic); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().topic).isNull(); |
| assertThat(diff.removed().topic).isNull(); |
| } |
| |
| @Test |
| public void getDiff_givenChangedTopic_returnsTopics() { |
| ChangeInfo oldChangeInfo = createChangeInfoWithTopic("old-topic"); |
| ChangeInfo newChangeInfo = createChangeInfoWithTopic("new-topic"); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().topic).isEqualTo(newChangeInfo.topic); |
| assertThat(diff.removed().topic).isEqualTo(oldChangeInfo.topic); |
| } |
| |
| @Test |
| public void getDiff_givenEqualAssignees_returnsNullAssignee() { |
| ChangeInfo oldChangeInfo = |
| createChangeInfoWithAccount(new AccountInfo("name", "mail@mail.com")); |
| ChangeInfo newChangeInfo = |
| createChangeInfoWithAccount( |
| new AccountInfo(oldChangeInfo.assignee.name, oldChangeInfo.assignee.email)); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().assignee).isNull(); |
| assertThat(diff.removed().assignee).isNull(); |
| } |
| |
| @Test |
| public void getDiff_givenNewAssignee_returnsAssignee() { |
| ChangeInfo oldChangeInfo = new ChangeInfo(); |
| ChangeInfo newChangeInfo = |
| createChangeInfoWithAccount(new AccountInfo("name", "mail@mail.com")); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().assignee).isEqualTo(newChangeInfo.assignee); |
| assertThat(diff.removed().assignee).isNull(); |
| } |
| |
| @Test |
| public void getDiff_withRemovedAssignee_returnsAssignee() { |
| ChangeInfo oldChangeInfo = |
| createChangeInfoWithAccount(new AccountInfo("name", "mail@mail.com")); |
| ChangeInfo newChangeInfo = new ChangeInfo(); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().assignee).isNull(); |
| assertThat(diff.removed().assignee).isEqualTo(oldChangeInfo.assignee); |
| } |
| |
| @Test |
| public void getDiff_givenAssigneeWithNewName_returnsNameButNotEmail() { |
| ChangeInfo oldChangeInfo = |
| createChangeInfoWithAccount(new AccountInfo("old name", "mail@mail.com")); |
| ChangeInfo newChangeInfo = |
| createChangeInfoWithAccount(new AccountInfo("new name", oldChangeInfo.assignee.email)); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().assignee).isNotNull(); |
| assertThat(diff.added().assignee.name).isEqualTo(newChangeInfo.assignee.name); |
| assertThat(diff.added().assignee.email).isNull(); |
| assertThat(diff.removed().assignee).isNotNull(); |
| assertThat(diff.removed().assignee.name).isEqualTo(oldChangeInfo.assignee.name); |
| assertThat(diff.removed().assignee.email).isNull(); |
| } |
| |
| @Test |
| public void getDiff_whenHashtagsChanged_returnsHashtags() { |
| String removedHashtag = "removed"; |
| String addedHashtag = "added"; |
| ChangeInfo oldChangeInfo = createChangeInfoWithHashtags(removedHashtag, "existing"); |
| ChangeInfo newChangeInfo = createChangeInfoWithHashtags("existing", addedHashtag); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().hashtags).isNotNull(); |
| assertThat(diff.added().hashtags).containsExactly(addedHashtag); |
| assertThat(diff.removed().hashtags).isNotNull(); |
| assertThat(diff.removed().hashtags).containsExactly(removedHashtag); |
| } |
| |
| @Test |
| public void getDiff_whenDuplicateHashtagAdded_returnsHashtag() { |
| String hashtag = "hashtag"; |
| ChangeInfo oldChangeInfo = createChangeInfoWithHashtags(hashtag, hashtag); |
| ChangeInfo newChangeInfo = createChangeInfoWithHashtags(hashtag, hashtag, hashtag); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().hashtags).isNotNull(); |
| assertThat(diff.added().hashtags).containsExactly(hashtag); |
| assertThat(diff.removed().hashtags).isNull(); |
| } |
| |
| @Test |
| public void getDiff_whenChangeMessageUnchanged_returnsNullMessage() { |
| String message = "message"; |
| ChangeInfo oldChangeInfo = new ChangeInfo(new ChangeMessageInfo(message)); |
| ChangeInfo newChangeInfo = new ChangeInfo(new ChangeMessageInfo(message)); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().messages).isNull(); |
| assertThat(diff.removed().messages).isNull(); |
| } |
| |
| @Test |
| public void getDiff_whenChangeMessageAdded_returnsAdded() { |
| ChangeMessageInfo addedMessage = new ChangeMessageInfo("added"); |
| ChangeMessageInfo existingMessage = new ChangeMessageInfo("existing"); |
| ChangeInfo oldChangeInfo = new ChangeInfo(existingMessage); |
| ChangeInfo newChangeInfo = new ChangeInfo(existingMessage, addedMessage); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().messages).isNotNull(); |
| assertThat(diff.added().messages).containsExactly(addedMessage); |
| assertThat(diff.removed().messages).isNull(); |
| } |
| |
| @Test |
| public void getDiff_whenChangeMessageRemoved_returnsRemoved() { |
| ChangeMessageInfo removedMessage = new ChangeMessageInfo("removed"); |
| ChangeMessageInfo existingMessage = new ChangeMessageInfo("existing"); |
| ChangeInfo oldChangeInfo = new ChangeInfo(existingMessage, removedMessage); |
| ChangeInfo newChangeInfo = new ChangeInfo(existingMessage); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().messages).isNull(); |
| assertThat(diff.removed().messages).isNotNull(); |
| assertThat(diff.removed().messages).containsExactly(removedMessage); |
| } |
| |
| @Test |
| public void getDiff_whenDuplicateMessagesAdded_returnsDuplicates() { |
| ChangeMessageInfo message = new ChangeMessageInfo("message"); |
| ChangeInfo oldChangeInfo = new ChangeInfo(message, message); |
| ChangeInfo newChangeInfo = new ChangeInfo(message, message, message, message); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().messages).isNotNull(); |
| assertThat(diff.added().messages).containsExactly(message, message); |
| assertThat(diff.removed().messages).isNull(); |
| } |
| |
| @Test |
| public void getDiff_whenNoNewRevisions_returnsNullRevisions() { |
| ChangeInfo oldChangeInfo = new ChangeInfo(ImmutableMap.of(REVISION, new RevisionInfo("ref"))); |
| ChangeInfo newChangeInfo = new ChangeInfo(ImmutableMap.of(REVISION, new RevisionInfo("ref"))); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().revisions).isNull(); |
| assertThat(diff.removed().revisions).isNull(); |
| } |
| |
| @Test |
| public void getDiff_whenOneAddedRevision_returnsRevision() { |
| RevisionInfo addedRevision = new RevisionInfo("ref"); |
| ChangeInfo oldChangeInfo = new ChangeInfo(ImmutableMap.of()); |
| ChangeInfo newChangeInfo = new ChangeInfo(ImmutableMap.of(REVISION, addedRevision)); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().revisions).isNotNull(); |
| assertThat(diff.added().revisions).hasSize(1); |
| assertThat(diff.added().revisions).containsKey(REVISION); |
| assertThat(diff.added().revisions.get(REVISION).ref).isEqualTo(addedRevision.ref); |
| assertThat(diff.removed().revisions).isNull(); |
| } |
| |
| @Test |
| public void getDiff_whenOneModifiedRevision_returnsModificationsToRevision() { |
| RevisionInfo oldRevision = new RevisionInfo("ref", 1); |
| RevisionInfo newRevision = new RevisionInfo(oldRevision.ref, 2); |
| ChangeInfo oldChangeInfo = new ChangeInfo(ImmutableMap.of(REVISION, oldRevision)); |
| ChangeInfo newChangeInfo = new ChangeInfo(ImmutableMap.of(REVISION, newRevision)); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().revisions).isNotNull(); |
| assertThat(diff.added().revisions).hasSize(1); |
| assertThat(diff.added().revisions).containsKey(REVISION); |
| assertThat(diff.added().revisions.get(REVISION).ref).isNull(); |
| assertThat(diff.added().revisions.get(REVISION)._number).isEqualTo(newRevision._number); |
| assertThat(diff.removed().revisions).isNotNull(); |
| assertThat(diff.removed().revisions).hasSize(1); |
| assertThat(diff.removed().revisions).containsKey(REVISION); |
| assertThat(diff.removed().revisions.get(REVISION).ref).isNull(); |
| assertThat(diff.removed().revisions.get(REVISION)._number).isEqualTo(oldRevision._number); |
| } |
| |
| @Test |
| public void getDiff_whenOneModifiedRevisionUploader_returnsModificationsToRevisionUploader() { |
| RevisionInfo oldRevision = new RevisionInfo(new AccountInfo("name", "email@mail.com")); |
| RevisionInfo newRevision = |
| new RevisionInfo( |
| new AccountInfo(oldRevision.uploader.name, oldRevision.uploader.email + "2")); |
| ChangeInfo oldChangeInfo = new ChangeInfo(ImmutableMap.of(REVISION, oldRevision)); |
| ChangeInfo newChangeInfo = new ChangeInfo(ImmutableMap.of(REVISION, newRevision)); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().revisions).isNotNull(); |
| assertThat(diff.added().revisions).hasSize(1); |
| assertThat(diff.added().revisions).containsKey(REVISION); |
| assertThat(diff.added().revisions.get(REVISION).uploader).isNotNull(); |
| assertThat(diff.added().revisions.get(REVISION).uploader.name).isNull(); |
| assertThat(diff.added().revisions.get(REVISION).uploader.email) |
| .isEqualTo(newRevision.uploader.email); |
| assertThat(diff.removed().revisions).isNotNull(); |
| assertThat(diff.removed().revisions).hasSize(1); |
| assertThat(diff.removed().revisions).containsKey(REVISION); |
| assertThat(diff.removed().revisions.get(REVISION).uploader).isNotNull(); |
| assertThat(diff.removed().revisions.get(REVISION).uploader.name).isNull(); |
| assertThat(diff.removed().revisions.get(REVISION).uploader.email) |
| .isEqualTo(oldRevision.uploader.email); |
| } |
| |
| @Test |
| public void getDiff_whenOneUnchangedRevisionUploader_returnsNullRevision() { |
| RevisionInfo oldRevision = new RevisionInfo(new AccountInfo("name", "email@mail.com")); |
| RevisionInfo newRevision = new RevisionInfo(oldRevision.uploader); |
| ChangeInfo oldChangeInfo = new ChangeInfo(ImmutableMap.of(REVISION, oldRevision)); |
| ChangeInfo newChangeInfo = new ChangeInfo(ImmutableMap.of(REVISION, newRevision)); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| |
| assertThat(diff.added().revisions).isNull(); |
| assertThat(diff.removed().revisions).isNull(); |
| } |
| |
| @Test |
| public void getDiff_assertCanConstructAllChangeInfoReferences() throws Exception { |
| buildObjectWithFullFields(ChangeInfo.class); |
| } |
| |
| @Test |
| public void getDiff_arrayListInMap() { |
| ChangeInfo oldChangeInfo = new ChangeInfo(); |
| ChangeInfo newChangeInfo = new ChangeInfo(); |
| |
| AccountInfo i1 = new AccountInfo(); |
| i1._accountId = 1; |
| AccountInfo i2 = new AccountInfo(); |
| i2._accountId = 2; |
| |
| ArrayList<AccountInfo> a1 = new ArrayList<>(); |
| ArrayList<AccountInfo> a2 = new ArrayList<>(); |
| |
| a1.add(i1); |
| a2.add(i1); |
| a2.add(i2); |
| oldChangeInfo.reviewers = ImmutableMap.of(ReviewerState.REVIEWER, a1); |
| newChangeInfo.reviewers = ImmutableMap.of(ReviewerState.REVIEWER, a2); |
| |
| ChangeInfoDifference diff = ChangeInfoDiffer.getDifference(oldChangeInfo, newChangeInfo); |
| assertThat(diff.added().reviewers).hasSize(1); |
| assertThat(diff.added().reviewers).containsKey(ReviewerState.REVIEWER); |
| assertThat(diff.added().reviewers.get(ReviewerState.REVIEWER)).containsExactly(i2); |
| assertThat(diff.removed().reviewers).isNull(); |
| } |
| |
| private static Object buildObjectWithFullFields(Class<?> c) throws Exception { |
| if (c == null) { |
| return null; |
| } |
| Object toPopulate = ChangeInfoDiffer.construct(c); |
| for (Field field : toPopulate.getClass().getDeclaredFields()) { |
| Class<?> parameterizedType = getParameterizedType(field); |
| if (!ChangeInfoDiffer.isSimple(field.getType()) |
| && !field.getType().isArray() |
| && !Map.class.isAssignableFrom(field.getType()) |
| && !Collection.class.isAssignableFrom(field.getType())) { |
| field.set(toPopulate, buildObjectWithFullFields(field.getType())); |
| } else if (Collection.class.isAssignableFrom(field.getType()) |
| && parameterizedType != null |
| && !ChangeInfoDiffer.isSimple(parameterizedType)) { |
| field.set(toPopulate, ImmutableList.of(buildObjectWithFullFields(parameterizedType))); |
| } |
| } |
| return toPopulate; |
| } |
| |
| private static Class<?> getParameterizedType(Field field) { |
| if (!Collection.class.isAssignableFrom(field.getType())) { |
| return null; |
| } |
| Type genericType = field.getGenericType(); |
| if (genericType instanceof ParameterizedType) { |
| return (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0]; |
| } |
| return null; |
| } |
| |
| private static ChangeInfo createChangeInfoWithTopic(String topic) { |
| ChangeInfo changeInfo = new ChangeInfo(); |
| changeInfo.topic = topic; |
| return changeInfo; |
| } |
| |
| private static ChangeInfo createChangeInfoWithAccount(AccountInfo accountInfo) { |
| ChangeInfo changeInfo = new ChangeInfo(); |
| changeInfo.assignee = accountInfo; |
| return changeInfo; |
| } |
| |
| private static ChangeInfo createChangeInfoWithHashtags(String... hashtags) { |
| ChangeInfo changeInfo = new ChangeInfo(); |
| changeInfo.hashtags = ImmutableList.copyOf(hashtags); |
| return changeInfo; |
| } |
| } |