1 /*
2  * Copyright (C) 2011 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.cache;
18 
19 import static com.google.common.cache.CacheBuilderSpec.parse;
20 import static com.google.common.cache.TestingWeighers.constantWeigher;
21 
22 import com.google.common.base.Suppliers;
23 import com.google.common.cache.LocalCache.Strength;
24 import com.google.common.testing.EqualsTester;
25 
26 import junit.framework.TestCase;
27 
28 import java.util.concurrent.TimeUnit;
29 
30 /**
31  * Tests CacheBuilderSpec.
32  * TODO(user): tests of a few invalid input conditions, boundary conditions.
33  *
34  * @author Adam Winer
35  */
36 public class CacheBuilderSpecTest extends TestCase {
testParse_empty()37   public void testParse_empty() {
38     CacheBuilderSpec spec = parse("");
39     assertNull(spec.initialCapacity);
40     assertNull(spec.maximumSize);
41     assertNull(spec.maximumWeight);
42     assertNull(spec.concurrencyLevel);
43     assertNull(spec.keyStrength);
44     assertNull(spec.valueStrength);
45     assertNull(spec.writeExpirationTimeUnit);
46     assertNull(spec.accessExpirationTimeUnit);
47     assertCacheBuilderEquivalence(CacheBuilder.newBuilder(), CacheBuilder.from(spec));
48   }
49 
testParse_initialCapacity()50   public void testParse_initialCapacity() {
51     CacheBuilderSpec spec = parse("initialCapacity=10");
52     assertEquals(10, spec.initialCapacity.intValue());
53     assertNull(spec.maximumSize);
54     assertNull(spec.maximumWeight);
55     assertNull(spec.concurrencyLevel);
56     assertNull(spec.keyStrength);
57     assertNull(spec.valueStrength);
58     assertNull(spec.writeExpirationTimeUnit);
59     assertNull(spec.accessExpirationTimeUnit);
60     assertCacheBuilderEquivalence(
61         CacheBuilder.newBuilder().initialCapacity(10), CacheBuilder.from(spec));
62   }
63 
testParse_initialCapacityRepeated()64   public void testParse_initialCapacityRepeated() {
65     try {
66       parse("initialCapacity=10, initialCapacity=20");
67       fail("Expected exception");
68     } catch (IllegalArgumentException expected) {
69       // expected
70     }
71   }
72 
testParse_maximumSize()73   public void testParse_maximumSize() {
74     CacheBuilderSpec spec = parse("maximumSize=9000");
75     assertNull(spec.initialCapacity);
76     assertEquals(9000, spec.maximumSize.longValue());
77     assertNull(spec.concurrencyLevel);
78     assertNull(spec.keyStrength);
79     assertNull(spec.valueStrength);
80     assertNull(spec.writeExpirationTimeUnit);
81     assertNull(spec.accessExpirationTimeUnit);
82     assertCacheBuilderEquivalence(
83         CacheBuilder.newBuilder().maximumSize(9000), CacheBuilder.from(spec));
84   }
85 
testParse_maximumSizeRepeated()86   public void testParse_maximumSizeRepeated() {
87     try {
88       parse("maximumSize=10, maximumSize=20");
89       fail("Expected exception");
90     } catch (IllegalArgumentException expected) {
91       // expected
92     }
93   }
94 
testParse_maximumWeight()95   public void testParse_maximumWeight() {
96     CacheBuilderSpec spec = parse("maximumWeight=9000");
97     assertNull(spec.initialCapacity);
98     assertEquals(9000, spec.maximumWeight.longValue());
99     assertNull(spec.concurrencyLevel);
100     assertNull(spec.keyStrength);
101     assertNull(spec.valueStrength);
102     assertNull(spec.writeExpirationTimeUnit);
103     assertNull(spec.accessExpirationTimeUnit);
104     assertCacheBuilderEquivalence(
105         CacheBuilder.newBuilder().maximumWeight(9000), CacheBuilder.from(spec));
106   }
107 
testParse_maximumWeightRepeated()108   public void testParse_maximumWeightRepeated() {
109     try {
110       parse("maximumWeight=10, maximumWeight=20");
111       fail("Expected exception");
112     } catch (IllegalArgumentException expected) {
113       // expected
114     }
115   }
116 
testParse_maximumSizeAndMaximumWeight()117   public void testParse_maximumSizeAndMaximumWeight() {
118     try {
119       parse("maximumSize=10, maximumWeight=20");
120       fail("Expected exception");
121     } catch (IllegalArgumentException expected) {
122       // expected
123     }
124   }
125 
testParse_concurrencyLevel()126   public void testParse_concurrencyLevel() {
127     CacheBuilderSpec spec = parse("concurrencyLevel=32");
128     assertNull(spec.initialCapacity);
129     assertNull(spec.maximumSize);
130     assertNull(spec.maximumWeight);
131     assertEquals(32, spec.concurrencyLevel.intValue());
132     assertNull(spec.keyStrength);
133     assertNull(spec.valueStrength);
134     assertNull(spec.writeExpirationTimeUnit);
135     assertNull(spec.accessExpirationTimeUnit);
136     assertCacheBuilderEquivalence(
137         CacheBuilder.newBuilder().concurrencyLevel(32), CacheBuilder.from(spec));
138   }
139 
testParse_concurrencyLevelRepeated()140   public void testParse_concurrencyLevelRepeated() {
141     try {
142       parse("concurrencyLevel=10, concurrencyLevel=20");
143       fail("Expected exception");
144     } catch (IllegalArgumentException expected) {
145       // expected
146     }
147   }
148 
testParse_weakKeys()149   public void testParse_weakKeys() {
150     CacheBuilderSpec spec = parse("weakKeys");
151     assertNull(spec.initialCapacity);
152     assertNull(spec.maximumSize);
153     assertNull(spec.maximumWeight);
154     assertNull(spec.concurrencyLevel);
155     assertEquals(Strength.WEAK, spec.keyStrength);
156     assertNull(spec.valueStrength);
157     assertNull(spec.writeExpirationTimeUnit);
158     assertNull(spec.accessExpirationTimeUnit);
159     assertCacheBuilderEquivalence(
160         CacheBuilder.newBuilder().weakKeys(), CacheBuilder.from(spec));
161   }
162 
testParse_weakKeysCannotHaveValue()163   public void testParse_weakKeysCannotHaveValue() {
164     try {
165       parse("weakKeys=true");
166       fail("Expected exception");
167     } catch (IllegalArgumentException expected) {
168       // expected
169     }
170   }
171 
testParse_repeatedKeyStrength()172   public void testParse_repeatedKeyStrength() {
173     try {
174       parse("weakKeys, weakKeys");
175       fail("Expected exception");
176     } catch (IllegalArgumentException expected) {
177       // expected
178     }
179   }
180 
testParse_softValues()181   public void testParse_softValues() {
182     CacheBuilderSpec spec = parse("softValues");
183     assertNull(spec.initialCapacity);
184     assertNull(spec.maximumSize);
185     assertNull(spec.maximumWeight);
186     assertNull(spec.concurrencyLevel);
187     assertNull(spec.keyStrength);
188     assertEquals(Strength.SOFT, spec.valueStrength);
189     assertNull(spec.writeExpirationTimeUnit);
190     assertNull(spec.accessExpirationTimeUnit);
191     assertCacheBuilderEquivalence(
192         CacheBuilder.newBuilder().softValues(), CacheBuilder.from(spec));
193   }
194 
testParse_softValuesCannotHaveValue()195   public void testParse_softValuesCannotHaveValue() {
196     try {
197       parse("softValues=true");
198       fail("Expected exception");
199     } catch (IllegalArgumentException expected) {
200       // expected
201     }
202   }
203 
testParse_weakValues()204   public void testParse_weakValues() {
205     CacheBuilderSpec spec = parse("weakValues");
206     assertNull(spec.initialCapacity);
207     assertNull(spec.maximumSize);
208     assertNull(spec.maximumWeight);
209     assertNull(spec.concurrencyLevel);
210     assertNull(spec.keyStrength);
211     assertEquals(Strength.WEAK, spec.valueStrength);
212     assertNull(spec.writeExpirationTimeUnit);
213     assertNull(spec.accessExpirationTimeUnit);
214     assertCacheBuilderEquivalence(
215         CacheBuilder.newBuilder().weakValues(), CacheBuilder.from(spec));
216   }
217 
testParse_weakValuesCannotHaveValue()218   public void testParse_weakValuesCannotHaveValue() {
219     try {
220       parse("weakValues=true");
221       fail("Expected exception");
222     } catch (IllegalArgumentException expected) {
223       // expected
224     }
225   }
226 
testParse_repeatedValueStrength()227   public void testParse_repeatedValueStrength() {
228     try {
229       parse("softValues, softValues");
230       fail("Expected exception");
231     } catch (IllegalArgumentException expected) {
232       // expected
233     }
234 
235     try {
236       parse("softValues, weakValues");
237       fail("Expected exception");
238     } catch (IllegalArgumentException expected) {
239       // expected
240     }
241 
242     try {
243       parse("weakValues, softValues");
244       fail("Expected exception");
245     } catch (IllegalArgumentException expected) {
246       // expected
247     }
248 
249     try {
250       parse("weakValues, weakValues");
251       fail("Expected exception");
252     } catch (IllegalArgumentException expected) {
253       // expected
254     }
255   }
256 
testParse_writeExpirationDays()257   public void testParse_writeExpirationDays() {
258     CacheBuilderSpec spec = parse("expireAfterWrite=10d");
259     assertNull(spec.initialCapacity);
260     assertNull(spec.maximumSize);
261     assertNull(spec.maximumWeight);
262     assertNull(spec.concurrencyLevel);
263     assertNull(spec.keyStrength);
264     assertNull(spec.valueStrength);
265     assertEquals(TimeUnit.SECONDS, spec.writeExpirationTimeUnit);
266     assertEquals(24 * 60 * 60 * 10L, spec.writeExpirationDuration);
267     assertNull(spec.accessExpirationTimeUnit);
268     assertCacheBuilderEquivalence(
269         CacheBuilder.newBuilder().expireAfterWrite(24 * 60 * 60 * 10L, TimeUnit.SECONDS), CacheBuilder.from(spec));
270   }
271 
testParse_writeExpirationHours()272   public void testParse_writeExpirationHours() {
273     CacheBuilderSpec spec = parse("expireAfterWrite=150h");
274     assertEquals(TimeUnit.SECONDS, spec.writeExpirationTimeUnit);
275     assertEquals(60 * 60 * 150L, spec.writeExpirationDuration);
276     assertCacheBuilderEquivalence(
277         CacheBuilder.newBuilder().expireAfterWrite(60 * 60 * 150L, TimeUnit.SECONDS), CacheBuilder.from(spec));
278   }
279 
testParse_writeExpirationMinutes()280   public void testParse_writeExpirationMinutes() {
281     CacheBuilderSpec spec = parse("expireAfterWrite=10m");
282     assertEquals(TimeUnit.SECONDS, spec.writeExpirationTimeUnit);
283     assertEquals(60 * 10L, spec.writeExpirationDuration);
284     assertCacheBuilderEquivalence(
285         CacheBuilder.newBuilder().expireAfterWrite(60 * 10L, TimeUnit.SECONDS), CacheBuilder.from(spec));
286   }
287 
testParse_writeExpirationSeconds()288   public void testParse_writeExpirationSeconds() {
289     CacheBuilderSpec spec = parse("expireAfterWrite=10s");
290     assertEquals(TimeUnit.SECONDS, spec.writeExpirationTimeUnit);
291     assertEquals(10L, spec.writeExpirationDuration);
292     assertCacheBuilderEquivalence(
293         CacheBuilder.newBuilder().expireAfterWrite(10L, TimeUnit.SECONDS), CacheBuilder.from(spec));
294   }
295 
testParse_writeExpirationRepeated()296   public void testParse_writeExpirationRepeated() {
297     try {
298       parse(
299           "expireAfterWrite=10s,expireAfterWrite=10m");
300       fail("Expected exception");
301     } catch (IllegalArgumentException expected) {
302       // expected
303     }
304   }
305 
testParse_accessExpirationDays()306   public void testParse_accessExpirationDays() {
307     CacheBuilderSpec spec = parse("expireAfterAccess=10d");
308     assertNull(spec.initialCapacity);
309     assertNull(spec.maximumSize);
310     assertNull(spec.maximumWeight);
311     assertNull(spec.concurrencyLevel);
312     assertNull(spec.keyStrength);
313     assertNull(spec.valueStrength);
314     assertNull(spec.writeExpirationTimeUnit);
315     assertEquals(TimeUnit.SECONDS, spec.accessExpirationTimeUnit);
316     assertEquals(24 * 60 * 60 * 10L, spec.accessExpirationDuration);
317     assertCacheBuilderEquivalence(
318         CacheBuilder.newBuilder().expireAfterAccess(24 * 60 * 60 * 10L, TimeUnit.SECONDS), CacheBuilder.from(spec));
319   }
320 
testParse_accessExpirationHours()321   public void testParse_accessExpirationHours() {
322     CacheBuilderSpec spec = parse("expireAfterAccess=150h");
323     assertEquals(TimeUnit.SECONDS, spec.accessExpirationTimeUnit);
324     assertEquals(60 * 60 * 150L, spec.accessExpirationDuration);
325     assertCacheBuilderEquivalence(
326         CacheBuilder.newBuilder().expireAfterAccess(60 * 60 * 150L, TimeUnit.SECONDS), CacheBuilder.from(spec));
327   }
328 
testParse_accessExpirationMinutes()329   public void testParse_accessExpirationMinutes() {
330     CacheBuilderSpec spec = parse("expireAfterAccess=10m");
331     assertEquals(TimeUnit.SECONDS, spec.accessExpirationTimeUnit);
332     assertEquals(60 * 10L, spec.accessExpirationDuration);
333     assertCacheBuilderEquivalence(
334         CacheBuilder.newBuilder().expireAfterAccess(60 * 10L, TimeUnit.SECONDS),
335         CacheBuilder.from(spec));
336   }
337 
testParse_accessExpirationSeconds()338   public void testParse_accessExpirationSeconds() {
339     CacheBuilderSpec spec = parse("expireAfterAccess=10s");
340     assertEquals(TimeUnit.SECONDS, spec.accessExpirationTimeUnit);
341     assertEquals(10L, spec.accessExpirationDuration);
342     assertCacheBuilderEquivalence(
343         CacheBuilder.newBuilder().expireAfterAccess(10L, TimeUnit.SECONDS),
344         CacheBuilder.from(spec));
345   }
346 
testParse_accessExpirationRepeated()347   public void testParse_accessExpirationRepeated() {
348     try {
349       parse(
350           "expireAfterAccess=10s,expireAfterAccess=10m");
351       fail("Expected exception");
352     } catch (IllegalArgumentException expected) {
353       // expected
354     }
355   }
356 
testParse_recordStats()357   public void testParse_recordStats() {
358     CacheBuilderSpec spec = parse("recordStats");
359     assertTrue(spec.recordStats);
360     assertCacheBuilderEquivalence(CacheBuilder.newBuilder().recordStats(), CacheBuilder.from(spec));
361   }
362 
testParse_recordStatsValueSpecified()363   public void testParse_recordStatsValueSpecified() {
364     try {
365       parse("recordStats=True");
366       fail("Expected exception");
367     } catch (IllegalArgumentException expected) {
368       // expected
369     }
370   }
371 
testParse_recordStatsRepeated()372   public void testParse_recordStatsRepeated() {
373     try {
374       parse("recordStats,recordStats");
375       fail("Expected exception");
376     } catch (IllegalArgumentException expected) {
377       // expected
378     }
379   }
380 
testParse_accessExpirationAndWriteExpiration()381   public void testParse_accessExpirationAndWriteExpiration() {
382     CacheBuilderSpec spec = parse("expireAfterAccess=10s,expireAfterWrite=9m");
383     assertEquals(TimeUnit.SECONDS, spec.writeExpirationTimeUnit);
384     assertEquals(60 * 9L, spec.writeExpirationDuration);
385     assertEquals(TimeUnit.SECONDS, spec.accessExpirationTimeUnit);
386     assertEquals(10L, spec.accessExpirationDuration);
387     assertCacheBuilderEquivalence(
388         CacheBuilder.newBuilder()
389           .expireAfterAccess(10L, TimeUnit.SECONDS)
390           .expireAfterWrite(60 * 9L, TimeUnit.SECONDS),
391         CacheBuilder.from(spec));
392   }
393 
testParse_multipleKeys()394   public void testParse_multipleKeys() {
395     CacheBuilderSpec spec = parse("initialCapacity=10,maximumSize=20,concurrencyLevel=30,"
396         + "weakKeys,weakValues,expireAfterAccess=10m,expireAfterWrite=1h");
397     assertEquals(10, spec.initialCapacity.intValue());
398     assertEquals(20, spec.maximumSize.intValue());
399     assertNull(spec.maximumWeight);
400     assertEquals(30, spec.concurrencyLevel.intValue());
401     assertEquals(Strength.WEAK, spec.keyStrength);
402     assertEquals(Strength.WEAK, spec.valueStrength);
403     assertEquals(TimeUnit.SECONDS, spec.writeExpirationTimeUnit);
404     assertEquals(TimeUnit.SECONDS, spec.accessExpirationTimeUnit);
405     assertEquals(60 * 60 * 1L, spec.writeExpirationDuration);
406     assertEquals(60 * 10L, spec.accessExpirationDuration);
407     CacheBuilder<?, ?> expected = CacheBuilder.newBuilder()
408         .initialCapacity(10)
409         .maximumSize(20)
410         .concurrencyLevel(30)
411         .weakKeys()
412         .weakValues()
413         .expireAfterAccess(60 * 10L, TimeUnit.SECONDS)
414         .expireAfterWrite(60 * 60 * 1L, TimeUnit.SECONDS);
415     assertCacheBuilderEquivalence(expected, CacheBuilder.from(spec));
416   }
417 
testParse_whitespaceAllowed()418   public void testParse_whitespaceAllowed() {
419     CacheBuilderSpec spec = parse(" initialCapacity=10,\nmaximumSize=20,\t\r"
420         + "weakKeys \t ,softValues \n , \r  expireAfterWrite \t =  15s\n\n");
421     assertEquals(10, spec.initialCapacity.intValue());
422     assertEquals(20, spec.maximumSize.intValue());
423     assertNull(spec.maximumWeight);
424     assertNull(spec.concurrencyLevel);
425     assertEquals(Strength.WEAK, spec.keyStrength);
426     assertEquals(Strength.SOFT, spec.valueStrength);
427     assertEquals(TimeUnit.SECONDS, spec.writeExpirationTimeUnit);
428     assertEquals(15L, spec.writeExpirationDuration);
429     assertNull(spec.accessExpirationTimeUnit);
430     CacheBuilder<?, ?> expected = CacheBuilder.newBuilder()
431         .initialCapacity(10)
432         .maximumSize(20)
433         .weakKeys()
434         .softValues()
435         .expireAfterWrite(15L, TimeUnit.SECONDS);
436     assertCacheBuilderEquivalence(expected, CacheBuilder.from(spec));
437   }
438 
testParse_unknownKey()439   public void testParse_unknownKey() {
440     try {
441       parse("foo=17");
442       fail("Expected exception");
443     } catch (IllegalArgumentException expected) {
444       // expected
445     }
446   }
447 
testParse_extraCommaIsInvalid()448   public void testParse_extraCommaIsInvalid() {
449     try {
450       parse("weakKeys,");
451       fail("Expected exception");
452     } catch (IllegalArgumentException expected) {
453       // expected
454     }
455 
456     try {
457       parse(",weakKeys");
458       fail("Expected exception");
459     } catch (IllegalArgumentException expected) {
460       // expected
461     }
462 
463     try {
464       parse("weakKeys,,softValues");
465       fail("Expected exception");
466     } catch (IllegalArgumentException expected) {
467       // expected
468     }
469   }
470 
testEqualsAndHashCode()471   public void testEqualsAndHashCode() {
472     new EqualsTester()
473         .addEqualityGroup(parse(""), parse(""))
474         .addEqualityGroup(parse("concurrencyLevel=7"), parse("concurrencyLevel=7"))
475         .addEqualityGroup(parse("concurrencyLevel=15"), parse("concurrencyLevel=15"))
476         .addEqualityGroup(parse("initialCapacity=7"), parse("initialCapacity=7"))
477         .addEqualityGroup(parse("initialCapacity=15"), parse("initialCapacity=15"))
478         .addEqualityGroup(parse("maximumSize=7"), parse("maximumSize=7"))
479         .addEqualityGroup(parse("maximumSize=15"), parse("maximumSize=15"))
480         .addEqualityGroup(parse("maximumWeight=7"), parse("maximumWeight=7"))
481         .addEqualityGroup(parse("maximumWeight=15"), parse("maximumWeight=15"))
482         .addEqualityGroup(parse("expireAfterAccess=60s"), parse("expireAfterAccess=1m"))
483         .addEqualityGroup(parse("expireAfterAccess=60m"), parse("expireAfterAccess=1h"))
484         .addEqualityGroup(parse("expireAfterWrite=60s"), parse("expireAfterWrite=1m"))
485         .addEqualityGroup(parse("expireAfterWrite=60m"), parse("expireAfterWrite=1h"))
486         .addEqualityGroup(parse("weakKeys"), parse("weakKeys"))
487         .addEqualityGroup(parse("softValues"), parse("softValues"))
488         .addEqualityGroup(parse("weakValues"), parse("weakValues"))
489         .addEqualityGroup(parse("recordStats"), parse("recordStats"))
490         .testEquals();
491   }
492 
testMaximumWeight_withWeigher()493   public void testMaximumWeight_withWeigher() {
494     CacheBuilder<Object, Object> builder = CacheBuilder.from(parse("maximumWeight=9000"));
495     builder
496         .weigher(constantWeigher(42))
497         .build(CacheLoader.from(Suppliers.ofInstance(null)));
498   }
499 
testMaximumWeight_withoutWeigher()500   public void testMaximumWeight_withoutWeigher() {
501     CacheBuilder<Object, Object> builder = CacheBuilder.from(parse("maximumWeight=9000"));
502     try {
503       builder.build(CacheLoader.from(Suppliers.ofInstance(null)));
504       fail();
505     } catch (IllegalStateException expected) {}
506   }
507 
testMaximumSize_withWeigher()508   public void testMaximumSize_withWeigher() {
509     CacheBuilder<Object, Object> builder = CacheBuilder.from(parse("maximumSize=9000"));
510     builder
511         .weigher(constantWeigher(42))
512         .build(CacheLoader.from(Suppliers.ofInstance(null)));
513   }
514 
testMaximumSize_withoutWeigher()515   public void testMaximumSize_withoutWeigher() {
516     CacheBuilder<Object, Object> builder = CacheBuilder.from(parse("maximumSize=9000"));
517     builder.build(CacheLoader.from(Suppliers.ofInstance(null)));
518   }
519 
testDisableCaching()520   public void testDisableCaching() {
521     // Functional test: assert that CacheBuilderSpec.disableCaching()
522     // disables caching.  It's irrelevant how it does so.
523     CacheBuilder<Object, Object> builder = CacheBuilder.from(CacheBuilderSpec.disableCaching());
524     Object key = new Object();
525     Object value = new Object();
526     LoadingCache<Object, Object> cache = builder.build(
527         CacheLoader.from(Suppliers.ofInstance(value)));
528     assertSame(value, cache.getUnchecked(key));
529     assertEquals(0, cache.size());
530     assertFalse(cache.asMap().containsKey(key));
531   }
532 
testCacheBuilderFrom_string()533   public void testCacheBuilderFrom_string() {
534     CacheBuilder<?, ?> fromString = CacheBuilder.from(
535         "initialCapacity=10,maximumSize=20,concurrencyLevel=30,"
536         + "weakKeys,weakValues,expireAfterAccess=10m");
537     CacheBuilder<?, ?> expected = CacheBuilder.newBuilder()
538         .initialCapacity(10)
539         .maximumSize(20)
540         .concurrencyLevel(30)
541         .weakKeys()
542         .weakValues()
543         .expireAfterAccess(60 * 10L, TimeUnit.SECONDS);
544     assertCacheBuilderEquivalence(expected, fromString);
545   }
546 
assertCacheBuilderEquivalence(CacheBuilder<?, ?> a, CacheBuilder<?, ?> b)547   private static void assertCacheBuilderEquivalence(CacheBuilder<?, ?> a, CacheBuilder<?, ?> b) {
548     assertEquals("concurrencyLevel", a.concurrencyLevel, b.concurrencyLevel);
549     assertEquals("expireAfterAccessNanos", a.expireAfterAccessNanos, b.expireAfterAccessNanos);
550     assertEquals("expireAfterWriteNanos", a.expireAfterWriteNanos, b.expireAfterWriteNanos);
551     assertEquals("initialCapacity", a.initialCapacity, b.initialCapacity);
552     assertEquals("maximumSize", a.maximumSize, b.maximumSize);
553     assertEquals("maximumWeight", a.maximumWeight, b.maximumWeight);
554     assertEquals("refreshNanos", a.refreshNanos, b.refreshNanos);
555     assertEquals("keyEquivalence", a.keyEquivalence, b.keyEquivalence);
556     assertEquals("keyStrength", a.keyStrength, b.keyStrength);
557     assertEquals("removalListener", a.removalListener, b.removalListener);
558     assertEquals("weigher", a.weigher, b.weigher);
559     assertEquals("valueEquivalence", a.valueEquivalence, b.valueEquivalence);
560     assertEquals("valueStrength", a.valueStrength, b.valueStrength);
561     assertEquals("statsCounterSupplier", a.statsCounterSupplier, b.statsCounterSupplier);
562     assertEquals("ticker", a.ticker, b.ticker);
563     assertEquals("recordStats", a.isRecordingStats(), b.isRecordingStats());
564   }
565 }
566