package org.infinispan.functional; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import java.io.Serializable; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.stream.Collectors; import org.infinispan.Cache; import org.infinispan.commons.api.functional.EntryView.ReadEntryView; import org.infinispan.commons.api.functional.EntryView.WriteEntryView; import org.infinispan.persistence.dummy.DummyInMemoryStore; import org.infinispan.persistence.manager.PersistenceManager; import org.testng.annotations.Test; /** * @author Radim Vansa <rvansa@redhat.com> && Krzysztof Sobolewski <Krzysztof.Sobolewski@atende.pl> */ @Test(groups = "functional", testName = "functional.FunctionalCachestoreTest") public class FunctionalCachestoreTest extends AbstractFunctionalOpTest { @Override public Object[] factory() { return new Object[] { new FunctionalCachestoreTest().persistence(true).passivation(false), new FunctionalCachestoreTest().persistence(true).passivation(true) }; } @Override protected String parameters() { return "[passivation=" + passivation + "]"; } @Test(dataProvider = "owningModeAndWriteMethod") public void testWriteLoad(boolean isSourceOwner, WriteMethod method) throws InterruptedException { Object key = getKey(isSourceOwner); List<Cache<Object, Object>> owners = caches(DIST).stream() .filter(cache -> cache.getAdvancedCache().getDistributionManager().getLocality(key).isLocal()) .collect(Collectors.toList()); method.action.eval(key, wo, rw, (Function<ReadEntryView<Object, String>, Void> & Serializable) view -> { assertFalse(view.find().isPresent()); return null; }, (BiConsumer<WriteEntryView<String>, Void> & Serializable) (view, nil) -> view.set("value"), getClass()); assertInvocations(2); caches(DIST).forEach(cache -> assertEquals(cache.get(key), "value", getAddress(cache).toString())); // Staggered gets could arrive after evict command and that would reload the entry into DC advanceGenerationsAndAwait(10, TimeUnit.SECONDS); caches(DIST).forEach(cache -> cache.evict(key)); caches(DIST).forEach(cache -> assertFalse(cache.getAdvancedCache().getDataContainer().containsKey(key), getAddress(cache).toString())); owners.forEach(cache -> { DummyInMemoryStore store = getStore(cache); assertTrue(store.contains(key), getAddress(cache).toString()); }); method.action.eval(key, wo, rw, (Function<ReadEntryView<Object, String>, Void> & Serializable) view -> { assertTrue(view.find().isPresent()); assertEquals(view.get(), "value"); return null; }, (BiConsumer<WriteEntryView<String>, Void> & Serializable) (view, nil) -> {}, getClass()); assertInvocations(4); } public DummyInMemoryStore getStore(Cache cache) { Set<DummyInMemoryStore> stores = cache.getAdvancedCache().getComponentRegistry().getComponent(PersistenceManager.class).getStores(DummyInMemoryStore.class); return stores.iterator().next(); } @Test(dataProvider = "writeMethods") public void testWriteLoadLocal(WriteMethod method) { Integer key = 1; method.action.eval(key, lwo, lrw, (Function<ReadEntryView<Integer, String>, Void> & Serializable) view -> { assertFalse(view.find().isPresent()); return null; }, (BiConsumer<WriteEntryView<String>, Void> & Serializable) (view, nil) -> view.set("value"), getClass()); assertInvocations(1); Cache<Integer, String> cache = cacheManagers.get(0).getCache(); assertEquals(cache.get(key), "value"); cache.evict(key); assertFalse(cache.getAdvancedCache().getDataContainer().containsKey(key)); DummyInMemoryStore store = getStore(cache); assertTrue(store.contains(key)); method.action.eval(key, lwo, lrw, (Function<ReadEntryView<Object, String>, Void> & Serializable) view -> { assertTrue(view.find().isPresent()); assertEquals(view.get(), "value"); return null; }, (BiConsumer<WriteEntryView<String>, Void> & Serializable) (view, nil) -> {}, getClass()); assertInvocations(2); } @Test(dataProvider = "owningModeAndReadMethod") public void testReadLoad(boolean isSourceOwner, ReadMethod method) { Object key = getKey(isSourceOwner); List<Cache<Object, Object>> owners = caches(DIST).stream() .filter(cache -> cache.getAdvancedCache().getDistributionManager().getLocality(key).isLocal()) .collect(Collectors.toList()); assertTrue((Boolean) method.action.eval(key, ro, (Function<ReadEntryView<Object, String>, Boolean> & Serializable) view -> { assertFalse(view.find().isPresent()); return true; })); // we can't add from read-only cache, so we put manually: cache(0, DIST).put(key, "value"); caches(DIST).forEach(cache -> assertEquals(cache.get(key), "value", getAddress(cache).toString())); caches(DIST).forEach(cache -> cache.evict(key)); caches(DIST).forEach(cache -> assertFalse(cache.getAdvancedCache().getDataContainer().containsKey(key), getAddress(cache).toString())); owners.forEach(cache -> { Set<DummyInMemoryStore> stores = cache.getAdvancedCache().getComponentRegistry().getComponent(PersistenceManager.class).getStores(DummyInMemoryStore.class); DummyInMemoryStore store = stores.iterator().next(); assertTrue(store.contains(key), getAddress(cache).toString()); }); assertEquals(method.action.eval(key, ro, (Function<ReadEntryView<Object, String>, Object> & Serializable) view -> { assertTrue(view.find().isPresent()); assertEquals(view.get(), "value"); return "OK"; }), "OK"); } }