Skip to content

Commit

Permalink
Restore zero capacity support in ConcurrentLruCache
Browse files Browse the repository at this point in the history
Since the rewrite of ConcurrentLruCache in Spring Framework 6.0, an
attempt to create a ConcurrentLruCache with zero capacity results in an
IllegalArgumentException even though the documentation states that zero
capacity indicates "no caching, always generating a new value".

This commit restores the ability to configure a ConcurrentLruCache with
zero capacity and introduces corresponding tests (which were first
verified against the 5.3.x branch to ensure backward compatibility).

See gh-26320
Closes gh-31317
  • Loading branch information
sbrannen committed Sep 27, 2023
1 parent a37abd5 commit 06658c3
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -81,7 +81,7 @@ public ConcurrentLruCache(int capacity, Function<K, V> generator) {
}

private ConcurrentLruCache(int capacity, Function<K, V> generator, int concurrencyLevel) {
Assert.isTrue(capacity > 0, "Capacity must be > 0");
Assert.isTrue(capacity >= 0, "Capacity must be >= 0");
this.capacity = capacity;
this.cache = new ConcurrentHashMap<>(16, 0.75f, concurrencyLevel);
this.generator = generator;
Expand All @@ -95,6 +95,9 @@ private ConcurrentLruCache(int capacity, Function<K, V> generator, int concurren
* @return the cached or newly generated value
*/
public V get(K key) {
if (this.capacity == 0) {
return this.generator.apply(key);
}
final Node<K, V> node = this.cache.get(key);
if (node == null) {
V value = this.generator.apply(key);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -22,13 +22,38 @@

/**
* Tests for {@link ConcurrentLruCache}.
*
* @author Juergen Hoeller
* @author Sam Brannen
*/
class ConcurrentLruCacheTests {

private final ConcurrentLruCache<String, String> cache = new ConcurrentLruCache<>(2, key -> key + "value");


@Test
void zeroCapacity() {
ConcurrentLruCache<String, String> cache = new ConcurrentLruCache<>(0, key -> key + "value");

assertThat(cache.capacity()).isZero();
assertThat(cache.size()).isZero();

assertThat(cache.get("k1")).isEqualTo("k1value");
assertThat(cache.size()).isZero();
assertThat(cache.contains("k1")).isFalse();

assertThat(cache.get("k2")).isEqualTo("k2value");
assertThat(cache.size()).isZero();
assertThat(cache.contains("k1")).isFalse();
assertThat(cache.contains("k2")).isFalse();

assertThat(cache.get("k3")).isEqualTo("k3value");
assertThat(cache.size()).isZero();
assertThat(cache.contains("k1")).isFalse();
assertThat(cache.contains("k2")).isFalse();
assertThat(cache.contains("k3")).isFalse();
}

@Test
void getAndSize() {
assertThat(this.cache.capacity()).isEqualTo(2);
Expand Down

0 comments on commit 06658c3

Please sign in to comment.