@Test
 public void testContainsKey() throws Exception {
   assertThat(store.containsKey(1L), is(false));
   store.put(1L, "one");
   assertThat(store.containsKey(1L), is(true));
   validateStat(store, StoreOperationOutcomes.GetOutcome.HIT, 0);
   validateStat(store, StoreOperationOutcomes.GetOutcome.MISS, 0);
 }
 @Test
 public void testPut() throws Exception {
   assertThat(store.put(1L, "one"), is(Store.PutStatus.PUT));
   validateStats(store, EnumSet.of(StoreOperationOutcomes.PutOutcome.PUT));
   assertThat(store.put(1L, "another one"), is(Store.PutStatus.UPDATE));
   assertThat(store.put(1L, "yet another one"), is(Store.PutStatus.UPDATE));
   validateStat(store, StoreOperationOutcomes.PutOutcome.REPLACED, 2);
   validateStat(store, StoreOperationOutcomes.PutOutcome.PUT, 1);
 }
 @Test
 public void testGet() throws Exception {
   assertThat(store.get(1L), nullValue());
   validateStats(store, EnumSet.of(StoreOperationOutcomes.GetOutcome.MISS));
   store.put(1L, "one");
   assertThat(store.get(1L).value(), is("one"));
   validateStats(
       store,
       EnumSet.of(StoreOperationOutcomes.GetOutcome.MISS, StoreOperationOutcomes.GetOutcome.HIT));
 }
 @Test(expected = StoreAccessException.class)
 public void testConditionalReplaceThrowsOnlySAE() throws Exception {
   OperationsCodec<Long, String> codec = mock(OperationsCodec.class);
   ChainResolver chainResolver = mock(ChainResolver.class);
   ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class);
   when(serverStoreProxy.get(anyLong())).thenThrow(new RuntimeException());
   TestTimeSource testTimeSource = mock(TestTimeSource.class);
   ClusteredStore<Long, String> store =
       new ClusteredStore<Long, String>(codec, chainResolver, serverStoreProxy, testTimeSource);
   store.replace(1L, "one", "another one");
 }
 @Test
 public void testPutIfAbsent() throws Exception {
   assertThat(store.putIfAbsent(1L, "one"), nullValue());
   validateStats(store, EnumSet.of(StoreOperationOutcomes.PutIfAbsentOutcome.PUT));
   assertThat(store.putIfAbsent(1L, "another one").value(), is("one"));
   validateStats(
       store,
       EnumSet.of(
           StoreOperationOutcomes.PutIfAbsentOutcome.PUT,
           StoreOperationOutcomes.PutIfAbsentOutcome.HIT));
 }
 @Test(expected = StoreAccessException.class)
 public void testClearThrowsOnlySAE() throws Exception {
   OperationsCodec<Long, String> codec = mock(OperationsCodec.class);
   ChainResolver chainResolver = mock(ChainResolver.class);
   ServerStoreProxy serverStoreProxy = mock(ServerStoreProxy.class);
   doThrow(new RuntimeException()).when(serverStoreProxy).clear();
   TestTimeSource testTimeSource = mock(TestTimeSource.class);
   ClusteredStore<Long, String> store =
       new ClusteredStore<Long, String>(codec, chainResolver, serverStoreProxy, testTimeSource);
   store.remove(1L);
 }
 @Test
 public void testConditionalReplace() throws Exception {
   assertThat(store.replace(1L, "one", "another one"), is(Store.ReplaceStatus.MISS_NOT_PRESENT));
   validateStats(store, EnumSet.of(StoreOperationOutcomes.ConditionalReplaceOutcome.MISS));
   store.put(1L, "some other one");
   assertThat(store.replace(1L, "one", "another one"), is(Store.ReplaceStatus.MISS_PRESENT));
   validateStat(store, StoreOperationOutcomes.ConditionalReplaceOutcome.MISS, 2);
   validateStat(store, StoreOperationOutcomes.ConditionalReplaceOutcome.REPLACED, 0);
   assertThat(store.replace(1L, "some other one", "another one"), is(Store.ReplaceStatus.HIT));
   validateStat(store, StoreOperationOutcomes.ConditionalReplaceOutcome.REPLACED, 1);
   validateStat(store, StoreOperationOutcomes.ConditionalReplaceOutcome.MISS, 2);
 }
 @Test
 public void testReplace() throws Exception {
   assertThat(store.replace(1L, "one"), nullValue());
   validateStats(store, EnumSet.of(StoreOperationOutcomes.ReplaceOutcome.MISS));
   store.put(1L, "one");
   assertThat(store.replace(1L, "another one").value(), is("one"));
   validateStats(
       store,
       EnumSet.of(
           StoreOperationOutcomes.ReplaceOutcome.MISS,
           StoreOperationOutcomes.ReplaceOutcome.REPLACED));
 }
 @Test
 public void testRemove() throws Exception {
   assertThat(store.remove(1L), is(false));
   validateStats(store, EnumSet.of(StoreOperationOutcomes.RemoveOutcome.MISS));
   store.put(1L, "one");
   assertThat(store.remove(1L), is(true));
   assertThat(store.containsKey(1L), is(false));
   validateStats(
       store,
       EnumSet.of(
           StoreOperationOutcomes.RemoveOutcome.MISS,
           StoreOperationOutcomes.RemoveOutcome.REMOVED));
 }
  @Test
  public void testBulkComputeIfAbsentGetAll() throws Exception {
    store.put(1L, "one");
    store.put(2L, "two");
    Ehcache.GetAllFunction<Long, String> getAllAllFunction =
        new Ehcache.GetAllFunction<Long, String>();
    Map<Long, Store.ValueHolder<String>> valueHolderMap =
        store.bulkComputeIfAbsent(new HashSet<Long>(Arrays.asList(1L, 2L)), getAllAllFunction);

    assertThat(valueHolderMap.get(1L).value(), is("one"));
    assertThat(store.get(1L).value(), is("one"));
    assertThat(valueHolderMap.get(2L).value(), is("two"));
    assertThat(store.get(2L).value(), is("two"));
  }
 @Test
 public void testConditionalRemove() throws Exception {
   assertThat(store.remove(1L, "one"), is(Store.RemoveStatus.KEY_MISSING));
   validateStats(store, EnumSet.of(StoreOperationOutcomes.ConditionalRemoveOutcome.MISS));
   store.put(1L, "one");
   assertThat(store.remove(1L, "one"), is(Store.RemoveStatus.REMOVED));
   validateStats(
       store,
       EnumSet.of(
           StoreOperationOutcomes.ConditionalRemoveOutcome.MISS,
           StoreOperationOutcomes.ConditionalRemoveOutcome.REMOVED));
   store.put(1L, "another one");
   assertThat(store.remove(1L, "one"), is(Store.RemoveStatus.KEY_PRESENT));
   validateStat(store, StoreOperationOutcomes.ConditionalRemoveOutcome.MISS, 2);
 }
 @Test(expected = UnsupportedOperationException.class)
 public void testBulkComputeIfAbsentThrowsForGenericFunction() throws Exception {
   Function<
           Iterable<? extends Long>,
           Iterable<? extends Map.Entry<? extends Long, ? extends String>>>
       mappingFunction = mock(Function.class);
   store.bulkComputeIfAbsent(new HashSet<Long>(Arrays.asList(1L, 2L)), mappingFunction);
 }
  @Test
  public void testBulkComputePutAll() throws Exception {
    store.put(1L, "another one");
    Map<Long, String> map = new HashMap<Long, String>();
    map.put(1L, "one");
    map.put(2L, "two");
    Ehcache.PutAllFunction<Long, String> putAllFunction =
        new Ehcache.PutAllFunction<Long, String>(null, map, null);
    Map<Long, Store.ValueHolder<String>> valueHolderMap =
        store.bulkCompute(new HashSet<Long>(Arrays.asList(1L, 2L)), putAllFunction);

    assertThat(valueHolderMap.get(1L).value(), is(map.get(1L)));
    assertThat(store.get(1L).value(), is(map.get(1L)));
    assertThat(valueHolderMap.get(2L).value(), is(map.get(2L)));
    assertThat(store.get(2L).value(), is(map.get(2L)));
    assertThat(putAllFunction.getActualPutCount().get(), is(2));
    validateStats(
        store,
        EnumSet.of(StoreOperationOutcomes.PutOutcome.PUT)); // outcome of the initial store put
  }
  @Test
  public void testClear() throws Exception {
    assertThat(store.containsKey(1L), is(false));
    store.clear();
    assertThat(store.containsKey(1L), is(false));

    store.put(1L, "one");
    store.put(2L, "two");
    store.put(3L, "three");
    assertThat(store.containsKey(1L), is(true));

    store.clear();

    assertThat(store.containsKey(1L), is(false));
    assertThat(store.containsKey(2L), is(false));
    assertThat(store.containsKey(3L), is(false));
  }
  @Test
  public void testBulkComputeRemoveAll() throws Exception {
    store.put(1L, "one");
    store.put(2L, "two");
    store.put(3L, "three");
    Ehcache.RemoveAllFunction<Long, String> removeAllFunction =
        new Ehcache.RemoveAllFunction<Long, String>();
    Map<Long, Store.ValueHolder<String>> valueHolderMap =
        store.bulkCompute(new HashSet<Long>(Arrays.asList(1L, 2L, 4L)), removeAllFunction);

    assertThat(valueHolderMap.get(1L), nullValue());
    assertThat(store.get(1L), nullValue());
    assertThat(valueHolderMap.get(2L), nullValue());
    assertThat(store.get(2L), nullValue());
    assertThat(valueHolderMap.get(4L), nullValue());
    assertThat(store.get(4L), nullValue());
    validateStats(store, EnumSet.noneOf(StoreOperationOutcomes.RemoveOutcome.class));
  }