/*
* 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.Collections;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.ehcache.Status;
import org.ehcache.core.spi.store.Store;
import org.ehcache.core.statistics.CacheOperationOutcomes;
import org.ehcache.spi.loaderwriter.BulkCacheLoadingException;
import org.ehcache.core.spi.store.StoreAccessException;
import org.ehcache.spi.loaderwriter.CacheLoaderWriter;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.slf4j.LoggerFactory;
import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_A;
import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_B;
import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_C;
import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_D;
import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_E;
import static org.ehcache.core.EhcacheBasicBulkUtil.KEY_SET_F;
import static org.ehcache.core.EhcacheBasicBulkUtil.TEST_ENTRIES;
import static org.ehcache.core.EhcacheBasicBulkUtil.copyOnly;
import static org.ehcache.core.EhcacheBasicBulkUtil.copyUntil;
import static org.ehcache.core.EhcacheBasicBulkUtil.copyWithout;
import static org.ehcache.core.EhcacheBasicBulkUtil.fanIn;
import static org.ehcache.core.EhcacheBasicBulkUtil.getEntryMap;
import static org.ehcache.core.EhcacheBasicBulkUtil.getNullEntryMap;
import static org.ehcache.core.EhcacheBasicBulkUtil.union;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.ehcache.core.EhcacheBasicGetAllTest.getAnyStringSet;
import static org.ehcache.core.EhcacheBasicGetAllTest.getAnyIterableFunction;
import static org.ehcache.core.EhcacheBasicGetAllTest.validateBulkCounters;
/**
* Provides testing of basic GET_ALL operations on an {@code EhcacheWithLoaderWriter}.
* <h3>Note</h3>
* The current implementation of {@link EhcacheWithLoaderWriter#getAll(java.util.Set) Ehcache.getAll}
* does <b>not</b> produce partial results while handling a
* {@link StoreAccessException StoreAccessException}; all keys presented
* to {@code getAll} succeed or fail based on the recovery call to
* {@link CacheLoaderWriter#loadAll(Iterable)}.
*
* @author Clifford W. Johnson
*/
public class EhcacheWithLoaderWriterBasicGetAllTest extends EhcacheBasicCrudBase {
@Mock
private CacheLoaderWriter<String, String> loaderWriter;
/**
* A Mockito {@code ArgumentCaptor} for the {@code Set} argument to the
* {@link CacheLoaderWriter#loadAll(Iterable)}
* method.
*/
@Captor
private ArgumentCaptor<Set<String>> loadAllCaptor;
/**
* A Mockito {@code ArgumentCaptor} for the {@code Set} argument to the
* {@link org.ehcache.core.internal.resilience.ResilienceStrategy#getAllFailure(Iterable, Map, StoreAccessException)
* ResilienceStrategy.getAllFailure(Iterable, Map, StoreAccessException)} method.
*/
@Captor
private ArgumentCaptor<Map<String, String>> getAllFailureMapCaptor;
/**
* A Mockito {@code ArgumentCaptor} for the
* {@link BulkCacheLoadingException BulkCacheLoadingException}
* provided to the
* {@link org.ehcache.core.internal.resilience.ResilienceStrategy#getAllFailure(Iterable, StoreAccessException, BulkCacheLoadingException)
* ResilienceStrategy.getAllFailure(Iterable, StoreAccessException, BulkCacheLoadingException)} method.
*/
@Captor
private ArgumentCaptor<BulkCacheLoadingException> bulkExceptionCaptor;
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>empty request key set</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* </ul>
*/
@Test
public void testGetAllEmptyRequestWithLoader() throws Exception {
final FakeStore fakeStore = new FakeStore(Collections.<String, String>emptyMap());
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoaderWriter = new FakeCacheLoaderWriter(TEST_ENTRIES);
this.loaderWriter = spy(fakeLoaderWriter);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Map<String, String> actual = ehcache.getAll(Collections.<String>emptySet());
final Map<String, String> expected = Collections.emptyMap();
assertThat(actual, equalTo(expected));
verify(this.store, never()).bulkComputeIfAbsent(eq(Collections.<String>emptySet()), getAnyIterableFunction());
verify(this.spiedResilienceStrategy, never()).getAllFailure(eq(Collections.<String>emptySet()), any(StoreAccessException.class));
verify(this.loaderWriter, never()).loadAll(eq(Collections.<String>emptySet()));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchLoaderAllFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES);
this.loaderWriter = spy(fakeLoader);
doThrow(new Exception("loadAll failed")).when(this.loaderWriter).loadAll(getAnyStringSet());
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
try {
ehcache.getAll(KEY_SET_A);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), empty());
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
verify(this.store).bulkComputeIfAbsent(eq(KEY_SET_A), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_B)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_A));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchLoaderAllFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_A, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
try {
ehcache.getAll(KEY_SET_A);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), empty());
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
verify(this.store).bulkComputeIfAbsent(eq(KEY_SET_A), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_B)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_A));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchLoaderSomeFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_A, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_C));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_B)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionBeforeLoaderAllFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES);
this.loaderWriter = spy(fakeLoader);
doThrow(new Exception("loadAll failed")).when(this.loaderWriter).loadAll(getAnyStringSet());
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
try {
ehcache.getAll(KEY_SET_A);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(KEY_SET_A), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_A));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(KEY_SET_A), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().keySet(), empty());
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionBeforeLoaderAllFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_A, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
try {
ehcache.getAll(KEY_SET_A);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), empty());
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(KEY_SET_A), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_A));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(KEY_SET_A), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), Collections.<String> emptySet(), KEY_SET_A);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionBeforeLoaderSomeFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_A, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_C));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), KEY_SET_C, KEY_SET_A);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionAfterLoaderAllFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES);
this.loaderWriter = spy(fakeLoader);
doThrow(new Exception("loadAll failed")).when(this.loaderWriter).loadAll(getAnyStringSet());
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
try {
ehcache.getAll(KEY_SET_A);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(KEY_SET_A), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_A));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(KEY_SET_A), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().keySet(), empty());
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fails with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionAfterLoaderAllFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_A, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
try {
ehcache.getAll(KEY_SET_A);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), empty());
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(KEY_SET_A), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_A));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(KEY_SET_A), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), Collections.<String> emptySet(), KEY_SET_A);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fails with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionAfterLoaderSomeFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_A, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_C));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), KEY_SET_C, KEY_SET_A);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchLoaderNoMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Map<String, String> actual = ehcache.getAll(KEY_SET_A);
assertThat(actual, equalTo(getNullEntryMap(KEY_SET_A)));
verify(this.store).bulkComputeIfAbsent(eq(KEY_SET_A), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_B)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_A));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, 0, KEY_SET_A.size());
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(java.util.Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>no {@link org.ehcache.spi.loaderwriter.CacheLoaderWriter} entries match</li>
* <li>no {@link org.ehcache.spi.loaderwriter.CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionBeforeLoaderNoMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Map<String, String> actual = ehcache.getAll(KEY_SET_A);
final Map<String, String> expected = getNullEntryMap(KEY_SET_A);
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(KEY_SET_A), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_A));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(KEY_SET_A), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionAfterLoaderNoMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Map<String, String> actual = ehcache.getAll(KEY_SET_A);
final Map<String, String> expected = getNullEntryMap(KEY_SET_A);
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(KEY_SET_A), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_A));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(KEY_SET_A), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchLoaderNoMatchSomeFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C), KEY_SET_F);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_F);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses(), Matchers.<Map<?,?>>equalTo(getNullEntryMap(KEY_SET_A)));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_F));
}
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_B)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionBeforeLoaderNoMatchSomeFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C), KEY_SET_F);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_F);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().keySet(), empty());
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionAfterLoaderNoMatchSomeFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C), KEY_SET_F);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_F);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
final Set<String> successKeys = copyWithout(copyUntil(fetchKeys, "keyA3"), KEY_SET_F);
final Set<String> failKeys = copyWithout(fetchKeys, successKeys);
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses(),
Matchers.<Map<?, ?>>equalTo(getNullEntryMap(successKeys)));
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(failKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchLoaderSomeMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_B, KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(union(getNullEntryMap(KEY_SET_A), getEntryMap(KEY_SET_C))));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_B, KEY_SET_C)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, KEY_SET_C.size(), KEY_SET_A.size());
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionBeforeLoaderSomeMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_B, KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = union(getNullEntryMap(KEY_SET_A), getEntryMap(KEY_SET_C));
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionAfterLoaderSomeMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_B, KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = union(getNullEntryMap(KEY_SET_A), getEntryMap(KEY_SET_C));
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchLoaderSomeMatchDisjointFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C), KEY_SET_B);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(union(getNullEntryMap(KEY_SET_A), getEntryMap(KEY_SET_C))));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_B, KEY_SET_C)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, KEY_SET_C.size(), KEY_SET_A.size());
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionBeforeLoaderSomeMatchDisjointFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C), KEY_SET_B);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = union(getNullEntryMap(KEY_SET_A), getEntryMap(KEY_SET_C));
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionAfterLoaderSomeMatchDisjointFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C), KEY_SET_B);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = union(getNullEntryMap(KEY_SET_A), getEntryMap(KEY_SET_C));
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>all {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchLoaderAllMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(getEntryMap(fetchKeys)));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B, KEY_SET_C)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, KEY_SET_A.size() + KEY_SET_C.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>all {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionBeforeLoaderAllMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = getEntryMap(fetchKeys);
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>no {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>all {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreNoMatchStoreAccessExceptionAfterLoaderAllMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = getEntryMap(fetchKeys);
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchLoaderAllFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES);
this.loaderWriter = spy(fakeLoader);
doThrow(new Exception("loadAll failed")).when(this.loaderWriter).loadAll(getAnyStringSet());
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses(), Matchers.<Map<?,?>>equalTo(getEntryMap(KEY_SET_A)));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_C));
}
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_C));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, KEY_SET_A.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fails with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchLoaderAllFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_C, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses(), Matchers.<Map<?,?>>equalTo(getEntryMap(KEY_SET_A)));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_C));
}
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_C));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, KEY_SET_A.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fails with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchLoaderSomeFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_C, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses(), Matchers.<Map<?, ?>>equalTo(getEntryMap(KEY_SET_A, KEY_SET_D)));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_C));
}
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(union(KEY_SET_C, KEY_SET_D)));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, KEY_SET_A.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionBeforeLoaderAllFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES);
this.loaderWriter = spy(fakeLoader);
doThrow(new Exception("loadAll failed")).when(this.loaderWriter).loadAll(getAnyStringSet());
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().keySet(), empty());
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionBeforeLoaderAllFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, union(KEY_SET_A, KEY_SET_C), true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), empty());
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), Collections.<String> emptySet(), fetchKeys);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionBeforeLoaderLSomeFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, union(KEY_SET_A, KEY_SET_C), true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_D));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(union(KEY_SET_A, KEY_SET_C)));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), KEY_SET_D, union(KEY_SET_A, KEY_SET_C));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionAfterLoaderAllFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES);
this.loaderWriter = spy(fakeLoader);
doThrow(new Exception("loadAll failed")).when(this.loaderWriter).loadAll(getAnyStringSet());
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().isEmpty(), is(true));
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionAfterLoaderAllFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, fetchKeys, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), empty());
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), Collections.<String> emptySet(), fetchKeys);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionAfterLoaderSomeFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_A, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_C));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), KEY_SET_C, KEY_SET_A);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchLoaderNoMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_F));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(union(getEntryMap(KEY_SET_A), getNullEntryMap(KEY_SET_C))));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(KEY_SET_C));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, KEY_SET_A.size(), KEY_SET_C.size());
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionBeforeLoaderNoMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_F));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = getNullEntryMap(fetchKeys);
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionAfterLoaderNoMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_B));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(union(getNullEntryMap(KEY_SET_C), getEntryMap(KEY_SET_A))));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(actual), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchLoaderNoMatchSomeFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_F), KEY_SET_D);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses(), Matchers.<Map<?,?>>equalTo(union(getEntryMap(KEY_SET_A), getNullEntryMap(KEY_SET_C))));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_D));
}
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(copyWithout(fetchKeys, KEY_SET_A)));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, KEY_SET_A.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchLoaderNoMatchSomeFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_D, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses(), Matchers.<Map<?,?>>equalTo(union(getEntryMap(KEY_SET_A), getEntryMap(KEY_SET_C))));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_D));
}
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(copyWithout(fetchKeys, KEY_SET_A)));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, KEY_SET_A.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionBeforeLoaderNoMatchSomeFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_F), KEY_SET_D);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().keySet(), empty());
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionBeforeLoaderNoMatchAllFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, fetchKeys, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), empty());
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), Collections.<String> emptySet(), fetchKeys);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionAfterLoaderNoMatchSomeFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_B), KEY_SET_D);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
final Set<String> successKeys = copyWithout(copyUntil(fetchKeys, "keyA3"), fanIn(KEY_SET_A, KEY_SET_D));
final Set<String> failKeys = copyWithout(fetchKeys, successKeys);
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses(),
Matchers.<Map<?, ?>>equalTo(getNullEntryMap(successKeys)));
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(failKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchLoaderSomeMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C, KEY_SET_F));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(union(getEntryMap(KEY_SET_A, KEY_SET_C), getNullEntryMap(KEY_SET_D))));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B, KEY_SET_C)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(copyWithout(fetchKeys, KEY_SET_A)));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, KEY_SET_A.size() + KEY_SET_C.size(), KEY_SET_D.size());
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionBeforeLoaderSomeMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C, KEY_SET_F));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = union(getNullEntryMap(KEY_SET_A, KEY_SET_D), getEntryMap(KEY_SET_C));
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionAfterLoaderSomeMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_B, KEY_SET_C, KEY_SET_F));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(union(getNullEntryMap(KEY_SET_D), getEntryMap(KEY_SET_A, KEY_SET_C))));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(actual), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchLoaderSomeMatchDisjointFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C, KEY_SET_E), KEY_SET_F);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D, KEY_SET_F);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses(),
Matchers.<Map<?,?>>equalTo(union(getEntryMap(KEY_SET_A, KEY_SET_C), getNullEntryMap(KEY_SET_D))));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_F));
}
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B, KEY_SET_C)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(copyWithout(fetchKeys, KEY_SET_A)));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, KEY_SET_A.size() + KEY_SET_C.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fails with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchLoaderSomeMatchDisjointFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, union(KEY_SET_D, KEY_SET_F), true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D, KEY_SET_F);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses(),Matchers.<Map<?,?>>equalTo(getEntryMap(KEY_SET_A, KEY_SET_C)));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(union(KEY_SET_D, KEY_SET_F)));
}
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(copyWithout(fetchKeys, KEY_SET_A)));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, KEY_SET_A.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionBeforeLoaderSomeMatchDisjointFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C, KEY_SET_E), KEY_SET_F);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D, KEY_SET_F);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().keySet(), empty());
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionBeforeLoaderSomeMatchDisjointFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, union(KEY_SET_A, KEY_SET_C), true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_E);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses(), Matchers.<Map<?,?>>equalTo(getEntryMap(KEY_SET_E)));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(union(KEY_SET_A, KEY_SET_C)));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), KEY_SET_E, union(KEY_SET_A, KEY_SET_C));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionAfterLoaderSomeMatchDisjointFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_B, KEY_SET_C, KEY_SET_E), KEY_SET_F);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D, KEY_SET_F);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
final Set<String> successKeys = copyWithout(copyUntil(fetchKeys, "keyA3"), fanIn(KEY_SET_A, KEY_SET_F));
final Set<String> failKeys = copyWithout(fetchKeys, successKeys);
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses(),
Matchers.<Map<?,?>>equalTo(union(getEntryMap(copyOnly(KEY_SET_C, successKeys)),
getNullEntryMap(copyOnly(KEY_SET_D, successKeys)))));
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(failKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionAfterLoaderSomeMatchDisjointFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, union(KEY_SET_D, KEY_SET_F), true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D, KEY_SET_F);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses(), Matchers.<Map<?,?>>equalTo(union(getEntryMap(KEY_SET_A), getEntryMap(KEY_SET_C))));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(union(KEY_SET_D, KEY_SET_F)));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>all {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchLoaderAllMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_C, KEY_SET_D));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(getEntryMap(fetchKeys)));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B, KEY_SET_C, KEY_SET_D)));
verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(copyWithout(fetchKeys, KEY_SET_A)));
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, fetchKeys.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>all {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionBeforeLoaderAllMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_C, KEY_SET_D));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = getEntryMap(fetchKeys);
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>some {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>all {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreSomeMatchStoreAccessExceptionAfterLoaderAllMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_C, KEY_SET_D));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_C, KEY_SET_D);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = getEntryMap(fetchKeys);
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchLoaderAllFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES);
this.loaderWriter = spy(fakeLoader);
doThrow(new Exception("loadAll failed")).when(this.loaderWriter).loadAll(getAnyStringSet());
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(getEntryMap(fetchKeys)));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B)));
verify(this.loaderWriter, never()).loadAll(getAnyStringSet());
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, fetchKeys.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionBeforeLoaderAllFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES);
this.loaderWriter = spy(fakeLoader);
doThrow(new Exception("loadAll failed")).when(this.loaderWriter).loadAll(getAnyStringSet());
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().keySet(), empty());
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionBeforeLoaderAllFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, fetchKeys, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), empty());
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(union(KEY_SET_A, KEY_SET_B)));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), Collections.<String> emptySet(), fetchKeys);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionBeforeLoaderSomeFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_A, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_B));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), KEY_SET_B, KEY_SET_A);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionAfterLoaderAllFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES);
this.loaderWriter = spy(fakeLoader);
doThrow(new Exception("loadAll failed")).when(this.loaderWriter).loadAll(getAnyStringSet());
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().keySet(), empty());
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>all {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionAfterLoaderAllFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, fetchKeys, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), empty());
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), Collections.<String> emptySet(), fetchKeys);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>with a {@code CacheLoaderWriter} (loader-provided entries not relevant)</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionAfterLoaderSomeFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_A, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_B));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), KEY_SET_B, KEY_SET_A);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchLoaderNoMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(getEntryMap(fetchKeys)));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B)));
verify(this.loaderWriter, never()).loadAll(getAnyStringSet());
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, fetchKeys.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionBeforeLoaderNoMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = getNullEntryMap(fetchKeys);
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchLoaderNoMatchSomeFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C, KEY_SET_F), KEY_SET_B);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(getEntryMap(fetchKeys)));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B)));
verify(this.loaderWriter, never()).loadAll(getAnyStringSet());
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, fetchKeys.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionBeforeLoaderNoMatchSomeFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_C, KEY_SET_F), KEY_SET_B);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().keySet(), empty());
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionBeforeLoaderNoMatchSomeFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, fetchKeys, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), empty());
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), Collections.<String> emptySet(), fetchKeys);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>no {@link CacheLoaderWriter} entries match</li>
* <li>some {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionAfterLoaderNoMatchSomeFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_C, KEY_SET_F), KEY_SET_B);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().keySet(), empty());
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchLoaderSomeMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_B, KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(getEntryMap(fetchKeys)));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B)));
verify(this.loaderWriter, never()).loadAll(getAnyStringSet());
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, fetchKeys.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionBeforeLoaderSomeMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_B, KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = union(getNullEntryMap(KEY_SET_A), getEntryMap(KEY_SET_B));
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(fetchKeys);
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionAfterLoaderSomeMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_B, KEY_SET_C));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = getEntryMap(KEY_SET_A, KEY_SET_B);
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(fetchKeys);
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchLoaderSomeMatchDisjointFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_B, KEY_SET_C), KEY_SET_A);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = getEntryMap(KEY_SET_A, KEY_SET_B);
assertThat(actual, equalTo(expected));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B)));
verify(this.loaderWriter, never()).loadAll(getAnyStringSet());
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, fetchKeys.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionBeforeLoaderSomeMatchDisjointFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_B, KEY_SET_C), KEY_SET_A);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses(), Matchers.<Map<?,?>>equalTo(Collections.emptyMap()));
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionBeforeLoaderSomeMatchDisjointFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_A, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_B));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), KEY_SET_B, KEY_SET_A);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionAfterLoaderSomeMatchDisjointFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_B, KEY_SET_C), KEY_SET_A);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses(), Matchers.<Map<?,?>>equalTo(Collections.emptyMap()));
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>>equalTo(fetchKeys));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>some {@link CacheLoaderWriter} entries match</li>
* <li>non-matching {@link CacheLoaderWriter#loadAll(Iterable)} calls fail with {@link BulkCacheLoadingException}</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionAfterLoaderSomeMatchDisjointFailWithBulkCacheLoadingException() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(TEST_ENTRIES, KEY_SET_A, true);
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
try {
ehcache.getAll(fetchKeys);
fail();
} catch (BulkCacheLoadingException e) {
// Expected
assertThat(e.getSuccesses().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_B));
assertThat(e.getFailures().keySet(), Matchers.<Set<?>>equalTo(KEY_SET_A));
}
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), any(StoreAccessException.class), this.bulkExceptionCaptor.capture());
verifyBulkLoadingException(this.bulkExceptionCaptor.getValue(), KEY_SET_B, KEY_SET_A);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>all {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchLoaderAllMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_B));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
assertThat(actual, equalTo(getEntryMap(fetchKeys)));
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
assertThat(fakeStore.getEntryMap(), equalTo(getEntryMap(KEY_SET_A, KEY_SET_B)));
verify(this.loaderWriter, never()).loadAll(getAnyStringSet());
verifyZeroInteractions(this.spiedResilienceStrategy);
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.SUCCESS));
validateBulkCounters(ehcache, fetchKeys.size(), 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws before accessing loader</li>
* <li>all {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionBeforeLoaderAllMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B));
this.store = spy(fakeStore);
doThrow(new StoreAccessException("")).when(this.store)
.bulkComputeIfAbsent(getAnyStringSet(), getAnyIterableFunction());
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_B));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = getEntryMap(fetchKeys);
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
/**
* Tests {@link EhcacheWithLoaderWriter#getAll(Set)} for
* <ul>
* <li>non-empty request key set</li>
* <li>all {@link Store} entries match</li>
* <li>{@link Store#bulkComputeIfAbsent} throws after accessing loader</li>
* <li>all {@link CacheLoaderWriter} entries match</li>
* <li>no {@link CacheLoaderWriter#loadAll(Iterable)} calls fail</li>
* </ul>
*/
@Test
public void testGetAllStoreAllMatchStoreAccessExceptionAfterLoaderAllMatchNoneFail() throws Exception {
final FakeStore fakeStore = new FakeStore(getEntryMap(KEY_SET_A, KEY_SET_B), Collections.singleton("keyA3"));
this.store = spy(fakeStore);
final FakeCacheLoaderWriter fakeLoader = new FakeCacheLoaderWriter(getEntryMap(KEY_SET_A, KEY_SET_B));
this.loaderWriter = spy(fakeLoader);
final EhcacheWithLoaderWriter<String, String> ehcache = this.getEhcache(this.loaderWriter);
final Set<String> fetchKeys = fanIn(KEY_SET_A, KEY_SET_B);
final Map<String, String> actual = ehcache.getAll(fetchKeys);
final Map<String, String> expected = getEntryMap(fetchKeys);
assertThat(actual, equalTo(expected));
final InOrder ordered = inOrder(this.loaderWriter, this.spiedResilienceStrategy);
verify(this.store).bulkComputeIfAbsent(eq(fetchKeys), getAnyIterableFunction());
// ResilienceStrategy invoked: no assertion for Store content
ordered.verify(this.loaderWriter, atLeast(1)).loadAll(this.loadAllCaptor.capture());
assertThat(this.getLoadAllArgs(), equalTo(fetchKeys));
ordered.verify(this.spiedResilienceStrategy)
.getAllFailure(eq(fetchKeys), eq(expected), any(StoreAccessException.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.GetOutcome.class));
validateStats(ehcache, EnumSet.noneOf(CacheOperationOutcomes.CacheLoadingOutcome.class));
validateStats(ehcache, EnumSet.of(CacheOperationOutcomes.GetAllOutcome.FAILURE));
validateBulkCounters(ehcache, 0, 0);
}
private EhcacheWithLoaderWriter<String, String> getEhcache(final CacheLoaderWriter<String, String> cacheLoaderWriter) {
final EhcacheWithLoaderWriter<String, String> ehcache = new EhcacheWithLoaderWriter<String, String>(CACHE_CONFIGURATION, this.store, cacheLoaderWriter, cacheEventDispatcher, LoggerFactory.getLogger(EhcacheWithLoaderWriter.class + "-" + "EhcacheWithLoaderWriterBasicGetAllTest"));
ehcache.init();
assertThat("cache not initialized", ehcache.getStatus(), Matchers.is(Status.AVAILABLE));
this.spiedResilienceStrategy = this.setResilienceStrategySpy(ehcache);
return ehcache;
}
private void verifyBulkLoadingException(BulkCacheLoadingException e, Set<String> successKeys, Set<String> failureKeys) {
assertThat(this.bulkExceptionCaptor.getValue().getSuccesses().keySet(), Matchers.<Set<?>> equalTo(successKeys));
assertThat(this.bulkExceptionCaptor.getValue().getFailures().keySet(), Matchers.<Set<?>> equalTo(failureKeys));
}
/**
* Collects all arguments captured by {@link #loadAllCaptor}.
*
* @return the argument values collected by {@link #loadAllCaptor}; the
* {@code Iterator} over the resulting {@code Set} returns the values
* in the order observed by the captor.
*/
private Set<String> getLoadAllArgs() {
final Set<String> loadAllArgs = new LinkedHashSet<String>();
for (final Set<String> set : this.loadAllCaptor.getAllValues()) {
loadAllArgs.addAll(set);
}
return loadAllArgs;
}
}