@Test
  public void testRemoveAll_without_cache_writer() throws Exception {
    CacheConfigurationBuilder cacheConfigurationBuilder =
        CacheConfigurationBuilder.newCacheConfigurationBuilder(
            String.class, String.class, heap(100));
    CacheConfiguration<String, String> cacheConfiguration = cacheConfigurationBuilder.build();

    CacheManagerBuilder<CacheManager> managerBuilder = CacheManagerBuilder.newCacheManagerBuilder();
    CacheManager cacheManager = managerBuilder.withCache("myCache", cacheConfiguration).build(true);

    Cache<String, String> myCache = cacheManager.getCache("myCache", String.class, String.class);

    for (int i = 0; i < 3; i++) {
      myCache.put("key" + i, "value" + i);
    }

    Set<String> fewKeysSet =
        new HashSet<String>() {
          {
            add("key0");
            add("key2");
          }
        };
    // the call to removeAll
    myCache.removeAll(fewKeysSet);

    for (int i = 0; i < 3; i++) {
      if (i == 0 || i == 2) {
        assertThat(myCache.get("key" + i), is(nullValue()));
      } else {
        assertThat(myCache.get("key" + i), is("value" + i));
      }
    }
  }
  @Test
  public void testGetAll_without_cache_loader() throws Exception {
    CacheConfigurationBuilder cacheConfigurationBuilder =
        CacheConfigurationBuilder.newCacheConfigurationBuilder(
            String.class, String.class, heap(100));
    CacheConfiguration<String, String> cacheConfiguration = cacheConfigurationBuilder.build();

    CacheManagerBuilder<CacheManager> managerBuilder = CacheManagerBuilder.newCacheManagerBuilder();
    CacheManager cacheManager = managerBuilder.withCache("myCache", cacheConfiguration).build(true);

    Cache<String, String> myCache = cacheManager.getCache("myCache", String.class, String.class);

    for (int i = 0; i < 3; i++) {
      myCache.put("key" + i, "value" + i);
    }

    Set<String> fewKeysSet =
        new HashSet<String>() {
          {
            add("key0");
            add("key2");
          }
        };
    // the call to getAll
    Map<String, String> fewEntries = myCache.getAll(fewKeysSet);

    assertThat(fewEntries.size(), is(2));
    assertThat(fewEntries.get("key0"), is("value0"));
    assertThat(fewEntries.get("key2"), is("value2"));
  }
  @Test
  public void testRemoveAll_with_cache_writer() throws Exception {
    CacheConfigurationBuilder cacheConfigurationBuilder =
        CacheConfigurationBuilder.newCacheConfigurationBuilder(
            String.class, String.class, heap(100));
    CacheConfiguration<String, String> cacheConfiguration = cacheConfigurationBuilder.build();

    CacheLoaderWriterProvider cacheLoaderWriterProvider = mock(CacheLoaderWriterProvider.class);
    CacheLoaderWriter cacheLoaderWriter = mock(CacheLoaderWriter.class);
    doThrow(new RuntimeException("We should not have called .write() but .writeAll()"))
        .when(cacheLoaderWriter)
        .delete(Matchers.anyObject());
    when(cacheLoaderWriterProvider.createCacheLoaderWriter(
            anyString(), Matchers.any(CacheConfiguration.class)))
        .thenReturn(cacheLoaderWriter);

    CacheManagerBuilder<CacheManager> managerBuilder =
        CacheManagerBuilder.newCacheManagerBuilder().using(cacheLoaderWriterProvider);
    CacheManager cacheManager = managerBuilder.withCache("myCache", cacheConfiguration).build(true);

    Cache<String, String> myCache = cacheManager.getCache("myCache", String.class, String.class);

    for (int i = 0; i < 3; i++) {
      myCache.put("key" + i, "value" + i);
    }

    Set<String> fewKeysSet =
        new HashSet<String>() {
          {
            add("key0");
            add("key2");
          }
        };

    // the call to removeAll
    myCache.removeAll(fewKeysSet);

    for (int i = 0; i < 3; i++) {
      if (i == 0 || i == 2) {
        assertThat(myCache.get("key" + i), is(nullValue()));
      } else {
        assertThat(myCache.get("key" + i), is("value" + i));
      }
    }
    Set set =
        new HashSet() {
          {
            add("key0");
          }
        };
    verify(cacheLoaderWriter).deleteAll(set);
    set =
        new HashSet() {
          {
            add("key2");
          }
        };
    verify(cacheLoaderWriter).deleteAll(set);
  }
  @Test
  public void testPutAll_with_cache_writer() throws Exception {
    CacheConfigurationBuilder cacheConfigurationBuilder =
        CacheConfigurationBuilder.newCacheConfigurationBuilder(
            String.class, String.class, heap(100));
    CacheConfiguration<String, String> cacheConfiguration = cacheConfigurationBuilder.build();

    CacheLoaderWriterProvider cacheLoaderWriterProvider = mock(CacheLoaderWriterProvider.class);
    CacheLoaderWriter cacheLoaderWriter = mock(CacheLoaderWriter.class);
    doThrow(new RuntimeException("We should not have called .write() but .writeAll()"))
        .when(cacheLoaderWriter)
        .write(Matchers.anyObject(), Matchers.anyObject());
    when(cacheLoaderWriterProvider.createCacheLoaderWriter(
            anyString(), Matchers.any(CacheConfiguration.class)))
        .thenReturn(cacheLoaderWriter);

    CacheManagerBuilder<CacheManager> managerBuilder =
        CacheManagerBuilder.newCacheManagerBuilder().using(cacheLoaderWriterProvider);
    CacheManager cacheManager = managerBuilder.withCache("myCache", cacheConfiguration).build(true);

    Cache<String, String> myCache = cacheManager.getCache("myCache", String.class, String.class);

    HashMap<String, String> stringStringHashMap = new HashMap<String, String>();
    for (int i = 0; i < 3; i++) {
      stringStringHashMap.put("key" + i, "value" + i);
    }

    // the call to putAll
    myCache.putAll(stringStringHashMap);

    verify(cacheLoaderWriter, times(3)).writeAll(Matchers.any(Iterable.class));
    Set set =
        new HashSet() {
          {
            add(entry("key0", "value0"));
          }
        };
    verify(cacheLoaderWriter).writeAll(set);
    set =
        new HashSet() {
          {
            add(entry("key1", "value1"));
          }
        };
    verify(cacheLoaderWriter).writeAll(set);
    set =
        new HashSet() {
          {
            add(entry("key2", "value2"));
          }
        };
    verify(cacheLoaderWriter).writeAll(set);

    for (int i = 0; i < 3; i++) {
      assertThat(myCache.get("key" + i), is("value" + i));
    }
  }
  @Test
  public void testPutAll_store_throws_cache_exception() throws Exception {
    CacheConfigurationBuilder cacheConfigurationBuilder =
        CacheConfigurationBuilder.newCacheConfigurationBuilder(
            String.class, String.class, heap(100));
    CacheConfiguration<String, String> cacheConfiguration = cacheConfigurationBuilder.build();

    CacheLoaderWriterProvider cacheLoaderWriterProvider = mock(CacheLoaderWriterProvider.class);
    CacheLoaderWriter cacheLoaderWriter = mock(CacheLoaderWriter.class);
    doThrow(new RuntimeException("We should not have called .write() but .writeAll()"))
        .when(cacheLoaderWriter)
        .write(Matchers.anyObject(), Matchers.anyObject());
    when(cacheLoaderWriterProvider.createCacheLoaderWriter(
            anyString(), Matchers.any(CacheConfiguration.class)))
        .thenReturn(cacheLoaderWriter);

    CacheManagerBuilder<CacheManager> managerBuilder =
        CacheManagerBuilder.newCacheManagerBuilder()
            .using(cacheLoaderWriterProvider)
            .using(new CustomStoreProvider());
    CacheManager cacheManager = managerBuilder.withCache("myCache", cacheConfiguration).build(true);

    Cache<String, String> myCache = cacheManager.getCache("myCache", String.class, String.class);

    Map<String, String> stringStringHashMap = new HashMap<String, String>();
    for (int i = 0; i < 3; i++) {
      stringStringHashMap.put("key" + i, "value" + i);
    }

    // the call to putAll
    myCache.putAll(stringStringHashMap);

    for (int i = 0; i < 3; i++) {
      // the store threw an exception when we call bulkCompute
      assertThat(myCache.get("key" + i), is(nullValue()));
      // but still, the cache writer could writeAll the values !
      //      assertThat(cacheWriterToHashMapMap.get("key" + i), is("value" + i));
    }
    // but still, the cache writer could writeAll the values at once !
    verify(cacheLoaderWriter, times(1)).writeAll(Matchers.any(Iterable.class));
    Set set =
        new HashSet() {
          {
            add(entry("key0", "value0"));
            add(entry("key1", "value1"));
            add(entry("key2", "value2"));
          }
        };
    verify(cacheLoaderWriter).writeAll(set);
  }
  @Test
  public void testGetAll_with_cache_loader() throws Exception {
    CacheConfigurationBuilder cacheConfigurationBuilder =
        CacheConfigurationBuilder.newCacheConfigurationBuilder(
            String.class, String.class, heap(100));
    CacheConfiguration<String, String> cacheConfiguration = cacheConfigurationBuilder.build();

    CacheLoaderWriterProvider cacheLoaderWriterProvider = mock(CacheLoaderWriterProvider.class);
    CacheLoaderWriter cacheLoaderWriter = mock(CacheLoaderWriter.class);
    when(cacheLoaderWriter.load(Matchers.anyObject()))
        .thenThrow(new RuntimeException("We should not have called .load() but .loadAll()"));
    when(cacheLoaderWriterProvider.createCacheLoaderWriter(
            anyString(), Matchers.any(CacheConfiguration.class)))
        .thenReturn(cacheLoaderWriter);
    CacheManagerBuilder<CacheManager> managerBuilder =
        CacheManagerBuilder.newCacheManagerBuilder().using(cacheLoaderWriterProvider);
    CacheManager cacheManager = managerBuilder.withCache("myCache", cacheConfiguration).build(true);

    when(cacheLoaderWriter.loadAll(argThat(hasItem("key0"))))
        .thenReturn(
            new HashMap() {
              {
                put("key0", "value0");
              }
            });
    when(cacheLoaderWriter.loadAll(argThat(hasItem("key2"))))
        .thenReturn(
            new HashMap() {
              {
                put("key2", "value2");
              }
            });

    Cache<String, String> myCache = cacheManager.getCache("myCache", String.class, String.class);

    Set<String> fewKeysSet =
        new HashSet<String>() {
          {
            add("key0");
            add("key2");
          }
        };
    // the call to getAll
    Map<String, String> fewEntries = myCache.getAll(fewKeysSet);

    assertThat(fewEntries.size(), is(2));
    assertThat(fewEntries.get("key0"), is("value0"));
    assertThat(fewEntries.get("key2"), is("value2"));
  }
  @Test
  public void testRemoveAll_cache_writer_throws_exception() throws Exception {
    CacheConfigurationBuilder cacheConfigurationBuilder =
        CacheConfigurationBuilder.newCacheConfigurationBuilder(
            String.class, String.class, heap(100));
    CacheConfiguration<String, String> cacheConfiguration = cacheConfigurationBuilder.build();

    CacheLoaderWriterProvider cacheLoaderWriterProvider = mock(CacheLoaderWriterProvider.class);
    CacheLoaderWriter cacheLoaderWriterThatThrows = mock(CacheLoaderWriter.class);
    doThrow(new Exception("Simulating an exception from the cache writer"))
        .when(cacheLoaderWriterThatThrows)
        .deleteAll(Matchers.any(Iterable.class));
    when(cacheLoaderWriterProvider.createCacheLoaderWriter(
            anyString(), Matchers.any(CacheConfiguration.class)))
        .thenReturn(cacheLoaderWriterThatThrows);

    CacheManagerBuilder<CacheManager> managerBuilder =
        CacheManagerBuilder.newCacheManagerBuilder().using(cacheLoaderWriterProvider);
    CacheManager cacheManager = managerBuilder.withCache("myCache", cacheConfiguration).build(true);

    Cache<String, String> myCache = cacheManager.getCache("myCache", String.class, String.class);

    for (int i = 0; i < 3; i++) {
      myCache.put("key" + i, "value" + i);
    }

    doThrow(new RuntimeException("We should not have called .write() but .writeAll()"))
        .when(cacheLoaderWriterThatThrows)
        .write(Matchers.anyObject(), Matchers.anyObject());

    Set<String> fewKeysSet =
        new HashSet<String>() {
          {
            add("key0");
            add("key2");
          }
        };

    // the call to removeAll
    try {
      myCache.removeAll(fewKeysSet);
      fail();
    } catch (BulkCacheWritingException bcwe) {
      assertThat(bcwe.getFailures().size(), is(2));
      assertThat(bcwe.getSuccesses().size(), is(0));
    }
  }
  @Test
  public void testGetAll_cache_loader_throws_exception() throws Exception {
    CacheConfigurationBuilder cacheConfigurationBuilder =
        CacheConfigurationBuilder.newCacheConfigurationBuilder(
            String.class, String.class, heap(100));
    CacheConfiguration<String, String> cacheConfiguration = cacheConfigurationBuilder.build();

    CacheLoaderWriterProvider cacheLoaderWriterProvider = mock(CacheLoaderWriterProvider.class);
    CacheLoaderWriter cacheLoaderWriter = mock(CacheLoaderWriter.class);
    when(cacheLoaderWriter.load(Matchers.anyObject()))
        .thenThrow(new RuntimeException("We should not have called .load() but .loadAll()"));
    when(cacheLoaderWriter.loadAll(Matchers.any(Iterable.class)))
        .thenThrow(new Exception("Simulating an exception from the cache loader"));
    when(cacheLoaderWriterProvider.createCacheLoaderWriter(
            anyString(), Matchers.any(CacheConfiguration.class)))
        .thenReturn(cacheLoaderWriter);
    CacheManagerBuilder<CacheManager> managerBuilder =
        CacheManagerBuilder.newCacheManagerBuilder().using(cacheLoaderWriterProvider);
    CacheManager cacheManager = managerBuilder.withCache("myCache", cacheConfiguration).build(true);

    Cache<String, String> myCache = cacheManager.getCache("myCache", String.class, String.class);

    Set<String> fewKeysSet =
        new HashSet<String>() {
          {
            add("key0");
            add("key2");
          }
        };

    // the call to getAll
    try {
      myCache.getAll(fewKeysSet);
      fail();
    } catch (BulkCacheLoadingException bcwe) {
      // since onHeapStore.bulkComputeIfAbsent sends batches of 1 element,
      assertThat(bcwe.getFailures().size(), is(2));
      assertThat(bcwe.getSuccesses().size(), is(0));
    }
  }
  @Test
  public void testPutAll_without_cache_writer() throws Exception {
    CacheConfigurationBuilder cacheConfigurationBuilder =
        CacheConfigurationBuilder.newCacheConfigurationBuilder(
            String.class, String.class, heap(100));
    CacheConfiguration<String, String> cacheConfiguration = cacheConfigurationBuilder.build();

    CacheManagerBuilder<CacheManager> managerBuilder = CacheManagerBuilder.newCacheManagerBuilder();
    CacheManager cacheManager = managerBuilder.withCache("myCache", cacheConfiguration).build(true);

    Cache<String, String> myCache = cacheManager.getCache("myCache", String.class, String.class);

    HashMap<String, String> stringStringHashMap = new HashMap<String, String>();
    for (int i = 0; i < 3; i++) {
      stringStringHashMap.put("key" + i, "value" + i);
    }

    // the call to putAll
    myCache.putAll(stringStringHashMap);

    for (int i = 0; i < 3; i++) {
      assertThat(myCache.get("key" + i), is("value" + i));
    }
  }