package org.infinispan.query.blackbox; import static org.infinispan.query.helper.TestQueryHelperFactory.createCacheQuery; import static org.infinispan.query.helper.TestQueryHelperFactory.createQueryParser; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Future; import javax.transaction.TransactionManager; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; import org.hibernate.search.filter.FullTextFilter; import org.hibernate.search.query.dsl.QueryBuilder; import org.infinispan.Cache; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.configuration.cache.Index; import org.infinispan.configuration.cache.StorageType; import org.infinispan.query.CacheQuery; import org.infinispan.query.FetchOptions; import org.infinispan.query.ResultIterator; import org.infinispan.query.Search; import org.infinispan.query.SearchManager; import org.infinispan.query.backend.QueryInterceptor; import org.infinispan.query.helper.StaticTestingErrorHandler; import org.infinispan.query.spi.SearchManagerImplementor; import org.infinispan.query.test.CustomKey3; import org.infinispan.query.test.CustomKey3Transformer; import org.infinispan.query.test.Person; import org.infinispan.test.MultipleCacheManagersTest; import org.infinispan.test.TestingUtil; import org.testng.AssertJUnit; import org.testng.annotations.Test; /** * @author Navin Surtani * @author Sanne Grinovero */ @Test(groups = {"functional", "smoke"}, testName = "query.blackbox.ClusteredCacheTest") public class ClusteredCacheTest extends MultipleCacheManagersTest { protected Cache cache1; protected Cache cache2; Person person1; Person person2; Person person3; Person person4; QueryParser queryParser; Query luceneQuery; CacheQuery<Person> cacheQuery; final String key1 = "Navin"; final String key2 = "BigGoat"; final String key3 = "MiniGoat"; public ClusteredCacheTest() { cleanup = CleanupPhase.AFTER_METHOD; } private StorageType storageType; public Object[] factory() { return new Object[] { new ClusteredCacheTest().storageType(StorageType.OFF_HEAP), new ClusteredCacheTest().storageType(StorageType.BINARY), new ClusteredCacheTest().storageType(StorageType.OBJECT), }; } ClusteredCacheTest storageType(StorageType storageType) { this.storageType = storageType; return this; } protected void enhanceConfig(ConfigurationBuilder cacheCfg) { // meant to be overridden } @Override protected void createCacheManagers() throws Throwable { ConfigurationBuilder cacheCfg = getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, transactionsEnabled()); cacheCfg.indexing() .index(Index.ALL) .addIndexedEntity(Person.class) .addProperty("default.directory_provider", "ram") .addProperty("error_handler", "org.infinispan.query.helper.StaticTestingErrorHandler") .addProperty("lucene_version", "LUCENE_CURRENT"); cacheCfg.memory() .storageType(storageType); enhanceConfig(cacheCfg); List<Cache<String, Person>> caches = createClusteredCaches(2, cacheCfg); cache1 = caches.get(0); cache2 = caches.get(1); } private void prepareTestedObjects() { person1 = new Person(); person1.setName("Navin Surtani"); person1.setBlurb("Likes playing WoW"); person1.setAge(30); person2 = new Person(); person2.setName("BigGoat"); person2.setBlurb("Eats grass"); person2.setAge(22); person3 = new Person(); person3.setName("MiniGoat"); person3.setBlurb("Eats cheese"); person3.setAge(15); } protected void prepareTestData() throws Exception { prepareTestedObjects(); TransactionManager transactionManager = cache1.getAdvancedCache().getTransactionManager(); // Put the 3 created objects in the cache1. if (transactionsEnabled()) transactionManager.begin(); cache1.put(key1, person1); cache1.put(key2, person2); cache1.put(key3, person3); if (transactionsEnabled()) transactionManager.commit(); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } protected boolean transactionsEnabled() { return false; } public void testSimple() throws Exception { prepareTestData(); cacheQuery = createCacheQuery(cache2, "blurb", "playing"); List<Person> found = cacheQuery.list(); assert found.size() == 1; if (found.get(0) == null) { log.warn("found.get(0) is null"); Person p1 = (Person) cache2.get(key1); if (p1 == null) { log.warn("Person p1 is null in sc2 and cannot actually see the data of person1 in sc1"); } else { log.trace("p1 name is " + p1.getName()); } } assert found.get(0).equals(person1); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } private void assertQueryInterceptorPresent(Cache<?, ?> c) { QueryInterceptor i = TestingUtil.findInterceptor(c, QueryInterceptor.class); assert i != null : "Expected to find a QueryInterceptor, only found " + c.getAdvancedCache().getAsyncInterceptorChain().getInterceptors(); } public void testModified() throws Exception { prepareTestData(); assertQueryInterceptorPresent(cache2); queryParser = createQueryParser("blurb"); luceneQuery = queryParser.parse("playing"); cacheQuery = Search.getSearchManager(cache2).getQuery(luceneQuery); List<Person> found = cacheQuery.list(); assert found.size() == 1 : "Expected list of size 1, was of size " + found.size(); assert found.get(0).equals(person1); person1.setBlurb("Likes pizza"); cache1.put("Navin", person1); queryParser = createQueryParser("blurb"); luceneQuery = queryParser.parse("pizza"); cacheQuery = Search.getSearchManager(cache2).getQuery(luceneQuery); found = cacheQuery.list(); assert found.size() == 1; assert found.get(0).equals(person1); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testAdded() throws Exception { prepareTestData(); queryParser = createQueryParser("blurb"); luceneQuery = queryParser.parse("eats"); cacheQuery = Search.getSearchManager(cache2).getQuery(luceneQuery); List<Person> found = cacheQuery.list(); AssertJUnit.assertEquals(2, found.size()); assert found.contains(person2); assert found.contains(person3); assert !found.contains(person4) : "This should not contain object person4"; person4 = new Person(); person4.setName("Mighty Goat"); person4.setBlurb("Also eats grass"); cache1.put("mighty", person4); luceneQuery = queryParser.parse("eats"); cacheQuery = Search.getSearchManager(cache2).getQuery(luceneQuery); found = cacheQuery.list(); AssertJUnit.assertEquals(3, found.size()); assert found.contains(person2); assert found.contains(person3); assert found.contains(person4) : "This should now contain object person4"; StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testRemoved() throws Exception { prepareTestData(); queryParser = createQueryParser("blurb"); luceneQuery = queryParser.parse("eats"); cacheQuery = Search.getSearchManager(cache2).getQuery(luceneQuery); List<Person> found = cacheQuery.list(); assert found.size() == 2; assert found.contains(person2); assert found.contains(person3) : "This should still contain object person3"; cache1.remove(key3); found = cacheQuery.list(); assert found.size() == 1; assert found.contains(person2); assert !found.contains(person3) : "This should not contain object person3 anymore"; StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testGetResultSize() throws Exception { prepareTestData(); queryParser = createQueryParser("blurb"); luceneQuery = queryParser.parse("playing"); cacheQuery = Search.getSearchManager(cache2).getQuery(luceneQuery); List<Person> found = cacheQuery.list(); AssertJUnit.assertEquals(1, found.size()); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testPutMap() throws Exception { prepareTestData(); SearchManager searchManager = Search.getSearchManager(cache2); QueryBuilder queryBuilder = searchManager .buildQueryBuilderForClass(Person.class) .get(); Query allQuery = queryBuilder.all().createQuery(); assert searchManager.getQuery(allQuery, Person.class).list().size() == 3; Map<String,Person> allWrites = new HashMap<>(); allWrites.put(key1, person1); allWrites.put(key2, person2); allWrites.put(key3, person3); cache2.putAll(allWrites); List<Person> found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(3, found.size()); cache2.putAll(allWrites); found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(3, found.size()); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testPutMapAsync() throws Exception { prepareTestData(); SearchManager searchManager = Search.getSearchManager(cache2); QueryBuilder queryBuilder = searchManager .buildQueryBuilderForClass(Person.class) .get(); Query allQuery = queryBuilder.all().createQuery(); assert searchManager.getQuery(allQuery, Person.class).list().size() == 3; person4 = new Person(); person4.setName("New Goat"); person4.setBlurb("Also eats grass"); Map<String,Person> allWrites = new HashMap<>(); allWrites.put(key1, person1); allWrites.put(key2, person2); allWrites.put(key3, person3); allWrites.put("newGoat", person4); Future futureTask = cache2.putAllAsync(allWrites); futureTask.get(); assert futureTask.isDone(); List<Person> found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(4, found.size()); assert found.contains(person4); futureTask = cache1.putAllAsync(allWrites); futureTask.get(); assert futureTask.isDone(); found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(4, found.size()); assert found.contains(person4); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testPutForExternalRead() throws Exception { prepareTestData(); SearchManager searchManager = Search.getSearchManager(cache2); QueryBuilder queryBuilder = searchManager .buildQueryBuilderForClass(Person.class) .get(); Query allQuery = queryBuilder.all().createQuery(); assert searchManager.getQuery(allQuery, Person.class).list().size() == 3; person4 = new Person(); person4.setName("New Goat"); person4.setBlurb("Also eats grass"); cache2.putForExternalRead("newGoat", person4); eventually(() -> cache2.get("newGoat") != null); List<Person> found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(4, found.size()); assert found.contains(person4); Person person5 = new Person(); person5.setName("Abnormal Goat"); person5.setBlurb("Plays with grass."); cache2.putForExternalRead("newGoat", person5); found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(4, found.size()); assert !found.contains(person5); assert found.contains(person4); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testPutIfAbsent() throws Exception { prepareTestData(); SearchManager searchManager = Search.getSearchManager(cache2); QueryBuilder queryBuilder = searchManager .buildQueryBuilderForClass(Person.class) .get(); Query allQuery = queryBuilder.all().createQuery(); assert searchManager.getQuery(allQuery, Person.class).list().size() == 3; person4 = new Person(); person4.setName("New Goat"); person4.setBlurb("Also eats grass"); cache2.putIfAbsent("newGoat", person4); List<Person> found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(4, found.size()); assert found.contains(person4); Person person5 = new Person(); person5.setName("Abnormal Goat"); person5.setBlurb("Plays with grass."); cache2.putIfAbsent("newGoat", person5); found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(4, found.size()); assert !found.contains(person5); assert found.contains(person4); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testPutIfAbsentAsync() throws Exception { prepareTestData(); SearchManager searchManager = Search.getSearchManager(cache2); QueryBuilder queryBuilder = searchManager .buildQueryBuilderForClass(Person.class) .get(); Query allQuery = queryBuilder.all().createQuery(); assert searchManager.getQuery(allQuery, Person.class).list().size() == 3; person4 = new Person(); person4.setName("New Goat"); person4.setBlurb("Also eats grass"); Future futureTask = cache2.putIfAbsentAsync("newGoat", person4); futureTask.get(); assert futureTask.isDone(); List<Person> found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(4, found.size()); assert found.contains(person4); Person person5 = new Person(); person5.setName("Abnormal Goat"); person5.setBlurb("Plays with grass."); futureTask = cache2.putIfAbsentAsync("newGoat", person5); futureTask.get(); assert futureTask.isDone(); found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(4, found.size()); assert !found.contains(person5); assert found.contains(person4); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testPutAsync() throws Exception { prepareTestData(); SearchManager searchManager = Search.getSearchManager(cache2); QueryBuilder queryBuilder = searchManager .buildQueryBuilderForClass(Person.class) .get(); Query allQuery = queryBuilder.all().createQuery(); assert searchManager.getQuery(allQuery, Person.class).list().size() == 3; person4 = new Person(); person4.setName("New Goat"); person4.setBlurb("Also eats grass"); Future f = cache2.putAsync("newGoat", person4); f.get(); assert f.isDone(); List<Person> found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(4, found.size()); assert found.contains(person4); Person person5 = new Person(); person5.setName("Abnormal Goat"); person5.setBlurb("Plays with grass."); f = cache2.putAsync("newGoat", person5); f.get(); assert f.isDone(); found = searchManager.<Person>getQuery(allQuery, Person.class).list(); AssertJUnit.assertEquals(4, found.size()); assert !found.contains(person4); assert found.contains(person5); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testClear() throws Exception { prepareTestData(); queryParser = createQueryParser("blurb"); BooleanQuery luceneQuery = new BooleanQuery.Builder() .add(queryParser.parse("eats"), Occur.SHOULD) .add(queryParser.parse("playing"), Occur.SHOULD) .build(); CacheQuery<?> cacheQuery = Search.getSearchManager(cache1).getQuery(luceneQuery); AssertJUnit.assertEquals(3, cacheQuery.getResultSize()); cache2.clear(); AssertJUnit.assertEquals(3, cacheQuery.getResultSize()); cacheQuery = Search.getSearchManager(cache1).getQuery(luceneQuery); AssertJUnit.assertEquals(0, cacheQuery.getResultSize()); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testFullTextFilterOnOff() throws Exception { prepareTestData(); queryParser = createQueryParser("blurb"); Query luceneQuery = queryParser.parse("eats"); CacheQuery<Person> query = Search.getSearchManager(cache1).getQuery(luceneQuery); FullTextFilter filter = query.enableFullTextFilter("personFilter"); filter.setParameter("blurbText", "cheese"); AssertJUnit.assertEquals(1, query.getResultSize()); List<Person> result = query.list(); Person person = result.get(0); AssertJUnit.assertEquals("MiniGoat", person.getName()); AssertJUnit.assertEquals("Eats cheese", person.getBlurb()); //Disabling the fullTextFilter. query.disableFullTextFilter("personFilter"); AssertJUnit.assertEquals(2, query.getResultSize()); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testCombinationOfFilters() throws Exception { prepareTestData(); person4 = new Person(); person4.setName("ExtraGoat"); person4.setBlurb("Eats grass and is retired"); person4.setAge(70); cache1.put("ExtraGoat", person4); queryParser = createQueryParser("blurb"); Query luceneQuery = queryParser.parse("eats"); CacheQuery<Person> query = Search.getSearchManager(cache1).getQuery(luceneQuery); FullTextFilter filter = query.enableFullTextFilter("personFilter"); filter.setParameter("blurbText", "grass"); AssertJUnit.assertEquals(2, query.getResultSize()); FullTextFilter ageFilter = query.enableFullTextFilter("personAgeFilter"); ageFilter.setParameter("age", 70); AssertJUnit.assertEquals(1, query.getResultSize()); List<Person> result = query.list(); Person person = result.get(0); AssertJUnit.assertEquals("ExtraGoat", person.getName()); AssertJUnit.assertEquals(70, person.getAge()); //Disabling the fullTextFilter. query.disableFullTextFilter("personFilter"); query.disableFullTextFilter("personAgeFilter"); AssertJUnit.assertEquals(3, query.getResultSize()); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } public void testSearchKeyTransformer() throws Exception { SearchManagerImplementor manager = (SearchManagerImplementor) Search.getSearchManager(cache1); SearchManagerImplementor manager1 = (SearchManagerImplementor) Search.getSearchManager(cache2); manager.registerKeyTransformer(CustomKey3.class, CustomKey3Transformer.class); manager1.registerKeyTransformer(CustomKey3.class, CustomKey3Transformer.class); prepareTestedObjects(); TransactionManager transactionManager = cache1.getAdvancedCache().getTransactionManager(); CustomKey3 customeKey1 = new CustomKey3(key1); CustomKey3 customeKey2 = new CustomKey3(key2); CustomKey3 customeKey3 = new CustomKey3(key3); // Put the 3 created objects in the cache1. if (transactionsEnabled()) transactionManager.begin(); cache1.put(customeKey1, person1); cache1.put(customeKey2, person2); cache1.put(customeKey3, person3); if (transactionsEnabled()) transactionManager.commit(); queryParser = createQueryParser("blurb"); Query luceneQuery = queryParser.parse("Eats"); CacheQuery<Person> cacheQuery = manager.getQuery(luceneQuery); int counter = 0; try (ResultIterator<Person> found = cacheQuery.iterator(new FetchOptions().fetchMode(FetchOptions.FetchMode.LAZY))) { while (found.hasNext()) { found.next(); counter++; } } AssertJUnit.assertEquals(2, counter); StaticTestingErrorHandler.assertAllGood(cache1, cache2); } }