Adding concurrent locks/reclaiming locks tests Change-Id: Ia5b22d1f4fb83c85a2e14de144afcd1f983a7b4e
diff --git a/src/test/java/com/googlesource/gerrit/plugins/spannerrefdb/LockTest.java b/src/test/java/com/googlesource/gerrit/plugins/spannerrefdb/LockTest.java index cd5d65c..4f03f64 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/spannerrefdb/LockTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/spannerrefdb/LockTest.java
@@ -26,6 +26,10 @@ import com.google.gerrit.entities.Project; import java.util.Arrays; import java.util.Collections; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -117,6 +121,44 @@ .contains(String.format("Unable to lock ref %s on project %s", REF_NAME, PROJECT_NAME_KEY)); } + @Test + public void concurrentLocks_OnlyOneSuccess() throws Exception { + CyclicBarrier cyclicBarrier = new CyclicBarrier(2); + ExecutorService pool = Executors.newFixedThreadPool(2); + + for (int i = 0; i < 10; i++) { + Future<Boolean> f1 = pool.submit(() -> tryLockAwaitBarrier(cyclicBarrier)); + Future<Boolean> f2 = pool.submit(() -> tryLockAwaitBarrier(cyclicBarrier)); + assertThat(f1.get()).isNotEqualTo(f2.get()); + } + pool.shutdown(); + } + + @Test + public void concurrentReclamations_OnlyOneSuccess() throws Exception { + Timestamp staleTimestamp = Timestamp.ofTimeSecondsAndNanos(0, 0); + CyclicBarrier cyclicBarrier = new CyclicBarrier(2); + ExecutorService pool = Executors.newFixedThreadPool(2); + + for (int i = 0; i < 10; i++) { + insertLockRow(staleTimestamp); + Future<Boolean> f1 = pool.submit(() -> tryLockAwaitBarrier(cyclicBarrier)); + Future<Boolean> f2 = pool.submit(() -> tryLockAwaitBarrier(cyclicBarrier)); + assertThat(f1.get()).isNotEqualTo(f2.get()); + } + pool.shutdown(); + } + + private boolean tryLockAwaitBarrier(CyclicBarrier barrier) throws Exception { + try (AutoCloseable refLock = refDb.lockRef(PROJECT_NAME_KEY, REF_NAME)) { + barrier.await(); + return true; + } catch (GlobalRefDbLockException e) { + barrier.await(); + } + return false; + } + private Timestamp getLockTimestamp(Project.NameKey project, String refName, String column) { Struct row = getLockRow(project, refName); return row != null ? row.getTimestamp(column) : null;