/* * Copyright (C) 2011 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.benmanes.caffeine.cache; import static com.github.benmanes.caffeine.cache.Caffeine.UNSET_INT; import static com.github.benmanes.caffeine.cache.CaffeineSpec.parse; import java.util.concurrent.TimeUnit; import com.github.benmanes.caffeine.cache.Caffeine.Strength; import com.google.common.testing.EqualsTester; import junit.framework.TestCase; /** * A port of Guava's CacheBuilderSpecTest. * TODO(user): tests of a few invalid input conditions, boundary conditions. * * @author Adam Winer */ public class CaffeineSpecGuavaTest extends TestCase { public void testParse_empty() { CaffeineSpec spec = parse(""); assertEquals(spec.initialCapacity, UNSET_INT); assertEquals(spec.maximumSize, UNSET_INT); assertEquals(spec.maximumWeight, UNSET_INT); assertNull(spec.keyStrength); assertNull(spec.valueStrength); assertNull(spec.expireAfterAccessTimeUnit); assertNull(spec.expireAfterWriteTimeUnit); assertNull(spec.refreshAfterWriteTimeUnit); assertCaffeineEquivalence(Caffeine.newBuilder(), Caffeine.from(spec)); } public void testParse_initialCapacity() { CaffeineSpec spec = parse("initialCapacity=10"); assertEquals(10, spec.initialCapacity); assertEquals(spec.maximumSize, UNSET_INT); assertEquals(spec.maximumWeight, UNSET_INT); assertNull(spec.keyStrength); assertNull(spec.valueStrength); assertNull(spec.expireAfterWriteTimeUnit); assertNull(spec.expireAfterAccessTimeUnit); assertNull(spec.refreshAfterWriteTimeUnit); assertCaffeineEquivalence( Caffeine.newBuilder().initialCapacity(10), Caffeine.from(spec)); } public void testParse_initialCapacityRepeated() { try { parse("initialCapacity=10, initialCapacity=20"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_maximumSize() { CaffeineSpec spec = parse("maximumSize=9000"); assertEquals(spec.initialCapacity, UNSET_INT); assertEquals(9000, spec.maximumSize); assertNull(spec.keyStrength); assertNull(spec.valueStrength); assertNull(spec.expireAfterWriteTimeUnit); assertNull(spec.expireAfterAccessTimeUnit); assertNull(spec.refreshAfterWriteTimeUnit); assertCaffeineEquivalence( Caffeine.newBuilder().maximumSize(9000), Caffeine.from(spec)); } public void testParse_maximumSizeRepeated() { try { parse("maximumSize=10, maximumSize=20"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_maximumWeight() { CaffeineSpec spec = parse("maximumWeight=9000"); assertEquals(spec.initialCapacity, UNSET_INT); assertEquals(9000, spec.maximumWeight); assertNull(spec.keyStrength); assertNull(spec.valueStrength); assertNull(spec.expireAfterWriteTimeUnit); assertNull(spec.expireAfterAccessTimeUnit); assertNull(spec.refreshAfterWriteTimeUnit); assertCaffeineEquivalence( Caffeine.newBuilder().maximumWeight(9000), Caffeine.from(spec)); } public void testParse_maximumWeightRepeated() { try { parse("maximumWeight=10, maximumWeight=20"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_maximumSizeAndMaximumWeight() { try { parse("maximumSize=10, maximumWeight=20"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_weakKeys() { CaffeineSpec spec = parse("weakKeys"); assertEquals(spec.initialCapacity, UNSET_INT); assertEquals(spec.maximumSize, UNSET_INT); assertEquals(spec.maximumWeight, UNSET_INT); assertEquals(Strength.WEAK, spec.keyStrength); assertNull(spec.valueStrength); assertNull(spec.expireAfterWriteTimeUnit); assertNull(spec.expireAfterAccessTimeUnit); assertNull(spec.refreshAfterWriteTimeUnit); assertCaffeineEquivalence( Caffeine.newBuilder().weakKeys(), Caffeine.from(spec)); } public void testParse_weakKeysCannotHaveValue() { try { parse("weakKeys=true"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_repeatedKeyStrength() { try { parse("weakKeys, weakKeys"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_softValues() { CaffeineSpec spec = parse("softValues"); assertEquals(spec.initialCapacity, UNSET_INT); assertEquals(spec.maximumSize, UNSET_INT); assertEquals(spec.maximumWeight, UNSET_INT); assertNull(spec.keyStrength); assertEquals(Strength.SOFT, spec.valueStrength); assertNull(spec.expireAfterWriteTimeUnit); assertNull(spec.expireAfterAccessTimeUnit); assertNull(spec.refreshAfterWriteTimeUnit); assertCaffeineEquivalence( Caffeine.newBuilder().softValues(), Caffeine.from(spec)); } public void testParse_softValuesCannotHaveValue() { try { parse("softValues=true"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_weakValues() { CaffeineSpec spec = parse("weakValues"); assertEquals(spec.initialCapacity, UNSET_INT); assertEquals(spec.maximumSize, UNSET_INT); assertEquals(spec.maximumWeight, UNSET_INT); assertNull(spec.keyStrength); assertEquals(Strength.WEAK, spec.valueStrength); assertNull(spec.expireAfterWriteTimeUnit); assertNull(spec.expireAfterAccessTimeUnit); assertNull(spec.refreshAfterWriteTimeUnit); assertCaffeineEquivalence( Caffeine.newBuilder().weakValues(), Caffeine.from(spec)); } public void testParse_weakValuesCannotHaveValue() { try { parse("weakValues=true"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_repeatedValueStrength() { try { parse("softValues, softValues"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } try { parse("softValues, weakValues"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } try { parse("weakValues, softValues"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } try { parse("weakValues, weakValues"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_writeExpirationDays() { CaffeineSpec spec = parse("expireAfterWrite=10d"); assertEquals(spec.initialCapacity, UNSET_INT); assertEquals(spec.maximumSize, UNSET_INT); assertEquals(spec.maximumWeight, UNSET_INT); assertNull(spec.keyStrength); assertNull(spec.valueStrength); assertEquals(TimeUnit.DAYS, spec.expireAfterWriteTimeUnit); assertEquals(10L, spec.expireAfterWriteDuration); assertNull(spec.expireAfterAccessTimeUnit); assertNull(spec.refreshAfterWriteTimeUnit); assertCaffeineEquivalence( Caffeine.newBuilder().expireAfterWrite(10L, TimeUnit.DAYS), Caffeine.from(spec)); } public void testParse_writeExpirationHours() { CaffeineSpec spec = parse("expireAfterWrite=150h"); assertEquals(TimeUnit.HOURS, spec.expireAfterWriteTimeUnit); assertEquals(150L, spec.expireAfterWriteDuration); assertCaffeineEquivalence( Caffeine.newBuilder().expireAfterWrite(150L, TimeUnit.HOURS), Caffeine.from(spec)); } public void testParse_writeExpirationMinutes() { CaffeineSpec spec = parse("expireAfterWrite=10m"); assertEquals(TimeUnit.MINUTES, spec.expireAfterWriteTimeUnit); assertEquals(10L, spec.expireAfterWriteDuration); assertCaffeineEquivalence( Caffeine.newBuilder().expireAfterWrite(10L, TimeUnit.MINUTES), Caffeine.from(spec)); } public void testParse_writeExpirationSeconds() { CaffeineSpec spec = parse("expireAfterWrite=10s"); assertEquals(TimeUnit.SECONDS, spec.expireAfterWriteTimeUnit); assertEquals(10L, spec.expireAfterWriteDuration); assertCaffeineEquivalence( Caffeine.newBuilder().expireAfterWrite(10L, TimeUnit.SECONDS), Caffeine.from(spec)); } public void testParse_writeExpirationRepeated() { try { parse( "expireAfterWrite=10s,expireAfterWrite=10m"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_accessExpirationDays() { CaffeineSpec spec = parse("expireAfterAccess=10d"); assertEquals(spec.initialCapacity, UNSET_INT); assertEquals(spec.maximumSize, UNSET_INT); assertEquals(spec.maximumWeight, UNSET_INT); assertNull(spec.keyStrength); assertNull(spec.valueStrength); assertNull(spec.expireAfterWriteTimeUnit); assertEquals(TimeUnit.DAYS, spec.expireAfterAccessTimeUnit); assertEquals(10L, spec.expireAfterAccessDuration); assertCaffeineEquivalence( Caffeine.newBuilder().expireAfterAccess(10L, TimeUnit.DAYS), Caffeine.from(spec)); } public void testParse_accessExpirationHours() { CaffeineSpec spec = parse("expireAfterAccess=150h"); assertEquals(TimeUnit.HOURS, spec.expireAfterAccessTimeUnit); assertEquals(150L, spec.expireAfterAccessDuration); assertCaffeineEquivalence( Caffeine.newBuilder().expireAfterAccess(150L, TimeUnit.HOURS), Caffeine.from(spec)); } public void testParse_accessExpirationMinutes() { CaffeineSpec spec = parse("expireAfterAccess=10m"); assertEquals(TimeUnit.MINUTES, spec.expireAfterAccessTimeUnit); assertEquals(10L, spec.expireAfterAccessDuration); assertCaffeineEquivalence( Caffeine.newBuilder().expireAfterAccess(10L, TimeUnit.MINUTES), Caffeine.from(spec)); } public void testParse_accessExpirationSeconds() { CaffeineSpec spec = parse("expireAfterAccess=10s"); assertEquals(TimeUnit.SECONDS, spec.expireAfterAccessTimeUnit); assertEquals(10L, spec.expireAfterAccessDuration); assertCaffeineEquivalence( Caffeine.newBuilder().expireAfterAccess(10L, TimeUnit.SECONDS), Caffeine.from(spec)); } public void testParse_accessExpirationRepeated() { try { parse( "expireAfterAccess=10s,expireAfterAccess=10m"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_recordStats() { CaffeineSpec spec = parse("recordStats"); assertTrue(spec.recordStats); assertCaffeineEquivalence(Caffeine.newBuilder().recordStats(), Caffeine.from(spec)); } public void testParse_recordStatsValueSpecified() { try { parse("recordStats=True"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_recordStatsRepeated() { try { parse("recordStats,recordStats"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testParse_accessExpirationAndWriteExpiration() { CaffeineSpec spec = parse("expireAfterAccess=10s,expireAfterWrite=9m"); assertEquals(TimeUnit.MINUTES, spec.expireAfterWriteTimeUnit); assertEquals(9L, spec.expireAfterWriteDuration); assertEquals(TimeUnit.SECONDS, spec.expireAfterAccessTimeUnit); assertEquals(10L, spec.expireAfterAccessDuration); assertCaffeineEquivalence( Caffeine.newBuilder() .expireAfterAccess(10L, TimeUnit.SECONDS) .expireAfterWrite(9L, TimeUnit.MINUTES), Caffeine.from(spec)); } public void testParse_multipleKeys() { CaffeineSpec spec = parse("initialCapacity=10,maximumSize=20," + "weakKeys,weakValues,expireAfterAccess=10m,expireAfterWrite=1h"); assertEquals(10, spec.initialCapacity); assertEquals(20, spec.maximumSize); assertEquals(spec.maximumWeight, UNSET_INT); assertEquals(Strength.WEAK, spec.keyStrength); assertEquals(Strength.WEAK, spec.valueStrength); assertEquals(TimeUnit.HOURS, spec.expireAfterWriteTimeUnit); assertEquals(TimeUnit.MINUTES, spec.expireAfterAccessTimeUnit); assertEquals(1L, spec.expireAfterWriteDuration); assertEquals(10L, spec.expireAfterAccessDuration); Caffeine<?, ?> expected = Caffeine.newBuilder() .initialCapacity(10) .maximumSize(20) .weakKeys() .weakValues() .expireAfterAccess(10L, TimeUnit.MINUTES) .expireAfterWrite(1L, TimeUnit.HOURS); assertCaffeineEquivalence(expected, Caffeine.from(spec)); } public void testParse_whitespaceAllowed() { CaffeineSpec spec = parse(" initialCapacity=10,\nmaximumSize=20,\t\r" + "weakKeys \t ,softValues \n , \r expireAfterWrite \t = 15s\n\n"); assertEquals(10, spec.initialCapacity); assertEquals(20, spec.maximumSize); assertEquals(spec.maximumWeight, UNSET_INT); assertEquals(Strength.WEAK, spec.keyStrength); assertEquals(Strength.SOFT, spec.valueStrength); assertEquals(TimeUnit.SECONDS, spec.expireAfterWriteTimeUnit); assertEquals(15L, spec.expireAfterWriteDuration); assertNull(spec.expireAfterAccessTimeUnit); Caffeine<?, ?> expected = Caffeine.newBuilder() .initialCapacity(10) .maximumSize(20) .weakKeys() .softValues() .expireAfterWrite(15L, TimeUnit.SECONDS); assertCaffeineEquivalence(expected, Caffeine.from(spec)); } public void testParse_unknownKey() { try { parse("foo=17"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } // Allowed by Caffeine public void disabled_testParse_extraCommaIsInvalid() { try { parse("weakKeys,"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } try { parse(",weakKeys"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } try { parse("weakKeys,,softValues"); fail("Expected exception"); } catch (IllegalArgumentException expected) { // expected } } public void testEqualsAndHashCode() { new EqualsTester() .addEqualityGroup(parse(""), parse("")) .addEqualityGroup(parse("initialCapacity=7"), parse("initialCapacity=7")) .addEqualityGroup(parse("initialCapacity=15"), parse("initialCapacity=15")) .addEqualityGroup(parse("maximumSize=7"), parse("maximumSize=7")) .addEqualityGroup(parse("maximumSize=15"), parse("maximumSize=15")) .addEqualityGroup(parse("maximumWeight=7"), parse("maximumWeight=7")) .addEqualityGroup(parse("maximumWeight=15"), parse("maximumWeight=15")) .addEqualityGroup(parse("expireAfterAccess=60s"), parse("expireAfterAccess=1m")) .addEqualityGroup(parse("expireAfterAccess=60m"), parse("expireAfterAccess=1h")) .addEqualityGroup(parse("expireAfterWrite=60s"), parse("expireAfterWrite=1m")) .addEqualityGroup(parse("expireAfterWrite=60m"), parse("expireAfterWrite=1h")) .addEqualityGroup(parse("weakKeys"), parse("weakKeys")) .addEqualityGroup(parse("softValues"), parse("softValues")) .addEqualityGroup(parse("weakValues"), parse("weakValues")) .addEqualityGroup(parse("recordStats"), parse("recordStats")) .testEquals(); } public void testMaximumWeight_withWeigher() { Caffeine<Object, Object> builder = Caffeine.from(parse("maximumWeight=9000")); builder.weigher((k, v) -> 42).build(k -> null); } public void testMaximumWeight_withoutWeigher() { Caffeine<Object, Object> builder = Caffeine.from(parse("maximumWeight=9000")); try { builder.build(k -> null); fail(); } catch (IllegalStateException expected) {} } public void testMaximumSize_withWeigher() { Caffeine<Object, Object> builder = Caffeine.from(parse("maximumSize=9000")); builder.weigher((k, v) -> 42).build(k -> null); } public void testMaximumSize_withoutWeigher() { Caffeine<Object, Object> builder = Caffeine.from(parse("maximumSize=9000")); builder.build(k -> null); } public void testCaffeineFrom_string() { Caffeine<?, ?> fromString = Caffeine.from( "initialCapacity=10,maximumSize=20,weakKeys,weakValues,expireAfterAccess=10m"); Caffeine<?, ?> expected = Caffeine.newBuilder() .initialCapacity(10) .maximumSize(20) .weakKeys() .weakValues() .expireAfterAccess(10L, TimeUnit.MINUTES); assertCaffeineEquivalence(expected, fromString); } private static void assertCaffeineEquivalence(Caffeine<?, ?> a, Caffeine<?, ?> b) { assertEquals("expireAfterAccessNanos", a.expireAfterAccessNanos, b.expireAfterAccessNanos); assertEquals("expireAfterWriteNanos", a.expireAfterWriteNanos, b.expireAfterWriteNanos); assertEquals("initialCapacity", a.initialCapacity, b.initialCapacity); assertEquals("maximumSize", a.maximumSize, b.maximumSize); assertEquals("maximumWeight", a.maximumWeight, b.maximumWeight); assertEquals("refreshNanos", a.refreshNanos, b.refreshNanos); assertEquals("keyStrength", a.keyStrength, b.keyStrength); assertEquals("removalListener", a.removalListener, b.removalListener); assertEquals("weigher", a.weigher, b.weigher); assertEquals("valueStrength", a.valueStrength, b.valueStrength); assertEquals("statsCounterSupplier", a.statsCounterSupplier, b.statsCounterSupplier); assertEquals("ticker", a.ticker, b.ticker); assertEquals("recordStats", a.isRecordingStats(), b.isRecordingStats()); } }