@Test public void testBrokenEvictionVeto() throws CacheAccessException { TestTimeSource timeSource = new TestTimeSource(); Expiry<Object, Object> expiry = Expirations.timeToIdleExpiration(new Duration(15L, TimeUnit.MILLISECONDS)); EvictionVeto<String, byte[]> evictionVeto = new EvictionVeto<String, byte[]>() { @Override public boolean test(Cache.Entry<String, byte[]> entry) { throw new UnsupportedOperationException("Broken veto!"); } }; AbstractOffHeapStore<String, byte[]> offHeapStore = createAndInitStore(timeSource, expiry, evictionVeto); try { StoreEventListener<String, byte[]> mock = mock(StoreEventListener.class); offHeapStore.enableStoreEventNotifications(mock); byte[] value = getBytes(MemoryUnit.KB.toBytes(200)); offHeapStore.put("key1", value); offHeapStore.put("key2", value); offHeapStore.put("key3", value); offHeapStore.put("key4", value); offHeapStore.put("key5", value); offHeapStore.put("key6", value); verify(mock, atLeast(1)).onEviction(anyString(), any(Store.ValueHolder.class)); } finally { destroyStore(offHeapStore); } }
@Test public void testIteratorSkipsExpiredEntries() throws Exception { TestTimeSource timeSource = new TestTimeSource(); AbstractOffHeapStore<String, String> offHeapStore = createAndInitStore( timeSource, Expirations.timeToLiveExpiration(new Duration(10L, TimeUnit.MILLISECONDS))); try { offHeapStore.put("key1", "value1"); offHeapStore.put("key2", "value2"); timeSource.advanceTime(11L); offHeapStore.put("key3", "value3"); offHeapStore.put("key4", "value4"); final List<String> expiredKeys = new ArrayList<String>(); offHeapStore.enableStoreEventNotifications( new StoreEventListener<String, String>() { @Override public void onEviction(final String key, final Store.ValueHolder<String> valueHolder) { throw new AssertionError("This should not have happened."); } @Override public void onExpiration( final String key, final Store.ValueHolder<String> valueHolder) { expiredKeys.add(key); } }); List<String> iteratedKeys = new ArrayList<String>(); Store.Iterator<Cache.Entry<String, Store.ValueHolder<String>>> iterator = offHeapStore.iterator(); while (iterator.hasNext()) { iteratedKeys.add(iterator.next().getKey()); } assertThat(iteratedKeys, containsInAnyOrder("key3", "key4")); assertThat(expiredKeys, containsInAnyOrder("key1", "key2")); } finally { destroyStore(offHeapStore); } }
@Test public void testExpiryEventFiredOnExpiredCachedEntry() throws CacheAccessException { TestTimeSource timeSource = new TestTimeSource(); AbstractOffHeapStore<String, String> offHeapStore = createAndInitStore( timeSource, Expirations.timeToIdleExpiration(new Duration(10L, TimeUnit.MILLISECONDS))); try { final List<String> expiredKeys = new ArrayList<String>(); offHeapStore.enableStoreEventNotifications( new StoreEventListener<String, String>() { @Override public void onEviction(final String key, final Store.ValueHolder<String> valueHolder) { throw new AssertionError("This should not have happened."); } @Override public void onExpiration( final String key, final Store.ValueHolder<String> valueHolder) { expiredKeys.add(key); } }); offHeapStore.put("key1", "value1"); offHeapStore.put("key2", "value2"); offHeapStore.get("key1"); // Bring the entry to the caching tier timeSource.advanceTime(11); // Expire the elements offHeapStore.get("key1"); offHeapStore.get("key2"); assertThat(expiredKeys, containsInAnyOrder("key1", "key2")); assertThat( getExpirationStatistic(offHeapStore) .count(StoreOperationOutcomes.ExpirationOutcome.SUCCESS), is(2L)); } finally { destroyStore(offHeapStore); } }