Add ITs for replication events Ahead of some refactoring, ensure there's at least some minimal test coverage. Change-Id: If7c6cd66b19d3b98ab0be2a5cbd6298b3d41a865
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationEventsIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationEventsIT.java new file mode 100644 index 0000000..841bfd7 --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationEventsIT.java
@@ -0,0 +1,119 @@ +// 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.googlesource.gerrit.plugins.replication; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.gerrit.acceptance.PushOneCommit.Result; +import com.google.gerrit.acceptance.Sandboxed; +import com.google.gerrit.acceptance.TestPlugin; +import com.google.gerrit.acceptance.UseLocalDisk; +import com.google.gerrit.acceptance.WaitUtil; +import com.google.gerrit.entities.BranchNameKey; +import com.google.gerrit.entities.Project; +import com.google.gerrit.extensions.api.projects.BranchInput; +import com.google.gerrit.extensions.registration.DynamicItem; +import com.google.gerrit.server.events.EventDispatcher; +import com.google.gerrit.server.events.RefEvent; +import com.google.inject.Inject; +import java.time.Duration; +import java.util.List; +import java.util.Optional; +import java.util.function.Supplier; +import org.junit.Before; +import org.junit.Test; + +@UseLocalDisk +@Sandboxed +@TestPlugin( + name = "replication", + sysModule = "com.googlesource.gerrit.plugins.replication.ReplicationModule") +public class ReplicationEventsIT extends ReplicationDaemon { + private static final Duration TEST_POST_EVENT_TIMEOUT = Duration.ofSeconds(1); + + @Inject private DynamicItem<EventDispatcher> eventDispatcher; + private TestDispatcher testDispatcher; + + @Before + public void setup() throws Exception { + initConfig(); + setReplicationDestination( + "remote1", + "suffix1", + Optional.of("not-used-project")); // Simulates a full replication.config initialization + setUpTestPlugin(); + testDispatcher = new TestDispatcher(); + eventDispatcher.set(testDispatcher, eventDispatcher.getPluginName()); + } + + @Test + public void replicateNewChangeSendsEvents() throws Exception { + Project.NameKey targetProject = createTestProject(project + "replica"); + + setReplicationDestination("foo", "replica", ALL_PROJECTS); + reloadConfig(); + + Result pushResult = createChange(); + String sourceRef = pushResult.getPatchSet().refName(); + String metaRef = pushResult.getChange().notes().getRefName(); + BranchNameKey changeBranch = BranchNameKey.create(project, sourceRef); + BranchNameKey metaBranch = BranchNameKey.create(project, metaRef); + + assertThat(testDispatcher.getEvents(changeBranch, ReplicationScheduledEvent.class)).hasSize(1); + assertThat(testDispatcher.getEvents(metaBranch, ReplicationScheduledEvent.class)).hasSize(1); + + isPushCompleted(targetProject, sourceRef, TEST_PUSH_TIMEOUT); + isPushCompleted(targetProject, metaRef, TEST_PUSH_TIMEOUT); + + waitForRefEvent(() -> testDispatcher.getEvents(RefReplicatedEvent.class), metaRef); + waitForRefEvent(() -> testDispatcher.getEvents(RefReplicatedEvent.class), sourceRef); + assertThat(testDispatcher.getEvents(RefReplicatedEvent.class).size()).isEqualTo(2); + + waitForRefEvent(() -> testDispatcher.getEvents(RefReplicationDoneEvent.class), metaRef); + waitForRefEvent(() -> testDispatcher.getEvents(RefReplicationDoneEvent.class), sourceRef); + assertThat(testDispatcher.getEvents(RefReplicationDoneEvent.class).size()).isEqualTo(2); + } + + @Test + public void replicateNewBranchSendsEvents() throws Exception { + setReplicationDestination("foo", "replica", ALL_PROJECTS); + reloadConfig(); + + Project.NameKey targetProject = createTestProject(project + "replica"); + String newBranch = "refs/heads/mybranch"; + BranchNameKey branchName = BranchNameKey.create(project, newBranch); + String master = "refs/heads/master"; + BranchInput input = new BranchInput(); + input.revision = master; + gApi.projects().name(project.get()).branch(newBranch).create(input); + + assertThat(testDispatcher.getEvents(branchName, ReplicationScheduledEvent.class)).hasSize(1); + + isPushCompleted(targetProject, newBranch, TEST_PUSH_TIMEOUT); + + waitForRefEvent(() -> testDispatcher.getEvents(RefReplicatedEvent.class), newBranch); + assertThat(testDispatcher.getEvents(RefReplicatedEvent.class).size()).isEqualTo(1); + + waitForRefEvent(() -> testDispatcher.getEvents(RefReplicationDoneEvent.class), newBranch); + assertThat(testDispatcher.getEvents(RefReplicationDoneEvent.class).size()).isEqualTo(1); + } + + private <T extends RefEvent> void waitForRefEvent(Supplier<List<T>> events, String refName) + throws InterruptedException { + WaitUtil.waitUntil( + () -> events.get().stream().filter(e -> refName.equals(e.getRefName())).count() == 1, + TEST_POST_EVENT_TIMEOUT); + } +}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/TestDispatcher.java b/src/test/java/com/googlesource/gerrit/plugins/replication/TestDispatcher.java new file mode 100644 index 0000000..bc5c35c --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/TestDispatcher.java
@@ -0,0 +1,63 @@ +// 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.googlesource.gerrit.plugins.replication; + +import com.google.gerrit.entities.BranchNameKey; +import com.google.gerrit.entities.Change; +import com.google.gerrit.entities.Project; +import com.google.gerrit.server.events.ChangeEvent; +import com.google.gerrit.server.events.Event; +import com.google.gerrit.server.events.EventDispatcher; +import com.google.gerrit.server.events.ProjectEvent; +import com.google.gerrit.server.events.RefEvent; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +public class TestDispatcher implements EventDispatcher { + private final List<RefEvent> refEvents = new LinkedList<>(); + private final List<Event> events = new LinkedList<>(); + + @Override + public void postEvent(Change change, ChangeEvent event) {} // Not used in replication + + @Override + public void postEvent(BranchNameKey branchName, RefEvent event) { + refEvents.add(event); + } + + @Override + public void postEvent( + Project.NameKey projectName, ProjectEvent event) {} // Not used in replication + + @Override + public void postEvent(Event event) { + events.add(event); + } + + public List<RefEvent> getEvents(BranchNameKey branch, Class<? extends RefEvent> clazz) { + return getEvents(branch).stream().filter(clazz::isInstance).collect(Collectors.toList()); + } + + public <T extends RefEvent> List<T> getEvents(Class<T> clazz) { + return events.stream().filter(clazz::isInstance).map(clazz::cast).collect(Collectors.toList()); + } + + private List<RefEvent> getEvents(BranchNameKey branch) { + return refEvents.stream() + .filter(e -> e.getBranchNameKey().equals(branch)) + .collect(Collectors.toList()); + } +}