From 9bf94d413cc04d82c0ded357728a5d0fb7d2cb72 Mon Sep 17 00:00:00 2001 From: Ben Manes Date: Fri, 7 Jul 2017 12:36:29 -0700 Subject: [PATCH] Fix TravisCI build Due to exceeding the 50 minute time limit, the support team was very kind by extending it to 90 minutes. For now, merging this slow tests into the same job for a fuller code coverage report. Moving to a VM instance (vs container) for a beefer machine. This had hung because some Guava tests block indefinitely on CountDownLatches. Since I had switched their tests to use a pool instead of new threads, thread starvation meant no progress could be made. Reverted to ad hoc threads and added a timeout to the awaits(). --- .travis.yml | 5 +- .../benmanes/caffeine/cache/AsyncTest.java | 6 +- gradle.properties.ci | 4 +- gradle/dependencies.gradle | 8 +-- .../google/common/cache/CacheBuilderTest.java | 18 +++--- .../google/common/cache/CacheLoadingTest.java | 61 +++++++++---------- .../src/test/java/jsr166/JSR166TestCase.java | 3 +- .../caffeine/jcache/JCacheProfiler.java | 8 ++- travis.sh | 13 ++-- 9 files changed, 62 insertions(+), 64 deletions(-) diff --git a/.travis.yml b/.travis.yml index 48d8a39c77..4c34b8c33e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: java -sudo: false +sudo: required jdk: - oraclejdk8 @@ -9,8 +9,7 @@ env: - TERM=dumb matrix: - GROUP=analysis - - GROUP=unitTests - - GROUP=slowTests + - GROUP=tests before_install: - cp gradle.properties.ci gradle.properties diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncTest.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncTest.java index 3230d6d23e..c0a320b891 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncTest.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncTest.java @@ -28,7 +28,6 @@ import java.lang.reflect.Constructor; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -38,6 +37,7 @@ import com.github.benmanes.caffeine.cache.Async.AsyncExpiry; import com.github.benmanes.caffeine.testing.Awaits; +import com.github.benmanes.caffeine.testing.ConcurrentTestHarness; /** * @author ben.manes@gmail.com (Ben Manes) @@ -81,7 +81,7 @@ public void getWhenSuccessful_success(CompletableFuture future) { public void getWhenSuccessful_success_async() { CompletableFuture future = new CompletableFuture(); AtomicInteger result = new AtomicInteger(); - ForkJoinPool.commonPool().execute(() -> { + ConcurrentTestHarness.execute(() -> { result.set(1); result.set(Async.getWhenSuccessful(future)); }); @@ -94,7 +94,7 @@ public void getWhenSuccessful_success_async() { public void getWhenSuccessful_fails(CompletableFuture future) { if ((future != null) && !future.isDone()) { AtomicInteger result = new AtomicInteger(); - ForkJoinPool.commonPool().execute(() -> { + ConcurrentTestHarness.execute(() -> { result.set(1); Object value = Async.getWhenSuccessful(future); result.set((value == null) ? 2 : 3); diff --git a/gradle.properties.ci b/gradle.properties.ci index 2869a2dabc..eb955d7cbf 100644 --- a/gradle.properties.ci +++ b/gradle.properties.ci @@ -1,4 +1,4 @@ -org.gradle.jvmargs=-Xmx384m -XX:+UseG1GC -XX:SoftRefLRUPolicyMSPerMB=0 -noverify -org.gradle.daemon=false +org.gradle.jvmargs=-Xmx1024m -XX:+UseG1GC -XX:SoftRefLRUPolicyMSPerMB=0 -noverify +org.gradle.daemon=true nexusUsername= nexusPassword= diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 97de901567..31b5af99e5 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -62,7 +62,7 @@ ext { ehcache3: '3.3.1', elasticSearch: '5.4.0', expiringMap: '0.5.8', - jackrabbit: '1.7.2', + jackrabbit: '1.7.3', jamm: '0.3.1', javaObjectLayout: '0.8', jmh: 1.19, @@ -73,7 +73,7 @@ ext { tcache: '1.0.3', ] pluginVersions = [ - buildscan: '1.7.4', + buildscan: '1.8', buildscanRecipes: '0.2.0', checkstyle: '8.0', coveralls: '2.8.1', @@ -81,9 +81,9 @@ ext { errorProne: '0.0.10', jacoco: '0.7.9', jmh: '0.4.2', - jmhReport: '0.2.0', + jmhReport: '0.4.1', nexus: '2.3.1', - pmd: '5.8.0', + pmd: '5.8.1', propdeps: '0.0.10.RELEASE', semanticVersioning: '1.1.0', shadow: '2.0.1', diff --git a/guava/src/test/java/com/google/common/cache/CacheBuilderTest.java b/guava/src/test/java/com/google/common/cache/CacheBuilderTest.java index 68cb3d0c0d..115883d7bc 100644 --- a/guava/src/test/java/com/google/common/cache/CacheBuilderTest.java +++ b/guava/src/test/java/com/google/common/cache/CacheBuilderTest.java @@ -32,7 +32,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -329,7 +328,6 @@ public void testNullCache() { } @GwtIncompatible("QueuingRemovalListener") - public void testRemovalNotification_clear() throws InterruptedException { // If a clear() happens while a computation is pending, we should not get a removal // notification. @@ -339,7 +337,7 @@ public void testRemovalNotification_clear() throws InterruptedException { CacheLoader computingFunction = new CacheLoader() { @Override public String load(String key) { if (shouldWait.get()) { - Uninterruptibles.awaitUninterruptibly(computingLatch); + assertTrue(Uninterruptibles.awaitUninterruptibly(computingLatch, 300, TimeUnit.MINUTES)); } return key; } @@ -356,19 +354,19 @@ public void testRemovalNotification_clear() throws InterruptedException { final CountDownLatch computationStarted = new CountDownLatch(1); final CountDownLatch computationComplete = new CountDownLatch(1); - ForkJoinPool.commonPool().execute(() -> { + new Thread(() -> { computationStarted.countDown(); cache.getUnchecked("b"); computationComplete.countDown(); - }); + }).start(); // wait for the computingEntry to be created - computationStarted.await(); + assertTrue(computationStarted.await(300, TimeUnit.MINUTES)); cache.invalidateAll(); // let the computation proceed computingLatch.countDown(); // don't check cache.size() until we know the get("b") call is complete - computationComplete.await(); + assertTrue(computationComplete.await(300, TimeUnit.MINUTES)); // At this point, the listener should be holding the seed value (a -> a), and the map should // contain the computed value (b -> b), since the clear() happened before the computation @@ -439,7 +437,7 @@ public void testRemovalNotification_clear_basher() throws InterruptedException { Thread.yield(); } cache.invalidateAll(); - tasksFinished.await(); + assertTrue(tasksFinished.await(300, TimeUnit.MINUTES)); // Check all of the removal notifications we received: they should have had correctly-associated // keys and values. (An earlier bug saw removal notifications for in-progress computations, @@ -525,7 +523,7 @@ public void testRemovalNotification_get_basher() throws InterruptedException { } threadPool.shutdown(); - threadPool.awaitTermination(300, TimeUnit.SECONDS); + assertTrue(threadPool.awaitTermination(300, TimeUnit.SECONDS)); // Since we're not doing any more cache operations, and the cache only expires/evicts when doing // other operations, the cache and the removal queue won't change from this point on. @@ -562,7 +560,7 @@ static final class DelayingIdentityLoader extends CacheLoader { @Override public T load(T key) { if (shouldWait.get()) { - Uninterruptibles.awaitUninterruptibly(delayLatch); + assertTrue(Uninterruptibles.awaitUninterruptibly(delayLatch, 300, TimeUnit.SECONDS)); } return key; } diff --git a/guava/src/test/java/com/google/common/cache/CacheLoadingTest.java b/guava/src/test/java/com/google/common/cache/CacheLoadingTest.java index c70f510221..f1cb2346ca 100644 --- a/guava/src/test/java/com/google/common/cache/CacheLoadingTest.java +++ b/guava/src/test/java/com/google/common/cache/CacheLoadingTest.java @@ -30,7 +30,6 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; -import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -1871,7 +1870,7 @@ private static void testConcurrentLoadingDefault(Caffeine builde new CacheLoader() { @Override public Object load(String key) { callCount.incrementAndGet(); - Uninterruptibles.awaitUninterruptibly(startSignal); + assertTrue(Uninterruptibles.awaitUninterruptibly(startSignal, 300, TimeUnit.SECONDS)); return result; } }); @@ -1900,7 +1899,7 @@ private static void testConcurrentLoadingNull(Caffeine builder) new CacheLoader() { @Override public String load(String key) { callCount.incrementAndGet(); - Uninterruptibles.awaitUninterruptibly(startSignal); + assertTrue(Uninterruptibles.awaitUninterruptibly(startSignal, 300, TimeUnit.SECONDS)); return null; } }); @@ -1938,7 +1937,7 @@ private static void testConcurrentLoadingUncheckedException( new CacheLoader() { @Override public String load(String key) { callCount.incrementAndGet(); - Uninterruptibles.awaitUninterruptibly(startSignal); + assertTrue(Uninterruptibles.awaitUninterruptibly(startSignal, 300, TimeUnit.SECONDS)); throw e; } }); @@ -1979,7 +1978,7 @@ private static void testConcurrentLoadingCheckedException( new CacheLoader() { @Override public String load(String key) throws Exception { callCount.incrementAndGet(); - Uninterruptibles.awaitUninterruptibly(startSignal); + assertTrue(Uninterruptibles.awaitUninterruptibly(startSignal, 300, TimeUnit.SECONDS)); throw e; } }); @@ -2055,7 +2054,7 @@ private static List doConcurrentGet(final LoadingCache cache, } } gettersStartedSignal.countDown(); - gettersComplete.await(); + assertTrue(gettersComplete.await(300, TimeUnit.SECONDS)); List resultList = Lists.newArrayListWithExpectedSize(nThreads); for (int i = 0; i < nThreads; i++) { @@ -2076,7 +2075,7 @@ public void testAsMapDuringLoading() throws InterruptedException, ExecutionExcep @Override public String load(String key) { getStartedSignal.countDown(); - Uninterruptibles.awaitUninterruptibly(letGetFinishSignal); + assertTrue(Uninterruptibles.awaitUninterruptibly(letGetFinishSignal, 300, TimeUnit.SECONDS)); return key + suffix; } }; @@ -2090,16 +2089,16 @@ public String load(String key) { assertFalse(map.containsKey(getKey)); assertSame(refreshKey, map.get(refreshKey)); - ForkJoinPool.commonPool().execute(() -> { + new Thread(() -> { cache.getUnchecked(getKey); getFinishedSignal.countDown(); - }); - ForkJoinPool.commonPool().execute(() -> { + }).start(); + new Thread(() -> { cache.refresh(refreshKey); getFinishedSignal.countDown(); - }); + }).start(); - getStartedSignal.await(); + assertTrue(getStartedSignal.await(300, TimeUnit.SECONDS)); // computation is in progress; asMap shouldn't have changed assertEquals(1, map.size()); @@ -2108,7 +2107,7 @@ public String load(String key) { // let computation complete letGetFinishSignal.countDown(); - getFinishedSignal.await(); + assertTrue(getFinishedSignal.await(300, TimeUnit.SECONDS)); checkNothingLogged(); // asMap view should have been updated @@ -2131,7 +2130,7 @@ public void disabled_testInvalidateDuringLoading() throws InterruptedException, @Override public String load(String key) { computationStarted.countDown(); - Uninterruptibles.awaitUninterruptibly(letGetFinishSignal); + assertTrue(Uninterruptibles.awaitUninterruptibly(letGetFinishSignal, 300, TimeUnit.SECONDS)); return key + suffix; } }; @@ -2141,16 +2140,16 @@ public String load(String key) { ConcurrentMap map = cache.asMap(); map.put(refreshKey, refreshKey); - ForkJoinPool.commonPool().execute(() -> { + new Thread(() -> { cache.getUnchecked(getKey); getFinishedSignal.countDown(); - }); - ForkJoinPool.commonPool().execute(() -> { + }).start(); + new Thread(() -> { cache.refresh(refreshKey); getFinishedSignal.countDown(); - }); + }).start(); - computationStarted.await(); + assertTrue(computationStarted.await(300, TimeUnit.SECONDS)); cache.invalidate(getKey); cache.invalidate(refreshKey); assertFalse(map.containsKey(getKey)); @@ -2158,7 +2157,7 @@ public String load(String key) { // let computation complete letGetFinishSignal.countDown(); - getFinishedSignal.await(); + assertTrue(getFinishedSignal.await(300, TimeUnit.SECONDS)); checkNothingLogged(); // results should be visible @@ -2183,7 +2182,7 @@ public void disabled_testInvalidateAndReloadDuringLoading() @Override public String load(String key) { computationStarted.countDown(); - Uninterruptibles.awaitUninterruptibly(letGetFinishSignal); + assertTrue(Uninterruptibles.awaitUninterruptibly(letGetFinishSignal, 300, TimeUnit.SECONDS)); return key + suffix; } }; @@ -2193,34 +2192,34 @@ public String load(String key) { ConcurrentMap map = cache.asMap(); map.put(refreshKey, refreshKey); - ForkJoinPool.commonPool().execute(() -> { + new Thread(() -> { cache.getUnchecked(getKey); getFinishedSignal.countDown(); - }); - ForkJoinPool.commonPool().execute(() -> { + }).start(); + new Thread(() -> { cache.refresh(refreshKey); getFinishedSignal.countDown(); - }); + }).start(); - computationStarted.await(); + assertTrue(computationStarted.await(300, TimeUnit.SECONDS)); cache.invalidate(getKey); cache.invalidate(refreshKey); assertFalse(map.containsKey(getKey)); assertFalse(map.containsKey(refreshKey)); // start new computations - ForkJoinPool.commonPool().execute(() -> { + new Thread(() -> { cache.getUnchecked(getKey); getFinishedSignal.countDown(); - }); - ForkJoinPool.commonPool().execute(() -> { + }).start(); + new Thread(() -> { cache.refresh(refreshKey); getFinishedSignal.countDown(); - }); + }).start(); // let computation complete letGetFinishSignal.countDown(); - getFinishedSignal.await(); + assertTrue(getFinishedSignal.await(300, TimeUnit.SECONDS)); checkNothingLogged(); // results should be visible diff --git a/guava/src/test/java/jsr166/JSR166TestCase.java b/guava/src/test/java/jsr166/JSR166TestCase.java index 6e7905a460..7b65216691 100644 --- a/guava/src/test/java/jsr166/JSR166TestCase.java +++ b/guava/src/test/java/jsr166/JSR166TestCase.java @@ -44,6 +44,7 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; @@ -1062,7 +1063,7 @@ public Callable latchAwaitingStringTask(final CountDownLatch latch) { @Override protected String realCall() { try { - latch.await(); + assertTrue(latch.await(300, TimeUnit.SECONDS)); } catch (InterruptedException quittingTime) {} return TEST_STRING; }}; diff --git a/jcache/src/test/java/com/github/benmanes/caffeine/jcache/JCacheProfiler.java b/jcache/src/test/java/com/github/benmanes/caffeine/jcache/JCacheProfiler.java index 5be5396ff7..d47592b899 100644 --- a/jcache/src/test/java/com/github/benmanes/caffeine/jcache/JCacheProfiler.java +++ b/jcache/src/test/java/com/github/benmanes/caffeine/jcache/JCacheProfiler.java @@ -18,8 +18,8 @@ import static java.util.Objects.requireNonNull; import java.util.Random; +import java.util.concurrent.Executor; import java.util.concurrent.Executors; -import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.LongAdder; @@ -31,6 +31,7 @@ import com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider; import com.google.common.base.Stopwatch; +import com.google.common.util.concurrent.ThreadFactoryBuilder; /** * A hook for profiling the JCache adapter. @@ -43,6 +44,7 @@ public final class JCacheProfiler { private static final boolean READ = true; private final Cache cache; + private final Executor executor; private final LongAdder count; private final Random random; @@ -53,6 +55,8 @@ public final class JCacheProfiler { CacheManager cacheManager = provider.getCacheManager( provider.getDefaultURI(), provider.getDefaultClassLoader()); cache = cacheManager.createCache("profiler", new MutableConfiguration<>()); + executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder() + .setPriority(Thread.MIN_PRIORITY).setDaemon(true).build()); } public void start() { @@ -73,7 +77,7 @@ public void start() { scheduleStatusTask(); for (int i = 0; i < THREADS; i++) { - ForkJoinPool.commonPool().execute(task); + executor.execute(task); } } diff --git a/travis.sh b/travis.sh index a769886d62..b5ea74c7d4 100755 --- a/travis.sh +++ b/travis.sh @@ -1,5 +1,4 @@ -# travis.sh -#!/bin/sh +#!/bin/bash set -eu @@ -19,21 +18,19 @@ runSlow() { done } -case "$1" in +case "${1:?''}" in analysis) run "./gradlew findbugsMain pmdMain -Dfindbugs -Dpmd --console plain" run "sh -c 'cd examples/stats-metrics && ./gradlew test --console plain'" run "sh -c 'cd examples/write-behind-rxjava && mvn test'" ;; - unitTests) + tests) run "./gradlew check --console plain" - run "./gradlew coveralls uploadArchives -x :caffeine:slowCaffeineTest -x :caffeine:slowGuavaTest --console plain" - ;; - slowTests) runSlow "./gradlew :caffeine:slowCaffeineTest --console plain" runSlow "./gradlew :caffeine:slowGuavaTest --console plain" + run "./gradlew coveralls uploadArchives --console plain" ;; *) - echo $"Usage: $0 {analysis|unitTests|slowTests}" + echo $"Usage: $0 {analysis|tests}" exit 1 esac