From 093c0abb0213e08fd7de30105e8acbc6feafd81a Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 11 Dec 2019 13:32:05 +0100 Subject: [PATCH] Add unit test for asynchronous browse --- .../repository/spi/GitBrowseCommandTest.java | 25 +++++++ .../repository/spi/SyncAsyncExecutors.java | 71 +++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBrowseCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBrowseCommandTest.java index 40dfdf2159..0e36c39499 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBrowseCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBrowseCommandTest.java @@ -35,6 +35,7 @@ import org.junit.Test; import sonia.scm.repository.BrowserResult; import sonia.scm.repository.FileObject; import sonia.scm.repository.GitRepositoryConfig; +import sonia.scm.repository.spi.SyncAsyncExecutors.AsyncExecutorStepper; import java.io.IOException; import java.util.Collection; @@ -43,7 +44,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static sonia.scm.repository.spi.SyncAsyncExecutors.stepperAsynchronousExecutor; import static sonia.scm.repository.spi.SyncAsyncExecutors.synchronousExecutor; /** @@ -112,6 +115,28 @@ public class GitBrowseCommandTest extends AbstractGitCommandTestBase { assertEquals("c", c.getPath()); } + @Test + public void testAsynchronousBrowse() throws IOException { + try (AsyncExecutorStepper executor = stepperAsynchronousExecutor()) { + GitBrowseCommand command = new GitBrowseCommand(createContext(), repository, null, executor); + FileObject root = command.getBrowserResult(new BrowseCommandRequest()).getFile(); + assertNotNull(root); + + Collection foList = root.getChildren(); + + FileObject a = findFile(foList, "a.txt"); + + assertFalse(a.isDirectory()); + assertNull("expected empty name before commit could have been read", a.getDescription()); + assertNull("expected empty date before commit could have been read", a.getLastModified()); + + executor.next(); + + assertNotNull("expected correct name after commit could have been read", a.getDescription()); + assertNotNull("expected correct date after commit could have been read", a.getLastModified()); + } + } + @Test public void testBrowseSubDirectory() throws IOException { BrowseCommandRequest request = new BrowseCommandRequest(); diff --git a/scm-test/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutors.java b/scm-test/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutors.java index 15a1bef046..9dbe26403b 100644 --- a/scm-test/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutors.java +++ b/scm-test/src/main/java/sonia/scm/repository/spi/SyncAsyncExecutors.java @@ -1,7 +1,12 @@ package sonia.scm.repository.spi; +import java.io.Closeable; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.Semaphore; import java.util.function.Consumer; +import static sonia.scm.repository.spi.SyncAsyncExecutor.ExecutionType.ASYNCHRONOUS; import static sonia.scm.repository.spi.SyncAsyncExecutor.ExecutionType.SYNCHRONOUS; public final class SyncAsyncExecutors { @@ -20,4 +25,70 @@ public final class SyncAsyncExecutors { } }; } + + public static SyncAsyncExecutor asynchronousExecutor() { + + Executor executor = Executors.newSingleThreadExecutor(); + + return new SyncAsyncExecutor() { + @Override + public ExecutionType execute(Consumer runnable) { + executor.execute(() -> runnable.accept(ASYNCHRONOUS)); + return ASYNCHRONOUS; + } + + @Override + public boolean hasExecutedAllSynchronously() { + return true; + } + }; + } + + public static AsyncExecutorStepper stepperAsynchronousExecutor() { + + Executor executor = Executors.newSingleThreadExecutor(); + Semaphore enterSemaphore = new Semaphore(0); + Semaphore exitSemaphore = new Semaphore(0); + + return new AsyncExecutorStepper() { + @Override + public void close() { + enterSemaphore.release(Integer.MAX_VALUE); + exitSemaphore.release(Integer.MAX_VALUE); + } + + @Override + public ExecutionType execute(Consumer runnable) { + executor.execute(() -> { + try { + enterSemaphore.acquire(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + runnable.accept(ASYNCHRONOUS); + exitSemaphore.release(); + }); + return ASYNCHRONOUS; + } + + @Override + public void next() { + enterSemaphore.release(); + try { + exitSemaphore.acquire(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + @Override + public boolean hasExecutedAllSynchronously() { + return true; + } + }; + } + + public interface AsyncExecutorStepper extends SyncAsyncExecutor, Closeable { + void next(); + } }