diff --git a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java index 97ff1a6a14..1ee026dcc5 100644 --- a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java +++ b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java @@ -1056,7 +1056,7 @@ boolean evictEntry(Node node, RemovalCause cause, long now) { expired |= ((now - n.getWriteTime()) >= expiresAfterWriteNanos()); } if (expiresVariable()) { - expired |= (n.getVariableTime() <= now); + expired |= ((now - node.getVariableTime()) >= 0); } if (!expired) { resurrect[0] = true; diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/ExpirationTest.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/ExpirationTest.java index f7cce7e8b9..a2303f33c1 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/ExpirationTest.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/ExpirationTest.java @@ -67,6 +67,7 @@ import com.github.benmanes.caffeine.cache.testing.CacheSpec.Loader; import com.github.benmanes.caffeine.cache.testing.CacheSpec.Maximum; import com.github.benmanes.caffeine.cache.testing.CacheSpec.Population; +import com.github.benmanes.caffeine.cache.testing.CacheSpec.StartTime; import com.github.benmanes.caffeine.cache.testing.CacheValidationListener; import com.github.benmanes.caffeine.cache.testing.CheckMaxLogLevel; import com.github.benmanes.caffeine.cache.testing.CheckNoStats; @@ -256,9 +257,10 @@ public void get_writeTime(Cache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.MOCKITO }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_insert(Cache cache, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); cache.put(context.firstKey(), context.absentValue()); runVariableExpiration(context); @@ -277,7 +279,8 @@ public void put_insert(Cache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.MOCKITO }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_replace(Cache cache, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); @@ -330,9 +333,10 @@ public void put_weighted(Cache> cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void putAll_insert(Cache cache, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); cache.putAll(Map.of(context.firstKey(), context.absentValue(), context.middleKey(), context.absentValue(), context.lastKey(), context.absentValue())); @@ -346,7 +350,8 @@ public void putAll_insert(Cache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void putAll_replace(Cache cache, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); @@ -373,9 +378,10 @@ public void putAll_replace(Cache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void invalidate(Cache cache, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); cache.invalidate(context.firstKey()); assertThat(context).notifications().withCause(EXPIRED) @@ -387,9 +393,10 @@ public void invalidate(Cache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void invalidateAll_iterable(Cache cache, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); cache.invalidateAll(context.firstMiddleLastKeys()); assertThat(context).notifications().withCause(EXPIRED) @@ -401,7 +408,8 @@ public void invalidateAll_iterable(Cache cache, CacheContext context) mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void invalidateAll_full(Cache cache, CacheContext context) { context.ticker().advance(Duration.ofMinutes(1)); cache.invalidateAll(); @@ -416,9 +424,9 @@ public void invalidateAll_full(Cache cache, CacheContext context) { expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, - expiryTime = Expire.ONE_MINUTE) + expiryTime = Expire.ONE_MINUTE, startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void estimatedSize(Cache cache, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(cache).hasSize(context.initialSize()); } @@ -428,9 +436,9 @@ public void estimatedSize(Cache cache, CacheContext context) { expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, - expiryTime = Expire.ONE_MINUTE) + expiryTime = Expire.ONE_MINUTE, startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void cleanUp(Cache cache, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); cache.cleanUp(); assertThat(cache).isEmpty(); @@ -445,9 +453,10 @@ public void cleanUp(Cache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void refresh(LoadingCache cache, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); Int key = context.firstKey(); assertThat(cache.refresh(key)).succeedsWith(key); @@ -478,7 +487,8 @@ public void getIfPresent_inFlight(AsyncCache cache, CacheContext conte mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void get(AsyncCache cache, CacheContext context) { context.ticker().advance(Duration.ofMinutes(2)); @@ -512,7 +522,8 @@ public void get_writeTime(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiryTime = Expire.ONE_MINUTE, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void get_async(AsyncCache cache, CacheContext context) { var future = cache.get(context.absentKey(), (k, e) -> new CompletableFuture()); context.ticker().advance(Duration.ofMinutes(2)); @@ -551,10 +562,11 @@ public void get_inFlight(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void getAll(AsyncCache cache, CacheContext context) { var keys = context.firstMiddleLastKeys(); - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); cache.getAll(context.firstMiddleLastKeys(), keysToLoad -> Maps.toMap(keysToLoad, identity())).join(); @@ -570,9 +582,10 @@ public void getAll(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_insert(AsyncCache cache, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); cache.put(context.firstKey(), intern(context.absentValue().toFuture())); runVariableExpiration(context); @@ -586,7 +599,8 @@ public void put_insert(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_insert_async(AsyncCache cache, CacheContext context) { var future = new CompletableFuture(); cache.put(context.absentKey(), future); @@ -611,7 +625,8 @@ public void put_insert_async(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_replace(AsyncCache cache, CacheContext context) { var future = context.absentValue().toFuture(); context.ticker().advance(Duration.ofSeconds(30)); @@ -641,9 +656,10 @@ public void put_replace(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void isEmpty(Map map, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.isEmpty()).isFalse(); } @@ -652,9 +668,10 @@ public void isEmpty(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void size(Map map, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.size()).isEqualTo(context.initialSize()); } @@ -663,9 +680,10 @@ public void size(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void containsKey(Map map, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.containsKey(context.firstKey())).isFalse(); } @@ -691,9 +709,10 @@ public void containsKey_inFlight(AsyncCache cache, CacheContext contex mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void containsValue(Map map, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.containsValue(context.original().get(context.firstKey()))).isFalse(); } @@ -717,9 +736,10 @@ public void containsValue_inFlight(AsyncCache cache, CacheContext cont mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void clear(Map map, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); map.clear(); assertThat(context).notifications().withCause(EXPIRED) @@ -748,9 +768,10 @@ public void putIfAbsent_weighted(Map> map, CacheContext context) mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.MOCKITO }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_insert(Map map, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.put(context.firstKey(), context.absentValue())).isNull(); assertThat(map).hasSize(1); @@ -768,7 +789,8 @@ public void put_insert(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.MOCKITO }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_replace(Map map, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); @@ -818,9 +840,10 @@ public void put_inFlight(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void replace(Map map, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.replace(context.firstKey(), context.absentValue())).isNull(); if (!map.isEmpty()) { @@ -836,11 +859,12 @@ public void replace(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void replace_updated(Map map, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); assertThat(map.replace(context.firstKey(), context.absentValue())).isNotNull(); - context.ticker().advance(Duration.ofSeconds(30)); + context.ticker().advance(Duration.ofSeconds(45)); context.cleanUp(); assertThat(map).hasSize(1); @@ -868,10 +892,11 @@ public void replace_inFlight(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void replaceConditionally(Map map, CacheContext context) { Int key = context.firstKey(); - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.replace(key, context.original().get(key), context.absentValue())).isFalse(); if (!map.isEmpty()) { @@ -887,12 +912,13 @@ public void replaceConditionally(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void replaceConditionally_updated(Map map, CacheContext context) { Int key = context.firstKey(); context.ticker().advance(Duration.ofSeconds(30)); assertThat(map.replace(key, context.original().get(key), context.absentValue())).isTrue(); - context.ticker().advance(Duration.ofSeconds(30)); + context.ticker().advance(Duration.ofSeconds(45)); context.cleanUp(); assertThat(map).hasSize(1); @@ -920,9 +946,10 @@ public void replaceConditionally_inFlight(AsyncCache cache, CacheConte mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void remove(Map map, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.remove(context.firstKey())).isNull(); assertThat(context).notifications().withCause(EXPIRED) .contains(context.original()).exclusively(); @@ -950,10 +977,11 @@ public void remove_inFlight(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void removeConditionally(Map map, CacheContext context) { Int key = context.firstKey(); - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.remove(key, context.original().get(key))).isFalse(); assertThat(context).notifications().withCause(EXPIRED) @@ -982,10 +1010,11 @@ public void removeConditionally_inFlight(AsyncCache cache, CacheContex mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.MOCKITO }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void computeIfAbsent_prescreen(Map map, CacheContext context) { Int key = context.firstKey(); - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); var result = map.computeIfAbsent(key, k -> context.absentValue()); assertThat(result).isEqualTo(context.absentValue()); @@ -1004,9 +1033,10 @@ public void computeIfAbsent_prescreen(Map map, CacheContext context) { expiryTime = Expire.ONE_MINUTE, mustExpireWithAnyOf = {AFTER_ACCESS, AFTER_WRITE, VARIABLE}, expiry = {CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS}, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void computeIfAbsent_expiresInCompute(Map map, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.computeIfAbsent(context.firstKey(), k -> null)).isNull(); assertThat(context.cache()).whenCleanedUp().isEmpty(); @@ -1053,7 +1083,8 @@ public void computeIfAbsent_writeTime(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.ACCESS, CacheExpiry.WRITE }, expireAfterAccess = { Expire.DISABLED, Expire.ONE_MINUTE }, - expireAfterWrite = { Expire.DISABLED, Expire.ONE_MINUTE }) + expireAfterWrite = { Expire.DISABLED, Expire.ONE_MINUTE }, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void computeIfAbsent_error(Cache cache, CacheContext context) { context.ticker().advance(Duration.ofMinutes(2)); assertThrows(IllegalStateException.class, () -> { @@ -1094,9 +1125,10 @@ public void computeIfAbsent_inFlight(AsyncCache cache, CacheContext co mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.MOCKITO }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void computeIfPresent_prescreen(Map map, CacheContext context) { - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.computeIfPresent(context.firstKey(), (k, v) -> { throw new AssertionError("Should never be called"); })).isNull(); @@ -1119,7 +1151,8 @@ public void computeIfPresent_prescreen(Map map, CacheContext context) expiryTime = Expire.ONE_MINUTE, mustExpireWithAnyOf = {AFTER_ACCESS, AFTER_WRITE, VARIABLE}, expiry = {CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS}, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void computeIfPresent_expiresInCompute(Map map, CacheContext context) { context.ticker().advance(Duration.ofSeconds(59)); context.ticker().setAutoIncrementStep(Duration.ofSeconds(1)); @@ -1208,11 +1241,12 @@ public void computeIfPresent_inFlight(AsyncCache cache, CacheContext c mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.MOCKITO }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void compute(Map map, CacheContext context) { Int key = context.firstKey(); Int value = context.absentValue(); - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.compute(key, (k, v) -> { assertThat(v).isNull(); return value; @@ -1275,7 +1309,8 @@ public void compute_writeTime(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.ACCESS, CacheExpiry.WRITE }, expireAfterAccess = { Expire.DISABLED, Expire.ONE_MINUTE }, - expireAfterWrite = { Expire.DISABLED, Expire.ONE_MINUTE }) + expireAfterWrite = { Expire.DISABLED, Expire.ONE_MINUTE }, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void compute_absent_error(Cache cache, CacheContext context) { context.ticker().advance(Duration.ofMinutes(2)); assertThrows(IllegalStateException.class, () -> { @@ -1294,9 +1329,10 @@ public void compute_absent_error(Cache cache, CacheContext context) { @Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, compute = Compute.SYNC, expiryTime = Expire.ONE_MINUTE, mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, - expiry = { CacheExpiry.DISABLED, CacheExpiry.ACCESS, CacheExpiry.WRITE }) + expiry = { CacheExpiry.DISABLED, CacheExpiry.ACCESS, CacheExpiry.WRITE }, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void compute_present_error(Cache cache, CacheContext context) { - context.ticker().advance(Duration.ofSeconds(30)); + context.ticker().advance(Duration.ofMinutes(2)); var access = cache.policy().expireAfterAccess() .flatMap(policy -> policy.ageOf(context.firstKey())); var write = cache.policy().expireAfterWrite() @@ -1349,11 +1385,12 @@ public void compute_inFlight(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void merge(Map map, CacheContext context) { Int key = context.firstKey(); Int value = context.absentValue(); - context.ticker().advance(Duration.ofMinutes(1)); + context.ticker().advance(Duration.ofMinutes(2)); assertThat(map.merge(key, value, (oldValue, v) -> { throw new AssertionError("Should never be called"); })).isEqualTo(value); @@ -1411,7 +1448,8 @@ public void merge_writeTime(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void keySet_toArray(Map map, CacheContext context) { context.ticker().advance(context.expiryTime().duration().multipliedBy(2)); assertThat(map.keySet().toArray(new Int[0])).isEmpty(); @@ -1425,7 +1463,8 @@ public void keySet_toArray(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void keySet_iterator(Map map, CacheContext context) { context.ticker().advance(Duration.ofMinutes(10)); assertThat(map.keySet().iterator().hasNext()).isFalse(); @@ -1439,7 +1478,8 @@ public void keySet_iterator(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void keySet_iterator_traversal(Map map, CacheContext context) { var iterator = map.keySet().iterator(); assertThat(iterator.next()).isNotNull(); @@ -1476,7 +1516,8 @@ public void keySet_inFlight(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void values_toArray(Map map, CacheContext context) { context.ticker().advance(context.expiryTime().duration().multipliedBy(2)); assertThat(map.values().toArray(new Int[0])).isEmpty(); @@ -1490,7 +1531,8 @@ public void values_toArray(Map map, CacheContext context) { mustExpireWithAnyOf = {AFTER_ACCESS, AFTER_WRITE, VARIABLE}, expiry = {CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS}, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void values_iterator(Map map, CacheContext context) { context.ticker().advance(Duration.ofMinutes(10)); assertThat(map.values().iterator().hasNext()).isFalse(); @@ -1504,7 +1546,8 @@ public void values_iterator(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void values_iterator_traversal(Map map, CacheContext context) { var iterator = map.values().iterator(); assertThat(iterator.next()).isNotNull(); @@ -1541,7 +1584,8 @@ public void values_inFlight(AsyncCache cache, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void entrySet_toArray(Map map, CacheContext context) { context.ticker().advance(context.expiryTime().duration().multipliedBy(2)); assertThat(map.entrySet().toArray(new Map.Entry[0])).isEmpty(); @@ -1555,7 +1599,8 @@ public void entrySet_toArray(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void entrySet_iterator(Map map, CacheContext context) { context.ticker().advance(Duration.ofMinutes(10)); assertThat(map.entrySet().iterator().hasNext()).isFalse(); @@ -1569,7 +1614,8 @@ public void entrySet_iterator(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void entrySet_iterator_traversal(Map map, CacheContext context) { var iterator = map.entrySet().iterator(); assertThat(iterator.next()).isNotNull(); @@ -1606,7 +1652,8 @@ public void entrySet_inFlight(AsyncCache cache, CacheContext context) mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void entrySet_equals(Map map, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); map.putAll(context.absent()); @@ -1625,7 +1672,8 @@ public void entrySet_equals(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void entrySet_hashCode(Map map, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); map.putAll(context.absent()); @@ -1642,7 +1690,8 @@ public void entrySet_hashCode(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void equals(Map map, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); map.putAll(context.absent()); @@ -1661,7 +1710,8 @@ public void equals(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void hashCode(Map map, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); map.putAll(context.absent()); @@ -1678,7 +1728,8 @@ public void hashCode(Map map, CacheContext context) { mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void toString(Map map, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); map.putAll(context.absent()); @@ -1703,7 +1754,8 @@ private static Map parseToString(Map map) { expiryTime = Expire.ONE_MINUTE, mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, - expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) + expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void getIfPresentQuietly_expired(Cache cache, CacheContext context) { assertThat(cache.policy().getIfPresentQuietly(context.firstKey())).isNotNull(); context.ticker().advance(Duration.ofMinutes(10)); diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/ExpireAfterVarTest.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/ExpireAfterVarTest.java index aa808ab709..7cd7728996 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/ExpireAfterVarTest.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/ExpireAfterVarTest.java @@ -73,6 +73,7 @@ import com.github.benmanes.caffeine.cache.testing.CacheSpec.Listener; import com.github.benmanes.caffeine.cache.testing.CacheSpec.Loader; import com.github.benmanes.caffeine.cache.testing.CacheSpec.Population; +import com.github.benmanes.caffeine.cache.testing.CacheSpec.StartTime; import com.github.benmanes.caffeine.cache.testing.CacheValidationListener; import com.github.benmanes.caffeine.cache.testing.CheckMaxLogLevel; import com.github.benmanes.caffeine.cache.testing.CheckNoEvictions; @@ -174,7 +175,8 @@ public void getAll_absent(LoadingCache cache, CacheContext context) { @Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, - expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE) + expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_replace(Cache cache, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); @@ -198,7 +200,8 @@ public void put_replace(Cache cache, CacheContext context) { @Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, - expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE) + expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_replace(AsyncCache cache, CacheContext context) { var future = context.absentValue().toFuture(); context.ticker().advance(Duration.ofSeconds(30)); @@ -223,7 +226,8 @@ public void put_replace(AsyncCache cache, CacheContext context) { @Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, - expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE) + expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_replace(Map map, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); @@ -247,7 +251,8 @@ public void put_replace(Map map, CacheContext context) { @Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, - expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE) + expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void putAll_replace(Cache cache, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); @@ -272,11 +277,12 @@ public void putAll_replace(Cache cache, CacheContext context) { @Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, - expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE) + expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void replace_updated(Map map, CacheContext context) { context.ticker().advance(Duration.ofSeconds(30)); assertThat(map.replace(context.firstKey(), context.absentValue())).isNotNull(); - context.ticker().advance(Duration.ofSeconds(30)); + context.ticker().advance(Duration.ofSeconds(45)); context.cleanUp(); assertThat(map).isExhaustivelyEmpty(); @@ -311,12 +317,13 @@ public void replace_expiryFails_async(AsyncCache cache, CacheContext c @Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, - expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE) + expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void replaceConditionally_updated(Map map, CacheContext context) { Int key = context.firstKey(); context.ticker().advance(Duration.ofSeconds(30)); assertThat(map.replace(key, context.original().get(key), context.absentValue())).isTrue(); - context.ticker().advance(Duration.ofSeconds(30)); + context.ticker().advance(Duration.ofSeconds(45)); context.cleanUp(); assertThat(map).isExhaustivelyEmpty(); @@ -1031,7 +1038,8 @@ public void putIfAbsent_excessiveDuration(Cache cache, @Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, - expiry = CacheExpiry.WRITE, expiryTime = Expire.ONE_MINUTE) + expiry = CacheExpiry.WRITE, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void putIfAbsent_insert(Cache cache, CacheContext context, VarExpiration expireAfterVar) { Int key = context.absentKey(); @@ -1049,7 +1057,8 @@ public void putIfAbsent_insert(Cache cache, @Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, - expiry = CacheExpiry.WRITE, expiryTime = Expire.ONE_MINUTE) + expiry = CacheExpiry.WRITE, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void putIfAbsent_present(Cache cache, CacheContext context, VarExpiration expireAfterVar) { Int key = context.firstKey(); @@ -1136,7 +1145,8 @@ public void put_nullDuration(Cache cache, @Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, - expiry = CacheExpiry.WRITE, expiryTime = Expire.ONE_MINUTE) + expiry = CacheExpiry.WRITE, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_insert(Cache cache, CacheContext context, VarExpiration expireAfterVar) { Int key = context.absentKey(); @@ -1154,7 +1164,8 @@ public void put_insert(Cache cache, @Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, - expiry = CacheExpiry.WRITE, expiryTime = Expire.ONE_MINUTE) + expiry = CacheExpiry.WRITE, expiryTime = Expire.ONE_MINUTE, + startTime = {StartTime.RANDOM, StartTime.ONE_MINUTE_FROM_MAX}) public void put_replace(Cache cache, CacheContext context, VarExpiration expireAfterVar) { Int key = context.firstKey(); diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheContext.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheContext.java index 60dfd39c85..5b1c365e95 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheContext.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheContext.java @@ -59,6 +59,7 @@ import com.github.benmanes.caffeine.cache.testing.CacheSpec.Maximum; import com.github.benmanes.caffeine.cache.testing.CacheSpec.Population; import com.github.benmanes.caffeine.cache.testing.CacheSpec.ReferenceType; +import com.github.benmanes.caffeine.cache.testing.CacheSpec.StartTime; import com.github.benmanes.caffeine.cache.testing.CacheSpec.Stats; import com.github.benmanes.caffeine.cache.testing.GuavaCacheFromContext.GuavaLoadingCache; import com.github.benmanes.caffeine.cache.testing.GuavaCacheFromContext.SingleLoader; @@ -98,6 +99,7 @@ public final class CacheContext { final Population population; final Maximum maximumSize; final Scheduler scheduler; + final StartTime startTime; final Expire afterAccess; final Expire afterWrite; final Expire expiryTime; @@ -132,7 +134,7 @@ public CacheContext(CacheContext context) { context.keyStrength, context.valueStrength, context.cacheExecutor, context.cacheScheduler, context.removalListenerType, context.evictionListenerType, context.population, context.isAsyncLoader, context.compute, context.loader, context.implementation, - context.expiryTime); + context.startTime, context.expiryTime); } @SuppressWarnings({"NullAway.Init", "PMD.ExcessiveParameterList", "TooManyParameters"}) @@ -141,7 +143,7 @@ public CacheContext(InitialCapacity initialCapacity, Stats stats, CacheWeigher c Expire refresh, ReferenceType keyStrength, ReferenceType valueStrength, CacheExecutor cacheExecutor, CacheScheduler cacheScheduler, Listener removalListenerType, Listener evictionListenerType, Population population, boolean isAsyncLoader, Compute compute, - Loader loader, Implementation implementation, Expire expiryTime) { + Loader loader, Implementation implementation, StartTime startTime, Expire expiryTime) { this.initialCapacity = requireNonNull(initialCapacity); this.stats = requireNonNull(stats); this.weigher = cacheWeigher.create(); @@ -163,13 +165,14 @@ public CacheContext(InitialCapacity initialCapacity, Stats stats, CacheWeigher c this.population = requireNonNull(population); this.loader = requireNonNull(loader); this.isAsyncLoader = isAsyncLoader; - this.ticker = new SerializableFakeTicker(); this.implementation = requireNonNull(implementation); this.original = new LinkedHashMap<>(); this.initialSize = -1; - this.compute = compute; - this.expiryType = expiryType; - this.expiryTime = expiryTime; + this.compute = requireNonNull(compute); + this.expiryType = requireNonNull(expiryType); + this.expiryTime = requireNonNull(expiryTime); + this.startTime = requireNonNull(startTime); + this.ticker = new SerializableFakeTicker(startTime.create()); this.expiry = (expiryType == CacheExpiry.DISABLED) ? null : expiryType.createExpiry(expiryTime); } @@ -536,9 +539,9 @@ static final class SerializableFakeTicker extends FakeTicker implements Serializ final long startTime; - public SerializableFakeTicker() { - startTime = ThreadLocalRandom.current().nextLong(Long.MIN_VALUE, Long.MAX_VALUE); + public SerializableFakeTicker(long startTime) { advance(Duration.ofNanos(startTime)); + this.startTime = startTime; } } } 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 f0ad656e5d..6bb808d813 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 @@ -38,6 +38,7 @@ import com.github.benmanes.caffeine.cache.testing.CacheSpec.Maximum; import com.github.benmanes.caffeine.cache.testing.CacheSpec.Population; import com.github.benmanes.caffeine.cache.testing.CacheSpec.ReferenceType; +import com.github.benmanes.caffeine.cache.testing.CacheSpec.StartTime; import com.github.benmanes.caffeine.cache.testing.CacheSpec.Stats; import com.github.benmanes.caffeine.testing.Int; import com.google.common.collect.ImmutableList; @@ -98,6 +99,7 @@ private Set> combinations() { 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 startTime = Sets.immutableEnumSet(Arrays.asList(cacheSpec.startTime())); var population = Sets.immutableEnumSet(Arrays.asList(cacheSpec.population())); var maximumSize = Sets.immutableEnumSet(Arrays.asList(cacheSpec.maximumSize())); var implementations = filterTypes(options.implementation(), cacheSpec.implementation()); @@ -135,7 +137,7 @@ private Set> combinations() { return Sets.cartesianProduct(initialCapacity, statistics, weigher, maximumSize, expiry, expireAfterAccess, expireAfterWrite, refreshAfterWrite, keys, values, executor, scheduler, removalListener, evictionListener, population, asyncLoader, computations, loaders, - implementations); + implementations, startTime); } /** Returns the set of options filtered if a specific type is specified. */ @@ -170,6 +172,7 @@ private CacheContext newCacheContext(List combination) { (Compute) combination.get(index++), (Loader) combination.get(index++), (Implementation) combination.get(index++), + (StartTime) combination.get(index), cacheSpec.expiryTime()); } diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheSpec.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheSpec.java index d1d5c7e96d..e0f944a30e 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheSpec.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheSpec.java @@ -42,6 +42,7 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; +import java.util.function.LongSupplier; import java.util.function.Supplier; import org.mockito.Mockito; @@ -795,7 +796,7 @@ public TrackingExecutor create() { /* --------------- Scheduler --------------- */ - /** The executors retrieved from a supplier, each resulting in a new combination. */ + /** The schedulers retrieved from a supplier, each resulting in a new combination. */ CacheScheduler[] scheduler() default { CacheScheduler.DISABLED, }; @@ -818,6 +819,29 @@ public Scheduler create() { } } + /* --------------- Ticker --------------- */ + + /** The starting time retrieved from a supplier, each resulting in a new combination. */ + StartTime[] startTime() default { + StartTime.RANDOM, + }; + + /** The starting time that the ticker can be configured with. */ + enum StartTime { + RANDOM(() -> ThreadLocalRandom.current().nextLong(Long.MIN_VALUE, Long.MAX_VALUE)), + ONE_MINUTE_FROM_MAX(() -> Long.MAX_VALUE - TimeUnit.MINUTES.toNanos(1)); + + private final LongSupplier startTime; + + StartTime(LongSupplier startTime) { + this.startTime = requireNonNull(startTime); + } + + public long create() { + return startTime.getAsLong(); + } + } + /* --------------- Populated --------------- */ /**