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 import static org.junit.Assert.assertThrows; 22 23 import com.google.common.base.Suppliers; 24 import com.google.common.cache.LocalCache.Strength; 25 import com.google.common.testing.EqualsTester; 26 import java.util.concurrent.TimeUnit; 27 import junit.framework.TestCase; 28 29 /** 30 * Tests CacheBuilderSpec. TODO(user): tests of a few invalid input conditions, boundary 31 * conditions. 32 * 33 * @author Adam Winer 34 */ 35 public class CacheBuilderSpecTest extends TestCase { testParse_empty()36 public void testParse_empty() { 37 CacheBuilderSpec spec = parse(""); 38 assertNull(spec.initialCapacity); 39 assertNull(spec.maximumSize); 40 assertNull(spec.maximumWeight); 41 assertNull(spec.concurrencyLevel); 42 assertNull(spec.keyStrength); 43 assertNull(spec.valueStrength); 44 assertNull(spec.writeExpirationTimeUnit); 45 assertNull(spec.accessExpirationTimeUnit); 46 assertCacheBuilderEquivalence(CacheBuilder.newBuilder(), CacheBuilder.from(spec)); 47 } 48 testParse_initialCapacity()49 public void testParse_initialCapacity() { 50 CacheBuilderSpec spec = parse("initialCapacity=10"); 51 assertEquals(10, spec.initialCapacity.intValue()); 52 assertNull(spec.maximumSize); 53 assertNull(spec.maximumWeight); 54 assertNull(spec.concurrencyLevel); 55 assertNull(spec.keyStrength); 56 assertNull(spec.valueStrength); 57 assertNull(spec.writeExpirationTimeUnit); 58 assertNull(spec.accessExpirationTimeUnit); 59 assertCacheBuilderEquivalence( 60 CacheBuilder.newBuilder().initialCapacity(10), CacheBuilder.from(spec)); 61 } 62 testParse_initialCapacityRepeated()63 public void testParse_initialCapacityRepeated() { 64 assertThrows( 65 IllegalArgumentException.class, () -> parse("initialCapacity=10, initialCapacity=20")); 66 } 67 testParse_maximumSize()68 public void testParse_maximumSize() { 69 CacheBuilderSpec spec = parse("maximumSize=9000"); 70 assertNull(spec.initialCapacity); 71 assertEquals(9000, spec.maximumSize.longValue()); 72 assertNull(spec.concurrencyLevel); 73 assertNull(spec.keyStrength); 74 assertNull(spec.valueStrength); 75 assertNull(spec.writeExpirationTimeUnit); 76 assertNull(spec.accessExpirationTimeUnit); 77 assertCacheBuilderEquivalence( 78 CacheBuilder.newBuilder().maximumSize(9000), CacheBuilder.from(spec)); 79 } 80 testParse_maximumSizeRepeated()81 public void testParse_maximumSizeRepeated() { 82 assertThrows(IllegalArgumentException.class, () -> parse("maximumSize=10, maximumSize=20")); 83 } 84 testParse_maximumWeight()85 public void testParse_maximumWeight() { 86 CacheBuilderSpec spec = parse("maximumWeight=9000"); 87 assertNull(spec.initialCapacity); 88 assertEquals(9000, spec.maximumWeight.longValue()); 89 assertNull(spec.concurrencyLevel); 90 assertNull(spec.keyStrength); 91 assertNull(spec.valueStrength); 92 assertNull(spec.writeExpirationTimeUnit); 93 assertNull(spec.accessExpirationTimeUnit); 94 assertCacheBuilderEquivalence( 95 CacheBuilder.newBuilder().maximumWeight(9000), CacheBuilder.from(spec)); 96 } 97 testParse_maximumWeightRepeated()98 public void testParse_maximumWeightRepeated() { 99 assertThrows(IllegalArgumentException.class, () -> parse("maximumWeight=10, maximumWeight=20")); 100 } 101 testParse_maximumSizeAndMaximumWeight()102 public void testParse_maximumSizeAndMaximumWeight() { 103 assertThrows(IllegalArgumentException.class, () -> parse("maximumSize=10, maximumWeight=20")); 104 } 105 testParse_concurrencyLevel()106 public void testParse_concurrencyLevel() { 107 CacheBuilderSpec spec = parse("concurrencyLevel=32"); 108 assertNull(spec.initialCapacity); 109 assertNull(spec.maximumSize); 110 assertNull(spec.maximumWeight); 111 assertEquals(32, spec.concurrencyLevel.intValue()); 112 assertNull(spec.keyStrength); 113 assertNull(spec.valueStrength); 114 assertNull(spec.writeExpirationTimeUnit); 115 assertNull(spec.accessExpirationTimeUnit); 116 assertCacheBuilderEquivalence( 117 CacheBuilder.newBuilder().concurrencyLevel(32), CacheBuilder.from(spec)); 118 } 119 testParse_concurrencyLevelRepeated()120 public void testParse_concurrencyLevelRepeated() { 121 assertThrows( 122 IllegalArgumentException.class, () -> parse("concurrencyLevel=10, concurrencyLevel=20")); 123 } 124 testParse_weakKeys()125 public void testParse_weakKeys() { 126 CacheBuilderSpec spec = parse("weakKeys"); 127 assertNull(spec.initialCapacity); 128 assertNull(spec.maximumSize); 129 assertNull(spec.maximumWeight); 130 assertNull(spec.concurrencyLevel); 131 assertEquals(Strength.WEAK, spec.keyStrength); 132 assertNull(spec.valueStrength); 133 assertNull(spec.writeExpirationTimeUnit); 134 assertNull(spec.accessExpirationTimeUnit); 135 assertCacheBuilderEquivalence(CacheBuilder.newBuilder().weakKeys(), CacheBuilder.from(spec)); 136 } 137 testParse_weakKeysCannotHaveValue()138 public void testParse_weakKeysCannotHaveValue() { 139 assertThrows(IllegalArgumentException.class, () -> parse("weakKeys=true")); 140 } 141 testParse_repeatedKeyStrength()142 public void testParse_repeatedKeyStrength() { 143 assertThrows(IllegalArgumentException.class, () -> parse("weakKeys, weakKeys")); 144 } 145 testParse_softValues()146 public void testParse_softValues() { 147 CacheBuilderSpec spec = parse("softValues"); 148 assertNull(spec.initialCapacity); 149 assertNull(spec.maximumSize); 150 assertNull(spec.maximumWeight); 151 assertNull(spec.concurrencyLevel); 152 assertNull(spec.keyStrength); 153 assertEquals(Strength.SOFT, spec.valueStrength); 154 assertNull(spec.writeExpirationTimeUnit); 155 assertNull(spec.accessExpirationTimeUnit); 156 assertCacheBuilderEquivalence(CacheBuilder.newBuilder().softValues(), CacheBuilder.from(spec)); 157 } 158 testParse_softValuesCannotHaveValue()159 public void testParse_softValuesCannotHaveValue() { 160 assertThrows(IllegalArgumentException.class, () -> parse("softValues=true")); 161 } 162 testParse_weakValues()163 public void testParse_weakValues() { 164 CacheBuilderSpec spec = parse("weakValues"); 165 assertNull(spec.initialCapacity); 166 assertNull(spec.maximumSize); 167 assertNull(spec.maximumWeight); 168 assertNull(spec.concurrencyLevel); 169 assertNull(spec.keyStrength); 170 assertEquals(Strength.WEAK, spec.valueStrength); 171 assertNull(spec.writeExpirationTimeUnit); 172 assertNull(spec.accessExpirationTimeUnit); 173 assertCacheBuilderEquivalence(CacheBuilder.newBuilder().weakValues(), CacheBuilder.from(spec)); 174 } 175 testParse_weakValuesCannotHaveValue()176 public void testParse_weakValuesCannotHaveValue() { 177 assertThrows(IllegalArgumentException.class, () -> parse("weakValues=true")); 178 } 179 testParse_repeatedValueStrength()180 public void testParse_repeatedValueStrength() { 181 assertThrows(IllegalArgumentException.class, () -> parse("softValues, softValues")); 182 183 assertThrows(IllegalArgumentException.class, () -> parse("softValues, weakValues")); 184 185 assertThrows(IllegalArgumentException.class, () -> parse("weakValues, softValues")); 186 187 assertThrows(IllegalArgumentException.class, () -> parse("weakValues, weakValues")); 188 } 189 testParse_writeExpirationDays()190 public void testParse_writeExpirationDays() { 191 CacheBuilderSpec spec = parse("expireAfterWrite=10d"); 192 assertNull(spec.initialCapacity); 193 assertNull(spec.maximumSize); 194 assertNull(spec.maximumWeight); 195 assertNull(spec.concurrencyLevel); 196 assertNull(spec.keyStrength); 197 assertNull(spec.valueStrength); 198 assertEquals(TimeUnit.DAYS, spec.writeExpirationTimeUnit); 199 assertEquals(10L, spec.writeExpirationDuration); 200 assertNull(spec.accessExpirationTimeUnit); 201 assertCacheBuilderEquivalence( 202 CacheBuilder.newBuilder().expireAfterWrite(10L, TimeUnit.DAYS), CacheBuilder.from(spec)); 203 } 204 testParse_writeExpirationHours()205 public void testParse_writeExpirationHours() { 206 CacheBuilderSpec spec = parse("expireAfterWrite=150h"); 207 assertEquals(TimeUnit.HOURS, spec.writeExpirationTimeUnit); 208 assertEquals(150L, spec.writeExpirationDuration); 209 assertCacheBuilderEquivalence( 210 CacheBuilder.newBuilder().expireAfterWrite(150L, TimeUnit.HOURS), CacheBuilder.from(spec)); 211 } 212 testParse_writeExpirationMinutes()213 public void testParse_writeExpirationMinutes() { 214 CacheBuilderSpec spec = parse("expireAfterWrite=10m"); 215 assertEquals(TimeUnit.MINUTES, spec.writeExpirationTimeUnit); 216 assertEquals(10L, spec.writeExpirationDuration); 217 assertCacheBuilderEquivalence( 218 CacheBuilder.newBuilder().expireAfterWrite(10L, TimeUnit.MINUTES), CacheBuilder.from(spec)); 219 } 220 testParse_writeExpirationSeconds()221 public void testParse_writeExpirationSeconds() { 222 CacheBuilderSpec spec = parse("expireAfterWrite=10s"); 223 assertEquals(TimeUnit.SECONDS, spec.writeExpirationTimeUnit); 224 assertEquals(10L, spec.writeExpirationDuration); 225 assertCacheBuilderEquivalence( 226 CacheBuilder.newBuilder().expireAfterWrite(10L, TimeUnit.SECONDS), CacheBuilder.from(spec)); 227 } 228 testParse_writeExpirationRepeated()229 public void testParse_writeExpirationRepeated() { 230 assertThrows( 231 IllegalArgumentException.class, () -> parse("expireAfterWrite=10s,expireAfterWrite=10m")); 232 } 233 testParse_accessExpirationDays()234 public void testParse_accessExpirationDays() { 235 CacheBuilderSpec spec = parse("expireAfterAccess=10d"); 236 assertNull(spec.initialCapacity); 237 assertNull(spec.maximumSize); 238 assertNull(spec.maximumWeight); 239 assertNull(spec.concurrencyLevel); 240 assertNull(spec.keyStrength); 241 assertNull(spec.valueStrength); 242 assertNull(spec.writeExpirationTimeUnit); 243 assertEquals(TimeUnit.DAYS, spec.accessExpirationTimeUnit); 244 assertEquals(10L, spec.accessExpirationDuration); 245 assertCacheBuilderEquivalence( 246 CacheBuilder.newBuilder().expireAfterAccess(10L, TimeUnit.DAYS), CacheBuilder.from(spec)); 247 } 248 testParse_accessExpirationHours()249 public void testParse_accessExpirationHours() { 250 CacheBuilderSpec spec = parse("expireAfterAccess=150h"); 251 assertEquals(TimeUnit.HOURS, spec.accessExpirationTimeUnit); 252 assertEquals(150L, spec.accessExpirationDuration); 253 assertCacheBuilderEquivalence( 254 CacheBuilder.newBuilder().expireAfterAccess(150L, TimeUnit.HOURS), CacheBuilder.from(spec)); 255 } 256 testParse_accessExpirationMinutes()257 public void testParse_accessExpirationMinutes() { 258 CacheBuilderSpec spec = parse("expireAfterAccess=10m"); 259 assertEquals(TimeUnit.MINUTES, spec.accessExpirationTimeUnit); 260 assertEquals(10L, spec.accessExpirationDuration); 261 assertCacheBuilderEquivalence( 262 CacheBuilder.newBuilder().expireAfterAccess(10L, TimeUnit.MINUTES), 263 CacheBuilder.from(spec)); 264 } 265 testParse_accessExpirationSeconds()266 public void testParse_accessExpirationSeconds() { 267 CacheBuilderSpec spec = parse("expireAfterAccess=10s"); 268 assertEquals(TimeUnit.SECONDS, spec.accessExpirationTimeUnit); 269 assertEquals(10L, spec.accessExpirationDuration); 270 assertCacheBuilderEquivalence( 271 CacheBuilder.newBuilder().expireAfterAccess(10L, TimeUnit.SECONDS), 272 CacheBuilder.from(spec)); 273 } 274 testParse_accessExpirationRepeated()275 public void testParse_accessExpirationRepeated() { 276 assertThrows( 277 IllegalArgumentException.class, () -> parse("expireAfterAccess=10s,expireAfterAccess=10m")); 278 } 279 testParse_recordStats()280 public void testParse_recordStats() { 281 CacheBuilderSpec spec = parse("recordStats"); 282 assertTrue(spec.recordStats); 283 assertCacheBuilderEquivalence(CacheBuilder.newBuilder().recordStats(), CacheBuilder.from(spec)); 284 } 285 testParse_recordStatsValueSpecified()286 public void testParse_recordStatsValueSpecified() { 287 assertThrows(IllegalArgumentException.class, () -> parse("recordStats=True")); 288 } 289 testParse_recordStatsRepeated()290 public void testParse_recordStatsRepeated() { 291 assertThrows(IllegalArgumentException.class, () -> parse("recordStats,recordStats")); 292 } 293 testParse_accessExpirationAndWriteExpiration()294 public void testParse_accessExpirationAndWriteExpiration() { 295 CacheBuilderSpec spec = parse("expireAfterAccess=10s,expireAfterWrite=9m"); 296 assertEquals(TimeUnit.MINUTES, spec.writeExpirationTimeUnit); 297 assertEquals(9L, spec.writeExpirationDuration); 298 assertEquals(TimeUnit.SECONDS, spec.accessExpirationTimeUnit); 299 assertEquals(10L, spec.accessExpirationDuration); 300 assertCacheBuilderEquivalence( 301 CacheBuilder.newBuilder() 302 .expireAfterAccess(10L, TimeUnit.SECONDS) 303 .expireAfterWrite(9L, TimeUnit.MINUTES), 304 CacheBuilder.from(spec)); 305 } 306 testParse_multipleKeys()307 public void testParse_multipleKeys() { 308 CacheBuilderSpec spec = 309 parse( 310 "initialCapacity=10,maximumSize=20,concurrencyLevel=30," 311 + "weakKeys,weakValues,expireAfterAccess=10m,expireAfterWrite=1h"); 312 assertEquals(10, spec.initialCapacity.intValue()); 313 assertEquals(20, spec.maximumSize.intValue()); 314 assertNull(spec.maximumWeight); 315 assertEquals(30, spec.concurrencyLevel.intValue()); 316 assertEquals(Strength.WEAK, spec.keyStrength); 317 assertEquals(Strength.WEAK, spec.valueStrength); 318 assertEquals(TimeUnit.HOURS, spec.writeExpirationTimeUnit); 319 assertEquals(TimeUnit.MINUTES, spec.accessExpirationTimeUnit); 320 assertEquals(1L, spec.writeExpirationDuration); 321 assertEquals(10L, spec.accessExpirationDuration); 322 CacheBuilder<?, ?> expected = 323 CacheBuilder.newBuilder() 324 .initialCapacity(10) 325 .maximumSize(20) 326 .concurrencyLevel(30) 327 .weakKeys() 328 .weakValues() 329 .expireAfterAccess(10L, TimeUnit.MINUTES) 330 .expireAfterWrite(1L, TimeUnit.HOURS); 331 assertCacheBuilderEquivalence(expected, CacheBuilder.from(spec)); 332 } 333 testParse_whitespaceAllowed()334 public void testParse_whitespaceAllowed() { 335 CacheBuilderSpec spec = 336 parse( 337 " initialCapacity=10,\nmaximumSize=20,\t\r" 338 + "weakKeys \t ,softValues \n , \r expireAfterWrite \t = 15s\n\n"); 339 assertEquals(10, spec.initialCapacity.intValue()); 340 assertEquals(20, spec.maximumSize.intValue()); 341 assertNull(spec.maximumWeight); 342 assertNull(spec.concurrencyLevel); 343 assertEquals(Strength.WEAK, spec.keyStrength); 344 assertEquals(Strength.SOFT, spec.valueStrength); 345 assertEquals(TimeUnit.SECONDS, spec.writeExpirationTimeUnit); 346 assertEquals(15L, spec.writeExpirationDuration); 347 assertNull(spec.accessExpirationTimeUnit); 348 CacheBuilder<?, ?> expected = 349 CacheBuilder.newBuilder() 350 .initialCapacity(10) 351 .maximumSize(20) 352 .weakKeys() 353 .softValues() 354 .expireAfterWrite(15L, TimeUnit.SECONDS); 355 assertCacheBuilderEquivalence(expected, CacheBuilder.from(spec)); 356 } 357 testParse_unknownKey()358 public void testParse_unknownKey() { 359 assertThrows(IllegalArgumentException.class, () -> parse("foo=17")); 360 } 361 testParse_extraCommaIsInvalid()362 public void testParse_extraCommaIsInvalid() { 363 assertThrows(IllegalArgumentException.class, () -> parse("weakKeys,")); 364 365 assertThrows(IllegalArgumentException.class, () -> parse(",weakKeys")); 366 367 assertThrows(IllegalArgumentException.class, () -> parse("weakKeys,,softValues")); 368 } 369 testEqualsAndHashCode()370 public void testEqualsAndHashCode() { 371 new EqualsTester() 372 .addEqualityGroup(parse(""), parse("")) 373 .addEqualityGroup(parse("concurrencyLevel=7"), parse("concurrencyLevel=7")) 374 .addEqualityGroup(parse("concurrencyLevel=15"), parse("concurrencyLevel=15")) 375 .addEqualityGroup(parse("initialCapacity=7"), parse("initialCapacity=7")) 376 .addEqualityGroup(parse("initialCapacity=15"), parse("initialCapacity=15")) 377 .addEqualityGroup(parse("maximumSize=7"), parse("maximumSize=7")) 378 .addEqualityGroup(parse("maximumSize=15"), parse("maximumSize=15")) 379 .addEqualityGroup(parse("maximumWeight=7"), parse("maximumWeight=7")) 380 .addEqualityGroup(parse("maximumWeight=15"), parse("maximumWeight=15")) 381 .addEqualityGroup(parse("expireAfterAccess=60s"), parse("expireAfterAccess=1m")) 382 .addEqualityGroup(parse("expireAfterAccess=60m"), parse("expireAfterAccess=1h")) 383 .addEqualityGroup(parse("expireAfterWrite=60s"), parse("expireAfterWrite=1m")) 384 .addEqualityGroup(parse("expireAfterWrite=60m"), parse("expireAfterWrite=1h")) 385 .addEqualityGroup(parse("weakKeys"), parse("weakKeys")) 386 .addEqualityGroup(parse("softValues"), parse("softValues")) 387 .addEqualityGroup(parse("weakValues"), parse("weakValues")) 388 .addEqualityGroup(parse("recordStats"), parse("recordStats")) 389 .testEquals(); 390 } 391 392 @SuppressWarnings("ReturnValueIgnored") testMaximumWeight_withWeigher()393 public void testMaximumWeight_withWeigher() { 394 CacheBuilder<Object, Object> builder = CacheBuilder.from(parse("maximumWeight=9000")); 395 builder.weigher(constantWeigher(42)).build(CacheLoader.from(Suppliers.ofInstance(null))); 396 } 397 398 @SuppressWarnings("ReturnValueIgnored") testMaximumWeight_withoutWeigher()399 public void testMaximumWeight_withoutWeigher() { 400 CacheBuilder<Object, Object> builder = CacheBuilder.from(parse("maximumWeight=9000")); 401 assertThrows( 402 IllegalStateException.class, 403 () -> builder.build(CacheLoader.from(Suppliers.ofInstance(null)))); 404 } 405 406 @SuppressWarnings("ReturnValueIgnored") testMaximumSize_withWeigher()407 public void testMaximumSize_withWeigher() { 408 CacheBuilder<Object, Object> builder = CacheBuilder.from(parse("maximumSize=9000")); 409 builder.weigher(constantWeigher(42)).build(CacheLoader.from(Suppliers.ofInstance(null))); 410 } 411 412 @SuppressWarnings("ReturnValueIgnored") testMaximumSize_withoutWeigher()413 public void testMaximumSize_withoutWeigher() { 414 CacheBuilder<Object, Object> builder = CacheBuilder.from(parse("maximumSize=9000")); 415 builder.build(CacheLoader.from(Suppliers.ofInstance(null))); 416 } 417 testDisableCaching()418 public void testDisableCaching() { 419 // Functional test: assert that CacheBuilderSpec.disableCaching() 420 // disables caching. It's irrelevant how it does so. 421 CacheBuilder<Object, Object> builder = CacheBuilder.from(CacheBuilderSpec.disableCaching()); 422 Object key = new Object(); 423 Object value = new Object(); 424 LoadingCache<Object, Object> cache = 425 builder.build(CacheLoader.from(Suppliers.ofInstance(value))); 426 assertSame(value, cache.getUnchecked(key)); 427 assertEquals(0, cache.size()); 428 assertFalse(cache.asMap().containsKey(key)); 429 } 430 testCacheBuilderFrom_string()431 public void testCacheBuilderFrom_string() { 432 CacheBuilder<?, ?> fromString = 433 CacheBuilder.from( 434 "initialCapacity=10,maximumSize=20,concurrencyLevel=30," 435 + "weakKeys,weakValues,expireAfterAccess=10m"); 436 CacheBuilder<?, ?> expected = 437 CacheBuilder.newBuilder() 438 .initialCapacity(10) 439 .maximumSize(20) 440 .concurrencyLevel(30) 441 .weakKeys() 442 .weakValues() 443 .expireAfterAccess(10L, TimeUnit.MINUTES); 444 assertCacheBuilderEquivalence(expected, fromString); 445 } 446 assertCacheBuilderEquivalence(CacheBuilder<?, ?> a, CacheBuilder<?, ?> b)447 private static void assertCacheBuilderEquivalence(CacheBuilder<?, ?> a, CacheBuilder<?, ?> b) { 448 assertEquals("concurrencyLevel", a.concurrencyLevel, b.concurrencyLevel); 449 assertEquals("expireAfterAccessNanos", a.expireAfterAccessNanos, b.expireAfterAccessNanos); 450 assertEquals("expireAfterWriteNanos", a.expireAfterWriteNanos, b.expireAfterWriteNanos); 451 assertEquals("initialCapacity", a.initialCapacity, b.initialCapacity); 452 assertEquals("maximumSize", a.maximumSize, b.maximumSize); 453 assertEquals("maximumWeight", a.maximumWeight, b.maximumWeight); 454 assertEquals("refreshNanos", a.refreshNanos, b.refreshNanos); 455 assertEquals("keyEquivalence", a.keyEquivalence, b.keyEquivalence); 456 assertEquals("keyStrength", a.keyStrength, b.keyStrength); 457 assertEquals("removalListener", a.removalListener, b.removalListener); 458 assertEquals("weigher", a.weigher, b.weigher); 459 assertEquals("valueEquivalence", a.valueEquivalence, b.valueEquivalence); 460 assertEquals("valueStrength", a.valueStrength, b.valueStrength); 461 assertEquals("statsCounterSupplier", a.statsCounterSupplier, b.statsCounterSupplier); 462 assertEquals("ticker", a.ticker, b.ticker); 463 assertEquals("recordStats", a.isRecordingStats(), b.isRecordingStats()); 464 } 465 } 466