ReplicationTasksStorage: Add unit tests Change-Id: I164426e70937bc3c4ac426be3056a01e9229746b
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorage.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorage.java index b1fbb10..bfb7e95 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorage.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorage.java
@@ -64,7 +64,12 @@ @Inject ReplicationTasksStorage(ReplicationConfig config) { - refUpdates = config.getEventsDirectory().resolve("ref-updates"); + this(config.getEventsDirectory().resolve("ref-updates")); + } + + @VisibleForTesting + public ReplicationTasksStorage(Path refUpdates) { + this.refUpdates = refUpdates; } public String persist(ReplicateRefUpdate r) {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorageTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorageTest.java new file mode 100644 index 0000000..3ee85d7 --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorageTest.java
@@ -0,0 +1,227 @@ +// 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 org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +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.Objects; +import org.eclipse.jgit.transport.URIish; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class ReplicationTasksStorageTest { + protected static final String PROJECT = "myProject"; + protected static final String REF = "myRef"; + protected static final String REMOTE = "myDest"; + protected static final URIish URISH = getUrish("http://example.com/" + PROJECT + ".git"); + protected static final ReplicateRefUpdate REF_UPDATE = + new ReplicateRefUpdate(PROJECT, REF, URISH, REMOTE); + + protected ReplicationTasksStorage storage; + protected FileSystem fileSystem; + protected Path storageSite; + + @Before + public void setUp() throws Exception { + fileSystem = Jimfs.newFileSystem(Configuration.unix()); + storageSite = fileSystem.getPath("replication_site"); + storage = new ReplicationTasksStorage(storageSite); + } + + @After + public void tearDown() throws Exception { + fileSystem.close(); + } + + @Test + public void canListEmptyStorage() throws Exception { + assertThat(storage.list()).isEmpty(); + } + + @Test + public void canListPersistedUpdate() throws Exception { + storage.persist(REF_UPDATE); + assertContainsExactly(storage, REF_UPDATE); + } + + @Test + public void canDeletePersistedUpdate() throws Exception { + storage.persist(REF_UPDATE); + storage.delete(REF_UPDATE); + assertThat(storage.list()).isEmpty(); + } + + @Test + public void instancesOfTheSameStorageHaveTheSameElements() throws Exception { + ReplicationTasksStorage persistedView = new ReplicationTasksStorage(storageSite); + + assertThat(storage.list()).isEmpty(); + assertThat(persistedView.list()).isEmpty(); + + storage.persist(REF_UPDATE); + assertContainsExactly(storage, REF_UPDATE); + assertContainsExactly(persistedView, REF_UPDATE); + + storage.delete(REF_UPDATE); + assertThat(storage.list()).isEmpty(); + assertThat(persistedView.list()).isEmpty(); + } + + @Test + public void sameRefUpdatePersistedTwiceIsStoredOnce() throws Exception { + String key = storage.persist(REF_UPDATE); + String secondKey = storage.persist(REF_UPDATE); + assertEquals(key, secondKey); + assertContainsExactly(storage, REF_UPDATE); + } + + @Test + public void canPersistDifferentUris() throws Exception { + ReplicateRefUpdate updateB = + new ReplicateRefUpdate( + PROJECT, + REF, + getUrish("ssh://example.com/" + PROJECT + ".git"), // uses ssh not http + REMOTE); + + String keyA = storage.persist(REF_UPDATE); + String keyB = storage.persist(updateB); + assertThat(storage.list()).hasSize(2); + assertNotEquals(keyA, keyB); + } + + @Test + public void canDeleteDifferentUris() throws Exception { + ReplicateRefUpdate updateB = + new ReplicateRefUpdate( + PROJECT, + REF, + getUrish("ssh://example.com/" + PROJECT + ".git"), // uses ssh not http + REMOTE); + storage.persist(REF_UPDATE); + storage.persist(updateB); + + storage.delete(REF_UPDATE); + assertContainsExactly(storage, updateB); + + storage.delete(updateB); + assertThat(storage.list()).isEmpty(); + } + + @Test + public void differentUrisPersistedTwiceIsStoredOnce() throws Exception { + ReplicateRefUpdate updateB = + new ReplicateRefUpdate( + PROJECT, + REF, + getUrish("ssh://example.com/" + PROJECT + ".git"), // uses ssh not http + REMOTE); + + storage.persist(REF_UPDATE); + storage.persist(updateB); + storage.persist(REF_UPDATE); + storage.persist(updateB); + assertThat(storage.list()).hasSize(2); + } + + @Test + public void canPersistMulipleRefsForSameUri() throws Exception { + ReplicateRefUpdate refA = new ReplicateRefUpdate(PROJECT, "refA", URISH, REMOTE); + ReplicateRefUpdate refB = new ReplicateRefUpdate(PROJECT, "refB", URISH, REMOTE); + + String keyA = storage.persist(refA); + String keyB = storage.persist(refB); + assertThat(storage.list()).hasSize(2); + assertNotEquals(keyA, keyB); + } + + @Test + public void canDeleteMulipleRefsForSameUri() throws Exception { + ReplicateRefUpdate refA = new ReplicateRefUpdate(PROJECT, "refA", URISH, REMOTE); + ReplicateRefUpdate refB = new ReplicateRefUpdate(PROJECT, "refB", URISH, REMOTE); + storage.persist(refA); + storage.persist(refB); + + storage.delete(refA); + assertContainsExactly(storage, refB); + + storage.delete(refB); + assertThat(storage.list()).isEmpty(); + } + + @Test(expected = Test.None.class /* no exception expected */) + public void illegalDeleteNonPersistedIsGraceful() throws Exception { + storage.delete(REF_UPDATE); + } + + @Test(expected = Test.None.class /* no exception expected */) + public void illegalDoubleDeleteIsGraceful() throws Exception { + storage.persist(REF_UPDATE); + storage.delete(REF_UPDATE); + + storage.delete(REF_UPDATE); + } + + @Test(expected = Test.None.class /* no exception expected */) + public void illegalDoubleDeleteDifferentUriIsGraceful() throws Exception { + ReplicateRefUpdate updateB = + new ReplicateRefUpdate( + PROJECT, + REF, + getUrish("ssh://example.com/" + PROJECT + ".git"), // uses ssh not http + REMOTE); + storage.persist(REF_UPDATE); + storage.persist(updateB); + storage.delete(REF_UPDATE); + storage.delete(updateB); + + storage.delete(REF_UPDATE); + storage.delete(updateB); + assertThat(storage.list()).isEmpty(); + } + + private void assertContainsExactly( + ReplicationTasksStorage tasksStorage, ReplicateRefUpdate update) { + assertTrue(equals(tasksStorage.list().get(0), update)); + } + + private boolean equals(ReplicateRefUpdate one, ReplicateRefUpdate two) { + return (one == null && two == null) + || (one != null + && two != null + && Objects.equals(one.project, two.project) + && Objects.equals(one.ref, two.ref) + && Objects.equals(one.remote, two.remote) + && Objects.equals(one.uri, two.uri)); + } + + public static URIish getUrish(String uri) { + try { + return new URIish(uri); + } catch (URISyntaxException e) { + throw new RuntimeException("Cannot instantiate URIish object", e); + } + } +}