From 68760ec5da43f8f871872155251ba8b8e33902c8 Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Mon, 7 May 2018 13:00:50 -0400 Subject: [PATCH] Add failing test for core cache deadlock The core cache implementation has a deadlock bug. This commit adds a failing test case. --- .../common/cache/CacheTests.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/server/src/test/java/org/elasticsearch/common/cache/CacheTests.java b/server/src/test/java/org/elasticsearch/common/cache/CacheTests.java index 773585cc3b4..dd376dd20b4 100644 --- a/server/src/test/java/org/elasticsearch/common/cache/CacheTests.java +++ b/server/src/test/java/org/elasticsearch/common/cache/CacheTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.common.cache; +import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.test.ESTestCase; import org.junit.Before; @@ -343,6 +344,37 @@ public class CacheTests extends ESTestCase { assertEquals(numberOfEntries, cache.stats().getEvictions()); } + @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/30428") + public void testComputeIfAbsentDeadlock() throws BrokenBarrierException, InterruptedException { + final int numberOfThreads = randomIntBetween(2, 32); + final Cache cache = CacheBuilder.builder().setExpireAfterAccess(TimeValue.timeValueNanos(1)).build(); + + final CyclicBarrier barrier = new CyclicBarrier(1 + numberOfThreads); + for (int i = 0; i < numberOfThreads; i++) { + final Thread thread = new Thread(() -> { + try { + barrier.await(); + for (int j = 0; j < numberOfEntries; j++) { + try { + cache.computeIfAbsent(0, k -> Integer.toString(k)); + } catch (final ExecutionException e) { + throw new AssertionError(e); + } + } + barrier.await(); + } catch (final BrokenBarrierException | InterruptedException e) { + throw new AssertionError(e); + } + }); + thread.start(); + } + + // wait for all threads to be ready + barrier.await(); + // wait for all threads to finish + barrier.await(); + } + // randomly promote some entries, step the clock forward, then check that the promoted entries remain and the // non-promoted entries were removed public void testPromotion() {