| // 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.server.notedb; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| import static com.google.gerrit.testing.GerritJUnit.assertThrows; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableListMultimap; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.gerrit.entities.Address; |
| import com.google.gerrit.entities.AttentionSetUpdate; |
| import com.google.gerrit.entities.Change; |
| import com.google.gerrit.entities.SubmissionId; |
| import com.google.gerrit.server.update.ChainedReceiveCommands; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Optional; |
| import org.eclipse.jgit.lib.Repository; |
| import org.eclipse.jgit.transport.ReceiveCommand; |
| import org.junit.Test; |
| |
| public class OpenRepoTest extends AbstractChangeNotesTest { |
| |
| private final Optional<Integer> NO_UPDATES_AT_ALL = Optional.of(0); |
| private final Optional<Integer> ONLY_ONE_UPDATE = Optional.of(1); |
| private final Optional<Integer> ONLY_TWO_UPDATES = Optional.of(2); |
| private final Optional<Integer> MAX_PATCH_SETS = Optional.empty(); |
| |
| private FakeChainedReceiveCommands fakeChainedReceiveCommands; |
| |
| @Override |
| public void setUpTestEnvironment() throws Exception { |
| super.setUpTestEnvironment(); |
| fakeChainedReceiveCommands = new FakeChainedReceiveCommands(repo); |
| } |
| |
| @Test |
| public void throwExceptionWhenExceedingMaxUpdatesLimit() throws Exception { |
| try (OpenRepo openRepo = openRepo()) { |
| Change c = newChange(); |
| ChangeUpdate update = newUpdate(c, changeOwner); |
| update.setStatus(Change.Status.NEW); |
| |
| ImmutableListMultimap<String, ChangeUpdate> changeUpdates = |
| new ImmutableListMultimap.Builder<String, ChangeUpdate>().put("one", update).build(); |
| |
| assertThrows( |
| LimitExceededException.class, |
| () -> openRepo.addUpdates(changeUpdates, NO_UPDATES_AT_ALL, MAX_PATCH_SETS)); |
| } |
| } |
| |
| @Test |
| public void allowExceedingLimitWhenAttentionSetUpdateOnly() throws Exception { |
| try (OpenRepo openRepo = openRepo()) { |
| Change c = newChange(); |
| ChangeUpdate update = newUpdate(c, changeOwner); |
| update.setStatus(Change.Status.NEW); |
| |
| addToAttentionSet(update); |
| |
| ImmutableListMultimap<String, ChangeUpdate> changeUpdates = |
| new ImmutableListMultimap.Builder<String, ChangeUpdate>().put("one", update).build(); |
| |
| openRepo.addUpdates(changeUpdates, NO_UPDATES_AT_ALL, MAX_PATCH_SETS); |
| |
| assertThat(fakeChainedReceiveCommands.commands.size()).isEqualTo(1); |
| } |
| } |
| |
| @Test |
| public void allowExceedingLimitWhenChangeIsSubmitted() throws Exception { |
| try (OpenRepo openRepo = openRepo()) { |
| Change c = newChange(); |
| ChangeUpdate 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)))); |
| |
| ImmutableListMultimap<String, ChangeUpdate> changeUpdates = |
| new ImmutableListMultimap.Builder<String, ChangeUpdate>().put("one", update).build(); |
| |
| openRepo.addUpdates(changeUpdates, NO_UPDATES_AT_ALL, MAX_PATCH_SETS); |
| |
| assertThat(fakeChainedReceiveCommands.commands.size()).isEqualTo(1); |
| } |
| } |
| |
| @Test |
| public void allowExceedingLimitWhenChangeIsAbandoned() throws Exception { |
| try (OpenRepo openRepo = openRepo()) { |
| Change c = newChange(); |
| ChangeUpdate update = newUpdate(c, changeOwner); |
| update.setStatus(Change.Status.ABANDONED); |
| |
| ImmutableListMultimap<String, ChangeUpdate> changeUpdates = |
| new ImmutableListMultimap.Builder<String, ChangeUpdate>().put("one", update).build(); |
| |
| openRepo.addUpdates(changeUpdates, NO_UPDATES_AT_ALL, MAX_PATCH_SETS); |
| |
| assertThat(fakeChainedReceiveCommands.commands.size()).isEqualTo(1); |
| } |
| } |
| |
| @Test |
| public void attentionSetUpdateShouldNotContributeToOperationsCount() throws Exception { |
| try (OpenRepo openRepo = openRepo()) { |
| Change c1 = newChange(); |
| |
| ChangeUpdate update1 = newUpdateForNewChange(c1, changeOwner); |
| addToAttentionSet(update1); |
| |
| ChangeUpdate update2 = newUpdateForNewChange(c1, changeOwner); |
| update2.setStatus(Change.Status.NEW); |
| |
| ImmutableListMultimap<String, ChangeUpdate> changeUpdates = |
| new ImmutableListMultimap.Builder<String, ChangeUpdate>().put("two", update2).build(); |
| |
| openRepo.addUpdates(changeUpdates, ONLY_TWO_UPDATES, MAX_PATCH_SETS); |
| |
| assertThat(fakeChainedReceiveCommands.commands.size()).isEqualTo(1); |
| } |
| } |
| |
| @Test |
| public void attentionSetAndReviewerUpdateShouldContributeToOperationsCount() throws Exception { |
| try (OpenRepo openRepo = openRepo()) { |
| Change c1 = newChange(); |
| |
| ChangeUpdate update1 = newUpdateForNewChange(c1, changeOwner); |
| addToAttentionSet(update1); |
| update1.putReviewer(otherUserId, ReviewerStateInternal.REVIEWER); |
| |
| ChangeUpdate update2 = newUpdateForNewChange(c1, changeOwner); |
| update2.setStatus(Change.Status.NEW); |
| |
| ImmutableListMultimap<String, ChangeUpdate> changeUpdates = |
| new ImmutableListMultimap.Builder<String, ChangeUpdate>().put("two", update2).build(); |
| |
| assertThrows( |
| LimitExceededException.class, |
| () -> openRepo.addUpdates(changeUpdates, NO_UPDATES_AT_ALL, MAX_PATCH_SETS)); |
| } |
| } |
| |
| @Test |
| public void attentionSetAndReviewerByEmailUpdateShouldContributeToOperationsCount() |
| throws Exception { |
| try (OpenRepo openRepo = openRepo()) { |
| Change c1 = newChange(); |
| |
| ChangeUpdate update1 = newUpdateForNewChange(c1, changeOwner); |
| addToAttentionSet(update1); |
| update1.putReviewerByEmail( |
| Address.create("anyEmail@mail.com"), ReviewerStateInternal.REVIEWER); |
| |
| ChangeUpdate update2 = newUpdateForNewChange(c1, changeOwner); |
| update2.setStatus(Change.Status.NEW); |
| |
| ImmutableListMultimap<String, ChangeUpdate> changeUpdates = |
| new ImmutableListMultimap.Builder<String, ChangeUpdate>().put("two", update2).build(); |
| |
| assertThrows( |
| LimitExceededException.class, |
| () -> openRepo.addUpdates(changeUpdates, NO_UPDATES_AT_ALL, MAX_PATCH_SETS)); |
| } |
| } |
| |
| @Test |
| public void attentionSetAndWIPUpdateToTrueShouldContributeToOperationsCount() throws Exception { |
| try (OpenRepo openRepo = openRepo()) { |
| Change c1 = newChange(); |
| |
| ChangeUpdate update1 = newUpdateForNewChange(c1, changeOwner); |
| addToAttentionSet(update1); |
| update1.setWorkInProgress(true); |
| |
| ChangeUpdate update2 = newUpdateForNewChange(c1, changeOwner); |
| update2.setStatus(Change.Status.NEW); |
| |
| ImmutableListMultimap<String, ChangeUpdate> changeUpdates = |
| new ImmutableListMultimap.Builder<String, ChangeUpdate>().put("two", update2).build(); |
| |
| assertThrows( |
| LimitExceededException.class, |
| () -> openRepo.addUpdates(changeUpdates, NO_UPDATES_AT_ALL, MAX_PATCH_SETS)); |
| } |
| } |
| |
| @Test |
| public void attentionSetAndWIPUpdateToFalseShouldContributeToOperationsCount() throws Exception { |
| try (OpenRepo openRepo = openRepo()) { |
| Change c1 = newChange(); |
| |
| ChangeUpdate update1 = newUpdateForNewChange(c1, changeOwner); |
| addToAttentionSet(update1); |
| update1.setWorkInProgress(false); |
| |
| ChangeUpdate update2 = newUpdateForNewChange(c1, changeOwner); |
| update2.setStatus(Change.Status.NEW); |
| |
| ImmutableListMultimap<String, ChangeUpdate> changeUpdates = |
| new ImmutableListMultimap.Builder<String, ChangeUpdate>().put("two", update2).build(); |
| |
| assertThrows( |
| LimitExceededException.class, |
| () -> openRepo.addUpdates(changeUpdates, NO_UPDATES_AT_ALL, MAX_PATCH_SETS)); |
| } |
| } |
| |
| @Test |
| public void normalChangeShouldContributeToOperationsCount() throws Exception { |
| try (OpenRepo openRepo = openRepo()) { |
| Change c1 = newChange(); |
| |
| ChangeUpdate update2 = newUpdateForNewChange(c1, changeOwner); |
| update2.setStatus(Change.Status.NEW); |
| |
| ImmutableListMultimap<String, ChangeUpdate> changeUpdates = |
| new ImmutableListMultimap.Builder<String, ChangeUpdate>().put("two", update2).build(); |
| |
| assertThrows( |
| LimitExceededException.class, |
| () -> openRepo.addUpdates(changeUpdates, ONLY_ONE_UPDATE, MAX_PATCH_SETS)); |
| } |
| } |
| |
| @Test |
| public void canCreateChangeNotesFromOpenRepoAndChangeid() throws Exception { |
| try (OpenRepo openRepo = openRepo()) { |
| Change change = newChange(); |
| |
| ChangeNotes changeNotes = |
| changeNotesFactory.createChecked(openRepo.repo, project, change.getId(), null); |
| |
| assertThat(changeNotes).isNotNull(); |
| assertThat(changeNotes.getChangeId()).isEqualTo(change.getId()); |
| } |
| } |
| |
| private void addToAttentionSet(ChangeUpdate update) { |
| AttentionSetUpdate attentionSetUpdate = |
| AttentionSetUpdate.createForWrite( |
| otherUser.getAccountId(), AttentionSetUpdate.Operation.ADD, "test"); |
| update.addToPlannedAttentionSetUpdates(ImmutableSet.of(attentionSetUpdate)); |
| } |
| |
| private static class FakeChainedReceiveCommands extends ChainedReceiveCommands { |
| Map<String, ReceiveCommand> commands = new HashMap<>(); |
| |
| public FakeChainedReceiveCommands(Repository repo) { |
| super(repo); |
| } |
| |
| @Override |
| public void add(ReceiveCommand cmd) { |
| commands.put(cmd.getRefName(), cmd); |
| } |
| } |
| |
| private OpenRepo openRepo() { |
| return new OpenRepo(repo, rw, null, fakeChainedReceiveCommands, false); |
| } |
| } |