| // Copyright (C) 2022 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.truth.Truth.assertThat; |
| import static com.google.gerrit.testing.GerritJUnit.assertThrows; |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.ArgumentMatchers.eq; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.when; |
| |
| import com.google.common.collect.ImmutableListMultimap; |
| import com.google.gerrit.entities.Account; |
| import com.google.gerrit.entities.Change; |
| import com.google.gerrit.entities.CommentRange; |
| import com.google.gerrit.entities.HumanComment; |
| import com.google.gerrit.server.IdentifiedUser; |
| import com.google.gerrit.server.account.externalids.ExternalId; |
| import com.google.gerrit.server.account.externalids.ExternalIdCache; |
| import com.google.gerrit.server.git.RepositoryCaseMismatchException; |
| import com.google.gerrit.server.util.time.TimeUtil; |
| import com.google.inject.AbstractModule; |
| import java.io.IOException; |
| import java.util.Objects; |
| import java.util.Optional; |
| import org.eclipse.jgit.errors.RepositoryNotFoundException; |
| import org.eclipse.jgit.lib.ObjectId; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| public class ImportedChangeNotesTest extends AbstractChangeNotesTest { |
| |
| private static final String FOREIGN_SERVER_ID = "foreign-server-id"; |
| private static final String IMPORTED_SERVER_ID = "gerrit-imported-1"; |
| |
| private ExternalIdCache externalIdCacheMock; |
| |
| @Before |
| @Override |
| public void setUpTestEnvironment() throws Exception { |
| setupTestPrerequisites(); |
| } |
| |
| private void initServerIds(String serverId, String... importedServerIds) |
| throws Exception, RepositoryCaseMismatchException, RepositoryNotFoundException { |
| externalIdCacheMock = mock(ExternalIdCache.class); |
| injector = |
| createTestInjector( |
| new AbstractModule() { |
| @Override |
| protected void configure() { |
| bind(ExternalIdCache.class).toInstance(externalIdCacheMock); |
| } |
| }, |
| serverId, |
| importedServerIds); |
| injector.injectMembers(this); |
| createAllUsers(injector); |
| } |
| |
| @Test |
| public void allowChangeFromImportedServerId() throws Exception { |
| initServerIds(LOCAL_SERVER_ID, IMPORTED_SERVER_ID); |
| |
| linkImportedAccountTo(changeOwner.getAccountId(), Optional.of(changeOwner.getAccountId())); |
| |
| Change importedChange = newChange(createTestInjector(IMPORTED_SERVER_ID), false); |
| Change localChange = newChange(); |
| |
| assertThat(newNotes(importedChange).getServerId()).isEqualTo(IMPORTED_SERVER_ID); |
| assertThat(newNotes(localChange).getServerId()).isEqualTo(LOCAL_SERVER_ID); |
| } |
| |
| @Test |
| public void rejectChangeWithForeignServerId() throws Exception { |
| initServerIds(LOCAL_SERVER_ID); |
| |
| linkImportedAccountTo(changeOwner.getAccountId(), Optional.empty()); |
| |
| Change foreignChange = newChange(createTestInjector(FOREIGN_SERVER_ID), false); |
| |
| InvalidServerIdException invalidServerIdEx = |
| assertThrows(InvalidServerIdException.class, () -> newNotes(foreignChange)); |
| |
| String invalidServerIdMessage = invalidServerIdEx.getMessage(); |
| assertThat(invalidServerIdMessage).contains("expected " + LOCAL_SERVER_ID); |
| assertThat(invalidServerIdMessage).contains("actual: " + FOREIGN_SERVER_ID); |
| } |
| |
| @Test |
| public void changeFromImportedServerIdWithUnknownAccountId() throws Exception { |
| initServerIds(LOCAL_SERVER_ID, IMPORTED_SERVER_ID); |
| |
| when(externalIdCacheMock.byKey(any())).thenReturn(Optional.empty()); |
| |
| Change importedChange = newChange(createTestInjector(IMPORTED_SERVER_ID), false); |
| assertThat(newNotes(importedChange).getServerId()).isEqualTo(IMPORTED_SERVER_ID); |
| |
| assertThat(newNotes(importedChange).getChange().getOwner()) |
| .isEqualTo(Account.UNKNOWN_ACCOUNT_ID); |
| } |
| |
| @Test |
| public void commentChangeFromImportedServerIdWithAnExistingAccountId() throws Exception { |
| initServerIds(LOCAL_SERVER_ID, IMPORTED_SERVER_ID); |
| |
| Account.Id importedAccountId = Account.id(12345); |
| linkImportedAccountTo(importedAccountId, Optional.of(otherUser.getAccountId())); |
| IdentifiedUser importedUserIdentity = userFactory.create(importedAccountId); |
| |
| Change importedChange = newChange(createTestInjector(IMPORTED_SERVER_ID), false); |
| ChangeUpdate update = newUpdate(importedChange, importedUserIdentity); |
| update.putComment( |
| HumanComment.Status.PUBLISHED, |
| comment(importedChange, importedUserIdentity, IMPORTED_SERVER_ID)); |
| update.commit(); |
| |
| ChangeNotes notes = newNotes(importedChange); |
| |
| ImmutableListMultimap<ObjectId, HumanComment> comments = notes.getHumanComments(); |
| assertThat(comments).hasSize(1); |
| HumanComment gotComment = comments.entries().asList().get(0).getValue(); |
| assertThat(gotComment.author.getId()).isEqualTo(otherUser.getAccountId()); |
| assertThat(gotComment.serverId).isEqualTo(LOCAL_SERVER_ID); |
| } |
| |
| @Test |
| public void commentChangeFromImportedServerIdWithUnknownAccountId() throws Exception { |
| initServerIds(LOCAL_SERVER_ID, IMPORTED_SERVER_ID); |
| |
| Account.Id importedAccountId = Account.id(12345); |
| linkImportedAccountTo(importedAccountId, Optional.empty()); |
| IdentifiedUser importedUserIdentity = userFactory.create(importedAccountId); |
| |
| Change importedChange = newChange(createTestInjector(IMPORTED_SERVER_ID), false); |
| ChangeUpdate update = newUpdate(importedChange, importedUserIdentity); |
| update.putComment( |
| HumanComment.Status.PUBLISHED, |
| comment(importedChange, importedUserIdentity, IMPORTED_SERVER_ID)); |
| update.commit(); |
| |
| ChangeNotes notes = newNotes(importedChange); |
| |
| ImmutableListMultimap<ObjectId, HumanComment> comments = notes.getHumanComments(); |
| assertThat(comments).hasSize(1); |
| HumanComment gotComment = comments.entries().asList().get(0).getValue(); |
| assertThat(gotComment.author.getId()).isEqualTo(Account.UNKNOWN_ACCOUNT_ID); |
| } |
| |
| private HumanComment comment(Change change, IdentifiedUser commenter, String serverId) { |
| return newComment( |
| Objects.requireNonNull(change.currentPatchSetId()), |
| "a.txt", |
| "uuid1", |
| new CommentRange(1, 2, 3, 4), |
| 1, |
| commenter, |
| null, |
| TimeUtil.now(), |
| "Comment", |
| (short) 1, |
| ObjectId.zeroId(), |
| false, |
| serverId); |
| } |
| |
| private void linkImportedAccountTo(Account.Id importedAccount, Optional<Account.Id> localAccount) |
| throws IOException { |
| |
| if (localAccount.isEmpty()) { |
| when(externalIdCacheMock.byKey(any())).thenReturn(Optional.empty()); |
| } else { |
| Account.Id localAccountId = localAccount.get(); |
| ExternalId.Key importedAccountIdKey = |
| ExternalId.Key.create( |
| ExternalId.SCHEME_IMPORTED, importedAccount + "@" + IMPORTED_SERVER_ID, false); |
| ExternalId linkedExternalId = |
| ExternalId.create(importedAccountIdKey, localAccountId, null, null, null); |
| |
| when(externalIdCacheMock.byKey(eq(importedAccountIdKey))) |
| .thenReturn(Optional.of(linkedExternalId)); |
| } |
| } |
| } |