ReplicationTasksStorage.Task: Add unit tests Change-Id: Ia3a2cefa55d59e5ee96ccd2bf14c9f669a9bb9d1
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 e75e55b..370d48b 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorage.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorage.java
@@ -205,7 +205,8 @@ } } - private class Task { + @VisibleForTesting + class Task { public final ReplicateRefUpdate update; public final String json; public final String taskKey;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorageTaskTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorageTaskTest.java new file mode 100644 index 0000000..ca69644 --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationTasksStorageTaskTest.java
@@ -0,0 +1,380 @@ +// 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 org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +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 com.googlesource.gerrit.plugins.replication.ReplicationTasksStorage.Task; +import java.net.URISyntaxException; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import org.eclipse.jgit.transport.URIish; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class ReplicationTasksStorageTaskTest { + 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 tasksStorage; + protected FileSystem fileSystem; + + @Before + public void setUp() throws Exception { + fileSystem = Jimfs.newFileSystem(Configuration.unix()); + tasksStorage = new ReplicationTasksStorage(fileSystem.getPath("replication_site")); + } + + @After + public void tearDown() throws Exception { + fileSystem.close(); + } + + @Test + public void createdTaskIsWaiting() throws Exception { + Task original = tasksStorage.new Task(REF_UPDATE); + assertNotWaiting(original); + + Task persistedView = tasksStorage.new Task(REF_UPDATE); + assertNotWaiting(persistedView); + + original.create(); + assertIsWaiting(original); + assertIsWaiting(persistedView); + } + + @Test + public void startedTaskIsRunning() throws Exception { + Task original = tasksStorage.new Task(REF_UPDATE); + + original.create(); + original.start(); + assertNotWaiting(original); + assertIsRunning(original); + + Task persistedView = tasksStorage.new Task(REF_UPDATE); + assertNotWaiting(persistedView); + assertIsRunning(persistedView); + } + + @Test + public void resetTaskIsWaiting() throws Exception { + Task original = tasksStorage.new Task(REF_UPDATE); + + original.create(); + original.start(); + original.reset(); + assertIsWaiting(original); + assertNotRunning(original); + + Task persistedView = tasksStorage.new Task(REF_UPDATE); + assertIsWaiting(persistedView); + assertNotRunning(persistedView); + } + + @Test + public void finishedTaskIsRemoved() throws Exception { + Task original = tasksStorage.new Task(REF_UPDATE); + + original.create(); + original.start(); + original.finish(); + assertNotWaiting(original); + assertNotRunning(original); + + Task persistedView = tasksStorage.new Task(REF_UPDATE); + assertNotWaiting(persistedView); + assertNotRunning(persistedView); + } + + @Test + public void createWaitingTaskIsDeduped() throws Exception { + Task original = tasksStorage.new Task(REF_UPDATE); + String key = original.create(); + + Task secondUpdate = tasksStorage.new Task(REF_UPDATE); + assertEquals(secondUpdate.create(), key); + assertIsWaiting(secondUpdate); + assertIsWaiting(original); + } + + @Test + public void createWaitingTaskWhileTaskIsRunning() throws Exception { + Task original = tasksStorage.new Task(REF_UPDATE); + original.create(); + original.start(); + assertIsRunning(original); + + Task secondUpdate = tasksStorage.new Task(REF_UPDATE); + secondUpdate.create(); + + assertIsWaiting(secondUpdate); + assertIsRunning(original); + } + + @Test + public void canCompleteTwoTasks() throws Exception { + Task original = tasksStorage.new Task(REF_UPDATE); + original.create(); + original.start(); + original.finish(); + + Task secondUpdate = tasksStorage.new Task(REF_UPDATE); + secondUpdate.create(); + assertIsWaiting(secondUpdate); + secondUpdate.start(); + assertIsRunning(secondUpdate); + secondUpdate.finish(); + assertNotWaiting(secondUpdate); + assertNotRunning(secondUpdate); + } + + @Test + public void canStartResetTask() throws Exception { + Task original = tasksStorage.new Task(REF_UPDATE); + + original.create(); + original.start(); + original.reset(); + + Task persistedView = tasksStorage.new Task(REF_UPDATE); + persistedView.start(); + assertIsRunning(persistedView); + assertIsRunning(original); + } + + @Test + public void canResetPreviouslyResetAndStartedTask() throws Exception { + Task original = tasksStorage.new Task(REF_UPDATE); + + original.create(); + original.start(); + original.reset(); + + Task persistedView = tasksStorage.new Task(REF_UPDATE); + persistedView.start(); + persistedView.reset(); + assertIsWaiting(persistedView); + assertIsWaiting(original); + } + + @Test + public void multipleActorsCanUpdateSameTask() throws Exception { + Task persistedView = tasksStorage.new Task(REF_UPDATE); + + Task fromEvent = tasksStorage.new Task(REF_UPDATE); + fromEvent.create(); + assertIsWaiting(persistedView); + + Task fromPusherStart = tasksStorage.new Task(REF_UPDATE); + fromPusherStart.start(); + assertIsRunning(persistedView); + + Task fromPusherEnd = tasksStorage.new Task(REF_UPDATE); + fromPusherEnd.finish(); + assertNotWaiting(persistedView); + assertNotRunning(persistedView); + } + + @Test + public void canHaveTwoWaitingTasksForDifferentRefs() throws Exception { + Task updateA = tasksStorage.new Task(new ReplicateRefUpdate(PROJECT, "refA", URISH, REMOTE)); + Task updateB = tasksStorage.new Task(new ReplicateRefUpdate(PROJECT, "refB", URISH, REMOTE)); + updateA.create(); + updateB.create(); + assertIsWaiting(updateA); + assertIsWaiting(updateB); + } + + @Test + public void canHaveTwoRunningTasksForDifferentRefs() throws Exception { + Task updateA = tasksStorage.new Task(new ReplicateRefUpdate(PROJECT, "refA", URISH, REMOTE)); + Task updateB = tasksStorage.new Task(new ReplicateRefUpdate(PROJECT, "refB", URISH, REMOTE)); + updateA.create(); + updateB.create(); + updateA.start(); + updateB.start(); + assertIsRunning(updateA); + assertIsRunning(updateB); + } + + @Test + public void canHaveTwoWaitingTasksForDifferentProjects() throws Exception { + Task updateA = + tasksStorage + .new Task( + new ReplicateRefUpdate( + "projectA", REF, getUrish("http://example.com/projectA.git"), REMOTE)); + Task updateB = + tasksStorage + .new Task( + new ReplicateRefUpdate( + "projectB", REF, getUrish("http://example.com/projectB.git"), REMOTE)); + updateA.create(); + updateB.create(); + assertIsWaiting(updateA); + assertIsWaiting(updateB); + } + + @Test + public void canHaveTwoRunningTasksForDifferentProjects() throws Exception { + Task updateA = + tasksStorage + .new Task( + new ReplicateRefUpdate( + "projectA", REF, getUrish("http://example.com/projectA.git"), REMOTE)); + Task updateB = + tasksStorage + .new Task( + new ReplicateRefUpdate( + "projectB", REF, getUrish("http://example.com/projectB.git"), REMOTE)); + updateA.create(); + updateB.create(); + updateA.start(); + updateB.start(); + assertIsRunning(updateA); + assertIsRunning(updateB); + } + + @Test + public void canHaveTwoWaitingTasksForDifferentRemotes() throws Exception { + Task updateA = tasksStorage.new Task(new ReplicateRefUpdate(PROJECT, REF, URISH, "remoteA")); + Task updateB = tasksStorage.new Task(new ReplicateRefUpdate(PROJECT, REF, URISH, "remoteB")); + updateA.create(); + updateB.create(); + assertIsWaiting(updateA); + assertIsWaiting(updateB); + } + + @Test + public void canHaveTwoRunningTasksForDifferentRemotes() throws Exception { + Task updateA = tasksStorage.new Task(new ReplicateRefUpdate(PROJECT, REF, URISH, "remoteA")); + Task updateB = tasksStorage.new Task(new ReplicateRefUpdate(PROJECT, REF, URISH, "remoteB")); + updateA.create(); + updateB.create(); + updateA.start(); + updateB.start(); + assertIsRunning(updateA); + assertIsRunning(updateB); + } + + @Test + public void illegalFinishNonRunningTaskIsGraceful() throws Exception { + Task task = tasksStorage.new Task(REF_UPDATE); + task.finish(); + assertNotWaiting(task); + assertNotRunning(task); + } + + @Test + public void illegalResetNonRunningTaskIsGraceful() throws Exception { + Task task = tasksStorage.new Task(REF_UPDATE); + task.reset(); + assertNotWaiting(task); + assertNotRunning(task); + } + + @Test + public void illegalResetFinishedTaskIsGraceful() throws Exception { + Task task = tasksStorage.new Task(REF_UPDATE); + + task.create(); + task.start(); + task.finish(); + task.reset(); + assertNotWaiting(task); + assertNotRunning(task); + } + + @Test + public void illegalFinishFinishedTaskIsGraceful() throws Exception { + Task task = tasksStorage.new Task(REF_UPDATE); + + task.create(); + task.start(); + task.finish(); + task.finish(); + assertNotWaiting(task); + assertNotRunning(task); + } + + @Test + public void illegalFinishResetTaskIsGraceful() throws Exception { + Task original = tasksStorage.new Task(REF_UPDATE); + + original.create(); + original.start(); + original.reset(); + + Task persistedView = tasksStorage.new Task(REF_UPDATE); + persistedView.finish(); + assertIsWaiting(persistedView); + } + + @Test + public void illegalResetResetTaskIsGraceful() throws Exception { + Task original = tasksStorage.new Task(REF_UPDATE); + + original.create(); + original.start(); + original.reset(); + + Task persistedView = tasksStorage.new Task(REF_UPDATE); + persistedView.reset(); + assertIsWaiting(persistedView); + } + + private void assertIsWaiting(Task task) { + assertTrue(whiteBoxIsWaiting(task)); + } + + private void assertNotWaiting(Task task) { + assertFalse(whiteBoxIsWaiting(task)); + } + + private void assertIsRunning(Task task) { + assertTrue(whiteBoxIsRunning(task)); + } + + private void assertNotRunning(Task task) { + assertFalse(whiteBoxIsRunning(task)); + } + + private boolean whiteBoxIsRunning(Task task) { + return Files.exists(task.running); + } + + private boolean whiteBoxIsWaiting(Task task) { + return Files.exists(task.waiting); + } + + public static URIish getUrish(String uri) { + try { + return new URIish(uri); + } catch (URISyntaxException e) { + throw new RuntimeException("Cannot instantiate URIish object", e); + } + } +}