@Test public void testBulkComputeStoreRemovesValueWhenFunctionReturnsNullMappings() throws Exception { Store.Configuration<Number, CharSequence> configuration = mockStoreConfig(); OnHeapStore<Number, CharSequence> store = new OnHeapStore<Number, CharSequence>(configuration, SystemTimeSource.INSTANCE, false); store.put(1, "one"); store.put(2, "two"); store.put(3, "three"); Map<Number, Store.ValueHolder<CharSequence>> result = store.bulkCompute( Arrays.asList(2, 1, 5), new Function< Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>>, Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>>>() { @Override public Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>> apply( Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>> entries) { Map<Number, CharSequence> newValues = new HashMap<Number, CharSequence>(); for (Map.Entry<? extends Number, ? extends CharSequence> entry : entries) { newValues.put(entry.getKey(), null); } return newValues.entrySet(); } }); assertThat(result.size(), is(3)); assertThat(store.get(1), is(nullValue())); assertThat(store.get(2), is(nullValue())); assertThat(store.get(3).value(), Matchers.<CharSequence>equalTo("three")); assertThat(store.get(5), is(nullValue())); }
@Test public void testPutAndGet() throws CacheAccessException { store.put(KEY, VALUE); Store.ValueHolder<Value> firstStoreValue = store.get(KEY); Store.ValueHolder<Value> secondStoreValue = store.get(KEY); compareValues(VALUE, firstStoreValue.value()); compareValues(VALUE, secondStoreValue.value()); compareReadValues(firstStoreValue.value(), secondStoreValue.value()); }
@Test public void testBulkComputeIfAbsentFunctionDoesNotGetPresentKeys() throws Exception { Store.Configuration<Number, CharSequence> configuration = mockStoreConfig(); OnHeapStore<Number, CharSequence> store = new OnHeapStore<Number, CharSequence>(configuration, SystemTimeSource.INSTANCE, false); store.put(1, "one"); store.put(2, "two"); store.put(3, "three"); Map<Number, Store.ValueHolder<CharSequence>> result = store.bulkComputeIfAbsent( Arrays.asList(1, 2, 3, 4, 5, 6), new Function< Iterable<? extends Number>, Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>>>() { @Override public Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>> apply( Iterable<? extends Number> keys) { Map<Number, CharSequence> result = new HashMap<Number, CharSequence>(); for (Number key : keys) { if (key.equals(1)) { fail(); } else if (key.equals(2)) { fail(); } else if (key.equals(3)) { fail(); } else { result.put(key, null); } } return result.entrySet(); } }); assertThat(result.size(), is(6)); assertThat(result.get(1).value(), Matchers.<CharSequence>equalTo("one")); assertThat(result.get(2).value(), Matchers.<CharSequence>equalTo("two")); assertThat(result.get(3).value(), Matchers.<CharSequence>equalTo("three")); assertThat(result.get(4), is(nullValue())); assertThat(result.get(5), is(nullValue())); assertThat(result.get(6), is(nullValue())); assertThat(store.get(1).value(), Matchers.<CharSequence>equalTo("one")); assertThat(store.get(2).value(), Matchers.<CharSequence>equalTo("two")); assertThat(store.get(3).value(), Matchers.<CharSequence>equalTo("three")); assertThat(store.get(4), is(nullValue())); assertThat(store.get(5), is(nullValue())); assertThat(store.get(6), is(nullValue())); }
@Test public void testBulkComputeIfAbsentDoNothingOnNullValues() throws Exception { Store.Configuration<Number, CharSequence> configuration = mockStoreConfig(); OnHeapStore<Number, CharSequence> store = new OnHeapStore<Number, CharSequence>(configuration, SystemTimeSource.INSTANCE, false); store.put(1, "one"); store.put(2, "two"); store.put(3, "three"); Map<Number, Store.ValueHolder<CharSequence>> result = store.bulkComputeIfAbsent( Arrays.asList(2, 1, 5), new Function< Iterable<? extends Number>, Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>>>() { @Override public Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>> apply( Iterable<? extends Number> numbers) { Map<Number, CharSequence> result = new HashMap<Number, CharSequence>(); for (Number key : numbers) { // 5 is a missing key, so it's the only key that is going passed to the function if (key.equals(5)) { result.put(key, null); } } Set<Number> numbersSet = new HashSet<Number>(); for (Number number : numbers) { numbersSet.add(number); } assertThat(numbersSet.size(), is(1)); assertThat(numbersSet.iterator().next(), Matchers.<Number>equalTo(5)); return result.entrySet(); } }); assertThat(result.size(), is(3)); assertThat(result.get(2).value(), Matchers.<CharSequence>equalTo("two")); assertThat(result.get(1).value(), Matchers.<CharSequence>equalTo("one")); assertThat(result.get(5), is(nullValue())); assertThat(store.get(1).value(), Matchers.<CharSequence>equalTo("one")); assertThat(store.get(2).value(), Matchers.<CharSequence>equalTo("two")); assertThat(store.get(3).value(), Matchers.<CharSequence>equalTo("three")); assertThat(store.get(5), is(nullValue())); }
@Test public void testValueUniqueObject() throws Exception { OnHeapStore<Serializable, Serializable> store = newStore(); String key = "key"; List<String> value = new ArrayList<String>(); value.add("value"); store.put(key, (Serializable) value); // mutate the value -- should not affect cache value.clear(); ValueHolder<Serializable> valueHolder = store.get(key); if (valueHolder.value() == value || !valueHolder.value().equals(Collections.singletonList("value"))) { throw new AssertionError(); } }
@Test public void testBulkComputeHappyPath() throws Exception { Store.Configuration<Number, CharSequence> configuration = mockStoreConfig(); OnHeapStore<Number, CharSequence> store = new OnHeapStore<Number, CharSequence>(configuration, SystemTimeSource.INSTANCE, false); store.put(1, "one"); Map<Number, Store.ValueHolder<CharSequence>> result = store.bulkCompute( Arrays.asList(1, 2), new Function< Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>>, Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>>>() { @Override public Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>> apply( Iterable<? extends Map.Entry<? extends Number, ? extends CharSequence>> entries) { Map<Number, CharSequence> newValues = new HashMap<Number, CharSequence>(); for (Map.Entry<? extends Number, ? extends CharSequence> entry : entries) { if (entry.getKey().intValue() == 1) { newValues.put(entry.getKey(), "un"); } else if (entry.getKey().intValue() == 2) { newValues.put(entry.getKey(), "deux"); } } return newValues.entrySet(); } }); assertThat(result.size(), is(2)); assertThat(result.get(1).value(), Matchers.<CharSequence>equalTo("un")); assertThat(result.get(2).value(), Matchers.<CharSequence>equalTo("deux")); assertThat(store.get(1).value(), Matchers.<CharSequence>equalTo("un")); assertThat(store.get(2).value(), Matchers.<CharSequence>equalTo("deux")); }
@Test public void testBulkComputeFunctionGetsValuesOfEntries() throws Exception { @SuppressWarnings("rawtypes") Store.Configuration config = mock(Store.Configuration.class); when(config.getExpiry()).thenReturn(Expirations.noExpiration()); when(config.getKeyType()).thenReturn(Number.class); when(config.getValueType()).thenReturn(Number.class); Store.Configuration<Number, Number> configuration = config; OnHeapStore<Number, Number> store = new OnHeapStore<Number, Number>(configuration, SystemTimeSource.INSTANCE, false); store.put(1, 2); store.put(2, 3); store.put(3, 4); Map<Number, Store.ValueHolder<Number>> result = store.bulkCompute( Arrays.asList(1, 2, 3, 4, 5, 6), new Function< Iterable<? extends Map.Entry<? extends Number, ? extends Number>>, Iterable<? extends Map.Entry<? extends Number, ? extends Number>>>() { @Override public Iterable<? extends Map.Entry<? extends Number, ? extends Number>> apply( Iterable<? extends Map.Entry<? extends Number, ? extends Number>> entries) { Map<Number, Number> newValues = new HashMap<Number, Number>(); for (Map.Entry<? extends Number, ? extends Number> entry : entries) { final Number currentValue = entry.getValue(); if (currentValue == null) { if (entry.getKey().equals(4)) { newValues.put(entry.getKey(), null); } else { newValues.put(entry.getKey(), 0); } } else { newValues.put(entry.getKey(), currentValue.intValue() * 2); } } return newValues.entrySet(); } }); ConcurrentMap<Number, Number> check = new ConcurrentHashMap<Number, Number>(); check.put(1, 4); check.put(2, 6); check.put(3, 8); check.put(4, 0); check.put(5, 0); check.put(6, 0); assertThat(result.get(1).value(), Matchers.<Number>is(check.get(1))); assertThat(result.get(2).value(), Matchers.<Number>is(check.get(2))); assertThat(result.get(3).value(), Matchers.<Number>is(check.get(3))); assertThat(result.get(4), nullValue()); assertThat(result.get(5).value(), Matchers.<Number>is(check.get(5))); assertThat(result.get(6).value(), Matchers.<Number>is(check.get(6))); for (Number key : check.keySet()) { final Store.ValueHolder<Number> holder = store.get(key); if (holder != null) { check.remove(key, holder.value()); } } assertThat(check.size(), is(1)); assertThat(check.containsKey(4), is(true)); }