| // Copyright (C) 2020 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 static com.googlesource.gerrit.plugins.replication.ReplicationTasksStorageTest.assertNoIncompleteTasks; |
| import static com.googlesource.gerrit.plugins.replication.ReplicationTasksStorageTest.assertThatStream; |
| |
| import com.google.common.jimfs.Configuration; |
| import com.google.common.jimfs.Jimfs; |
| import com.googlesource.gerrit.plugins.replication.ReplicationTasksStorage.ReplicateRefUpdate; |
| import java.net.URISyntaxException; |
| import java.nio.file.FileSystem; |
| import java.nio.file.Path; |
| import java.util.Set; |
| import org.eclipse.jgit.transport.URIish; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| public class ReplicationTasksStorageMPTest { |
| protected static final String PROJECT = "myProject"; |
| protected static final String REF = "myRef"; |
| protected static final String REMOTE = "myDest"; |
| protected static final URIish URISH = |
| ReplicationTasksStorageTest.getUrish("http://example.com/" + PROJECT + ".git"); |
| protected static final ReplicateRefUpdate REF_UPDATE = |
| ReplicateRefUpdate.create(PROJECT, Set.of(REF), URISH, REMOTE); |
| protected static final ReplicateRefUpdate STORED_REF_UPDATE = |
| ReplicateRefUpdate.create(REF_UPDATE, REF_UPDATE.sha1()); |
| protected static final UriUpdates URI_UPDATES = getUriUpdates(REF_UPDATE); |
| |
| protected ReplicationTasksStorage nodeA; |
| protected ReplicationTasksStorage nodeB; |
| protected ReplicationTasksStorage persistedView; |
| protected FileSystem fileSystem; |
| |
| @Before |
| public void setUp() throws Exception { |
| fileSystem = Jimfs.newFileSystem(Configuration.unix()); |
| Path storageSite = fileSystem.getPath("replication_site"); |
| nodeA = new ReplicationTasksStorage(storageSite); |
| nodeB = new ReplicationTasksStorage(storageSite); |
| persistedView = new ReplicationTasksStorage(storageSite); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| persistedView = null; |
| nodeA = null; |
| nodeB = null; |
| fileSystem.close(); |
| } |
| |
| @Test |
| public void sameTaskCreatedByOtherNodeIsDeduped() { |
| nodeA.create(REF_UPDATE); |
| |
| nodeB.create(REF_UPDATE); |
| assertThatStream(persistedView.streamWaiting()).containsExactly(STORED_REF_UPDATE); |
| } |
| |
| @Test |
| public void waitingTaskCanBeCompletedByOtherNode() { |
| nodeA.create(REF_UPDATE); |
| |
| nodeB.start(URI_UPDATES); |
| assertThatStream(persistedView.streamRunning()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeB.finish(URI_UPDATES); |
| assertNoIncompleteTasks(persistedView); |
| } |
| |
| @Test |
| public void resetTaskCanBeCompletedByOtherNode() { |
| nodeA.create(REF_UPDATE); |
| nodeA.start(URI_UPDATES); |
| |
| nodeA.reset(URI_UPDATES); |
| assertThatStream(persistedView.streamWaiting()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeB.start(URI_UPDATES); |
| assertThatStream(persistedView.streamRunning()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeB.finish(URI_UPDATES); |
| assertNoIncompleteTasks(persistedView); |
| } |
| |
| @Test |
| public void resetTaskCanBeResetAndCompletedByOtherNode() { |
| nodeA.create(REF_UPDATE); |
| nodeA.start(URI_UPDATES); |
| nodeA.reset(URI_UPDATES); |
| nodeB.start(URI_UPDATES); |
| |
| nodeB.reset(URI_UPDATES); |
| assertThatStream(persistedView.streamWaiting()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeB.start(URI_UPDATES); |
| assertThatStream(persistedView.streamRunning()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeB.finish(URI_UPDATES); |
| assertNoIncompleteTasks(persistedView); |
| } |
| |
| @Test |
| public void resetTaskCanBeResetByOtherNodeAndCompletedByOriginalNode() { |
| nodeA.create(REF_UPDATE); |
| nodeA.start(URI_UPDATES); |
| nodeA.reset(URI_UPDATES); |
| nodeB.start(URI_UPDATES); |
| nodeB.reset(URI_UPDATES); |
| |
| nodeA.start(URI_UPDATES); |
| assertThatStream(persistedView.streamRunning()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeA.finish(URI_UPDATES); |
| assertNoIncompleteTasks(persistedView); |
| } |
| |
| @Test |
| public void canBeRecoveredAndCompletedByOtherNode() { |
| nodeA.create(REF_UPDATE); |
| nodeA.start(URI_UPDATES); |
| |
| nodeB.recoverAll(); |
| assertThatStream(persistedView.streamWaiting()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeB.start(URI_UPDATES); |
| assertThatStream(persistedView.streamRunning()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeA.finish(URI_UPDATES); |
| // Bug: https://crbug.com/gerrit/12973 |
| // assertContainsExactly(persistedView.listRunning(), REF_UPDATE); |
| |
| nodeB.finish(URI_UPDATES); |
| assertNoIncompleteTasks(persistedView); |
| } |
| |
| @Test |
| public void canBeRecoveredAndCompletedByOtherNodeFastOriginalNode() { |
| nodeA.create(REF_UPDATE); |
| nodeA.start(URI_UPDATES); |
| nodeB.recoverAll(); |
| |
| nodeA.finish(URI_UPDATES); |
| assertThatStream(persistedView.streamWaiting()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeB.start(URI_UPDATES); |
| assertThatStream(persistedView.streamRunning()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeB.finish(URI_UPDATES); |
| assertNoIncompleteTasks(persistedView); |
| } |
| |
| @Test |
| public void canBeRecoveredAndCompletedByOtherNodeSlowOriginalNode() { |
| nodeA.create(REF_UPDATE); |
| nodeA.start(URI_UPDATES); |
| nodeB.recoverAll(); |
| |
| nodeB.start(URI_UPDATES); |
| assertThatStream(persistedView.streamRunning()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeB.finish(URI_UPDATES); |
| ReplicationTasksStorageTest.assertNoIncompleteTasks(persistedView); |
| |
| nodeA.finish(URI_UPDATES); |
| ReplicationTasksStorageTest.assertNoIncompleteTasks(persistedView); |
| } |
| |
| @Test |
| public void multipleNodesCanReplicateSameRef() { |
| nodeA.create(REF_UPDATE); |
| nodeA.start(URI_UPDATES); |
| assertThatStream(persistedView.streamRunning()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeA.finish(URI_UPDATES); |
| assertNoIncompleteTasks(persistedView); |
| |
| nodeB.create(REF_UPDATE); |
| nodeB.start(URI_UPDATES); |
| assertThatStream(persistedView.streamRunning()).containsExactly(STORED_REF_UPDATE); |
| |
| nodeB.finish(URI_UPDATES); |
| assertNoIncompleteTasks(persistedView); |
| } |
| |
| @Test |
| public void duplicateWorkIsNotPerformed() { |
| nodeA.create(REF_UPDATE); |
| nodeB.create(REF_UPDATE); |
| |
| assertThat(nodeA.start(URI_UPDATES)).containsExactly(REF_UPDATE.refs()); |
| assertThatStream(persistedView.streamRunning()).containsExactly(STORED_REF_UPDATE); |
| |
| assertThat(nodeB.start(URI_UPDATES)).isEmpty(); |
| assertThatStream(persistedView.streamRunning()).containsExactly(STORED_REF_UPDATE); |
| } |
| |
| public static UriUpdates getUriUpdates(ReplicationTasksStorage.ReplicateRefUpdate refUpdate) { |
| try { |
| return new TestUriUpdates(refUpdate); |
| } catch (URISyntaxException e) { |
| throw new RuntimeException("Cannot instantiate UriUpdates object", e); |
| } |
| } |
| } |