Search code examples
testingguavaticker

Guava Ticker Cache expire


Google Guava tutorial said cache expiration can be tested with Ticker

as my understanding, I can use it to force a quick expiration. am I right?

but I tried in the following code, and it did not work, any suggestion?

@Test
public void expireAfterWriteTestWithTicker() throws InterruptedException {
    Ticker t = new Ticker() {
        @Override
        public long read() {
            return TimeUnit.MILLISECONDS.toNanos(5);
        }
    };
    //Use ticker to force expire in 5 millseconds
    LoadingCache<String, String> cache = CacheBuilder.newBuilder()
            .expireAfterWrite(20, TimeUnit.MINUTES).ticker(t).build(loader);

    cache.getUnchecked("hello");
    assertEquals(1, cache.size());
    assertNotNull(cache.getIfPresent("hello"));
    //sleep
    Thread.sleep(10);
    assertNull(cache.getIfPresent("hello"));    //failed 

}

Solution

  • Just find the answer by myself

    Ticker can be used to skip the time, but not the expiration time

    class FakeTicker extends Ticker {
    
        private final AtomicLong nanos = new AtomicLong();
    
        /** Advances the ticker value by {@code time} in {@code timeUnit}. */
        public FakeTicker advance(long time, TimeUnit timeUnit) {
            nanos.addAndGet(timeUnit.toNanos(time));
            return this;
        }
    
        @Override
        public long read() {
            long value = nanos.getAndAdd(0);
            System.out.println("is called " + value);
            return value;
        }
    }
    

    @Test
    public void expireAfterWriteTestWithTicker() throws InterruptedException {
        FakeTicker t = new FakeTicker();
    
        // Use ticker to force expire in 20 minute
        LoadingCache<String, String> cache = CacheBuilder.newBuilder()
                .expireAfterWrite(20, TimeUnit.MINUTES).ticker(t).build(ldr);
        cache.getUnchecked("hello");
        assertEquals(1, cache.size());
        assertNotNull(cache.getIfPresent("hello"));
    
        // add 21 minutes
        t.advance(21, TimeUnit.MINUTES);
        assertNull(cache.getIfPresent("hello")); 
    
    }