blob: 366cbf736ed69f98acf7cdce79d82885445ade7a [file] [log] [blame]
// 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));
}
}
}