/* * Copyright Terracotta, Inc. * * 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 org.ehcache.core; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.ehcache.Cache; import org.ehcache.Status; import org.ehcache.spi.loaderwriter.CacheLoaderWriter; import org.hamcrest.Matchers; import org.junit.Test; import org.slf4j.LoggerFactory; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; /** * @author Abhilash * */ public class EhcacheWithLoaderWriterBasicIteratorTest extends EhcacheBasicIteratorTest { /** * Tests {@link java.util.Iterator#remove()} from {@link EhcacheWithLoaderWriter#iterator()} on a non-empty cache. */ @Test public void testIteratorNonEmptyRemoveOne() throws Exception { final Map<String, String> testStoreEntries = this.getTestStoreEntries(); final FakeStore fakeStore = new FakeStore(testStoreEntries); this.store = fakeStore; // Set CacheLoaderWriter & Store to have the same entries initially final FakeCacheLoaderWriter fakeWriterWriter = new FakeCacheLoaderWriter(testStoreEntries); final InternalCache<String, String> ehcache = this.getEhcache(fakeWriterWriter); final Iterator<Cache.Entry<String, String>> iterator = ehcache.iterator(); while (iterator.hasNext()) { final Cache.Entry<String, String> entry = iterator.next(); if (entry.getKey().equals("keyA")) { iterator.remove(); } } testStoreEntries.remove("keyA"); final Map<String, String> storeEntries = new HashMap<String, String>(fakeStore.getEntryMap()); for (Map.Entry<String, String> expectedEntry : testStoreEntries.entrySet()) { final String expectedEntryKey = expectedEntry.getKey(); assertThat(storeEntries, hasEntry(equalTo(expectedEntryKey), equalTo(expectedEntry.getValue()))); storeEntries.remove(expectedEntryKey); } assertThat("Iterator.remove removed incorrect Store entry", storeEntries.isEmpty(), is(true)); final Map<String, String> writerEntries = new HashMap<String, String>(fakeWriterWriter.getEntryMap()); for (Map.Entry<String, String> expectedEntry : testStoreEntries.entrySet()) { final String expectedEntryKey = expectedEntry.getKey(); assertThat(writerEntries, hasEntry(equalTo(expectedEntryKey), equalTo(expectedEntry.getValue()))); writerEntries.remove(expectedEntryKey); } assertThat("Iterator.remove removed incorrect Writer entry", writerEntries.isEmpty(), is(true)); } /** * Tests removal of all entries from {@link EhcacheWithLoaderWriter#iterator()} on a non-empty cache. */ @Test public void testIteratorNonEmptyRemoveAll() throws Exception { final Map<String, String> testStoreEntries = this.getTestStoreEntries(); final FakeStore fakeStore = new FakeStore(testStoreEntries); this.store = fakeStore; // Set CacheLoaderWriter & Store to have the same entries initially final FakeCacheLoaderWriter fakeLoaderWriter = new FakeCacheLoaderWriter(testStoreEntries); final InternalCache<String, String> ehcache = this.getEhcache(fakeLoaderWriter); final Iterator<Cache.Entry<String, String>> iterator = ehcache.iterator(); while (iterator.hasNext()) { iterator.next(); iterator.remove(); } assertThat("Failed to remove all entries from Store", fakeStore.getEntryMap().isEmpty(), is(true)); assertThat("Failed to remove all entries via CacheLoaderWriter", fakeLoaderWriter.getEntryMap().isEmpty(), is(true)); } /** * Tests {@link java.util.Iterator#remove()} twice on the same entry returned from the {@code Iterator} * returned from {@link EhcacheWithLoaderWriter#iterator()} on a non-empty cache. */ @Test public void testIteratorNonEmptyRemoveTwice() throws Exception { final Map<String, String> testStoreEntries = this.getTestStoreEntries(); this.store = new FakeStore(testStoreEntries); // Set CacheLoaderWriter & Store to have the same entries initially final FakeCacheLoaderWriter fakeWriterWriter = new FakeCacheLoaderWriter(testStoreEntries); final InternalCache<String, String> ehcache = this.getEhcache(fakeWriterWriter); final Iterator<Cache.Entry<String, String>> iterator = ehcache.iterator(); while (iterator.hasNext()) { final Cache.Entry<String, String> entry = iterator.next(); if (entry.getKey().equals("keyA")) { iterator.remove(); try { iterator.remove(); fail(); } catch (IllegalStateException e) { // Expected } break; } } } /** * Tests {@link java.util.Iterator#remove()} <b>after</b> removing the last entry returned from the {@code Iterator} * returned from {@link EhcacheWithLoaderWriter#iterator()} on a non-empty cache. */ @Test public void testIteratorNonEmptyRemoveAfterLast() throws Exception { final Map<String, String> testStoreEntries = this.getTestStoreEntries(); this.store = new FakeStore(testStoreEntries); // Set CacheLoaderWriter & Store to have the same entries initially final FakeCacheLoaderWriter fakeWriterWriter = new FakeCacheLoaderWriter(testStoreEntries); final InternalCache<String, String> ehcache = this.getEhcache(fakeWriterWriter); final Iterator<Cache.Entry<String, String>> iterator = ehcache.iterator(); while (iterator.hasNext()) { iterator.next(); } iterator.remove(); // Expected to remove last observed entry try { iterator.remove(); fail(); } catch (IllegalStateException e) { // Expected } } @Override protected InternalCache<String, String> getEhcache() throws Exception { @SuppressWarnings("unchecked") final CacheLoaderWriter<String, String> cacheLoaderWriter = mock(CacheLoaderWriter.class); doThrow(new UnsupportedOperationException()).when(cacheLoaderWriter).delete(anyString()); doThrow(new UnsupportedOperationException()).when(cacheLoaderWriter).deleteAll(getAnyStringIterable()); doThrow(new UnsupportedOperationException()).when(cacheLoaderWriter).write(anyString(), anyString()); doThrow(new UnsupportedOperationException()).when(cacheLoaderWriter).writeAll(getAnyMapEntryIterable()); doThrow(new UnsupportedOperationException()).when(cacheLoaderWriter).load(anyString()); doThrow(new UnsupportedOperationException()).when(cacheLoaderWriter).loadAll(getAnyStringIterable()); return this.getEhcache(cacheLoaderWriter); } /** * creates an instance {@code EhcacheWithLoaderWriter} * * @param cacheLoaderWriter * @return instance {@link EhcacheWithLoaderWriter} * @throws Exception */ private InternalCache<String, String> getEhcache(CacheLoaderWriter<String, String> cacheLoaderWriter) throws Exception { final EhcacheWithLoaderWriter<String, String> ehcache = new EhcacheWithLoaderWriter<String, String>(CACHE_CONFIGURATION, this.store, cacheLoaderWriter, cacheEventDispatcher, LoggerFactory.getLogger(EhcacheWithLoaderWriter.class + "-" + "EhcacheWithLoaderWriterBasicIteratorTest")); ehcache.init(); assertThat("cache not initialized", ehcache.getStatus(), Matchers.is(Status.AVAILABLE)); this.spiedResilienceStrategy = this.setResilienceStrategySpy(ehcache); return ehcache; } }