diff --git a/caffeine/build.gradle.kts b/caffeine/build.gradle.kts index f6382ec08b..a916638f1e 100644 --- a/caffeine/build.gradle.kts +++ b/caffeine/build.gradle.kts @@ -23,7 +23,7 @@ sourceSets { } val compileJavaPoetJava by tasks.existing -val javaAgent: Configuration by configurations.creating +val jammAgent: Configuration by configurations.creating val collections4Sources: Configuration by configurations.creating val javaPoetImplementation: Configuration = configurations["javaPoetImplementation"] @@ -48,15 +48,18 @@ dependencies { classifier = "tests" } } + testImplementation(sourceSets["codeGen"].output) + testImplementation(libs.eclipse.collections.testutils) + collections4Sources(libs.commons.collections4) { artifact { classifier = "test-sources" } } - testImplementation(sourceSets["codeGen"].output) - testImplementation(libs.eclipse.collections.testutils) - javaAgent(libs.jamm) + jammAgent(libs.jamm) { + isTransitive = false + } jmh(libs.jamm) jmh(libs.tcache) @@ -264,7 +267,7 @@ tasks.register("memoryOverhead") { "--add-opens", "java.base/java.lang.ref=ALL-UNNAMED", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "--add-opens", "java.base/java.util=ALL-UNNAMED", - "-javaagent:${configurations["javaAgent"].singleFile}") + "-javaagent:${jammAgent.asPath}") } tasks.register("stress") { diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/CaffeineTest.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/CaffeineTest.java index 85e8a45647..7bd8d5d09f 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/CaffeineTest.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/CaffeineTest.java @@ -808,6 +808,7 @@ public void ticker() { Ticker ticker = new FakeTicker()::read; var builder = Caffeine.newBuilder().ticker(ticker); assertThat(builder.ticker).isSameInstanceAs(ticker); + assertThat(builder.getTicker()).isSameInstanceAs(Ticker.disabledTicker()); assertThat(builder.build()).isNotNull(); } diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheGenerator.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheGenerator.java index 7ed1e03004..9366b7cef6 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheGenerator.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheGenerator.java @@ -92,9 +92,21 @@ private Set> combinations() { var keys = filterTypes(options.keys(), cacheSpec.keys()); var values = filterTypes(options.values(), cacheSpec.values()); var statistics = filterTypes(options.stats(), cacheSpec.stats()); + var expiry = Sets.immutableEnumSet(Arrays.asList(cacheSpec.expiry())); var computations = filterTypes(options.compute(), cacheSpec.compute()); var loaders = Sets.immutableEnumSet(Arrays.asList(cacheSpec.loader())); + var weigher = Sets.immutableEnumSet(Arrays.asList(cacheSpec.weigher())); + var executor = Sets.immutableEnumSet(Arrays.asList(cacheSpec.executor())); + var scheduler = Sets.immutableEnumSet(Arrays.asList(cacheSpec.scheduler())); + var population = Sets.immutableEnumSet(Arrays.asList(cacheSpec.population())); + var maximumSize = Sets.immutableEnumSet(Arrays.asList(cacheSpec.maximumSize())); var implementations = filterTypes(options.implementation(), cacheSpec.implementation()); + var initialCapacity = Sets.immutableEnumSet(Arrays.asList(cacheSpec.initialCapacity())); + var removalListener = Sets.immutableEnumSet(Arrays.asList(cacheSpec.removalListener())); + var evictionListener = Sets.immutableEnumSet(Arrays.asList(cacheSpec.evictionListener())); + var expireAfterWrite = Sets.immutableEnumSet(Arrays.asList(cacheSpec.expireAfterWrite())); + var expireAfterAccess = Sets.immutableEnumSet(Arrays.asList(cacheSpec.expireAfterAccess())); + var refreshAfterWrite = Sets.immutableEnumSet(Arrays.asList(cacheSpec.refreshAfterWrite())); if (isAsyncOnly) { values = values.contains(ReferenceType.STRONG) @@ -119,26 +131,11 @@ private Set> combinations() { if (computations.isEmpty() || implementations.isEmpty() || keys.isEmpty() || values.isEmpty()) { return ImmutableSet.of(); } - return Sets.cartesianProduct( - Sets.immutableEnumSet(Arrays.asList(cacheSpec.initialCapacity())), - Sets.immutableEnumSet(statistics), - Sets.immutableEnumSet(Arrays.asList(cacheSpec.weigher())), - Sets.immutableEnumSet(Arrays.asList(cacheSpec.maximumSize())), - Sets.immutableEnumSet(Arrays.asList(cacheSpec.expiry())), - Sets.immutableEnumSet(Arrays.asList(cacheSpec.expireAfterAccess())), - Sets.immutableEnumSet(Arrays.asList(cacheSpec.expireAfterWrite())), - Sets.immutableEnumSet(Arrays.asList(cacheSpec.refreshAfterWrite())), - Sets.immutableEnumSet(keys), - Sets.immutableEnumSet(values), - Sets.immutableEnumSet(Arrays.asList(cacheSpec.executor())), - Sets.immutableEnumSet(Arrays.asList(cacheSpec.scheduler())), - Sets.immutableEnumSet(Arrays.asList(cacheSpec.removalListener())), - Sets.immutableEnumSet(Arrays.asList(cacheSpec.evictionListener())), - Sets.immutableEnumSet(Arrays.asList(cacheSpec.population())), - asyncLoader, - Sets.immutableEnumSet(computations), - Sets.immutableEnumSet(loaders), - Sets.immutableEnumSet(implementations)); + + return Sets.cartesianProduct(initialCapacity, statistics, weigher, maximumSize, expiry, + expireAfterAccess, expireAfterWrite, refreshAfterWrite, keys, values, executor, scheduler, + removalListener, evictionListener, population, asyncLoader, computations, loaders, + implementations); } /** Returns the set of options filtered if a specific type is specified. */ diff --git a/gradle/config/spotbugs/exclude.xml b/gradle/config/spotbugs/exclude.xml index 2b787bc063..7b7c99d0b8 100644 --- a/gradle/config/spotbugs/exclude.xml +++ b/gradle/config/spotbugs/exclude.xml @@ -336,6 +336,11 @@ + + + + + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9a3a8cb9f3..230a125d8b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ eclipse-collections = "12.0.0.M3" ehcache3 = "3.10.8" errorprone = "2.35.1" errorprone-plugin = "4.1.0" -errorprone-support = "0.19.0" +errorprone-support = "0.19.1" expiring-map = "0.5.11" fast-filter = "1.0.2" fastutil = "8.5.15" diff --git a/gradle/plugins/src/main/kotlin/lifecycle/testing.caffeine.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/testing.caffeine.gradle.kts index 06214870cc..56f34e130a 100644 --- a/gradle/plugins/src/main/kotlin/lifecycle/testing.caffeine.gradle.kts +++ b/gradle/plugins/src/main/kotlin/lifecycle/testing.caffeine.gradle.kts @@ -6,6 +6,8 @@ plugins { `java-library` } +val mockitoAgent: Configuration by configurations.creating + dependencies { testImplementation(libs.guava) testImplementation(libs.guice) @@ -25,6 +27,10 @@ dependencies { testRuntimeOnly(libs.junit5.launcher) testRuntimeOnly(libs.bundles.junit.engines) testRuntimeOnly(libs.bundles.osgi.test.runtime) + + mockitoAgent(libs.mockito) { + isTransitive = false + } } tasks.withType().configureEach { @@ -32,6 +38,7 @@ tasks.withType().configureEach { // Use --debug-jvm to remotely attach to the test task jvmArgs("-XX:SoftRefLRUPolicyMSPerMB=0", "-XX:+EnableDynamicAgentLoading", "-Xshare:off") + jvmArgs("-javaagent:${mockitoAgent.asPath}") jvmArgs(defaultJvmArgs()) if (isCI()) { reports.junitXml.includeSystemOutLog = false diff --git a/jcache/src/main/java/com/github/benmanes/caffeine/jcache/CacheFactory.java b/jcache/src/main/java/com/github/benmanes/caffeine/jcache/CacheFactory.java index 543d2aa336..03b4a044dc 100644 --- a/jcache/src/main/java/com/github/benmanes/caffeine/jcache/CacheFactory.java +++ b/jcache/src/main/java/com/github/benmanes/caffeine/jcache/CacheFactory.java @@ -214,12 +214,8 @@ private CacheProxy newCacheProxy() { /** Creates a cache that reads through on a cache miss. */ private CacheProxy newLoadingCacheProxy() { - var factory = config.getCacheLoaderFactory(); - if (factory == null) { - throw new IllegalStateException(); - } - - CacheLoader cacheLoader = factory.create(); + @SuppressWarnings("NullAway") + CacheLoader cacheLoader = config.getCacheLoaderFactory().create(); var adapter = new JCacheLoaderAdapter<>( cacheLoader, dispatcher, expiryPolicy, ticker, statistics); var cache = new LoadingCacheProxy<>(cacheName, executor, cacheManager, config, diff --git a/jcache/src/test/java/com/github/benmanes/caffeine/jcache/integration/CacheWriterTest.java b/jcache/src/test/java/com/github/benmanes/caffeine/jcache/integration/CacheWriterTest.java index 8597625b35..d4e971fdce 100644 --- a/jcache/src/test/java/com/github/benmanes/caffeine/jcache/integration/CacheWriterTest.java +++ b/jcache/src/test/java/com/github/benmanes/caffeine/jcache/integration/CacheWriterTest.java @@ -111,5 +111,13 @@ public void disabled() { DisabledCacheWriter.get().deleteAll(null); } + @Test + public void hasCacheWriter() { + var noWriter = new CaffeineConfiguration<>(jcacheConfiguration) + .setCacheWriterFactory(null); + assertThat(noWriter.hasCacheWriter()).isFalse(); + assertThat(jcacheConfiguration.hasCacheWriter()).isTrue(); + } + interface CloseableCacheWriter extends CacheWriter, Closeable {} }