/*
* JBoss, Home of Professional Open Source
* Copyright 2009 Red Hat Inc. and/or its affiliates and other
* contributors as indicated by the @author tags. All rights reserved.
* See the copyright.txt in the distribution for a full listing of
* individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.infinispan.query.blackbox;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.PrefixFilter;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.hibernate.search.engine.spi.EntityIndexBinder;
import org.hibernate.search.engine.spi.SearchFactoryImplementor;
import org.hibernate.search.spi.SearchFactoryIntegrator;
import org.infinispan.Cache;
import org.infinispan.config.FluentConfiguration;
import org.infinispan.factories.ComponentRegistry;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.query.CacheQuery;
import org.infinispan.query.Search;
import org.infinispan.query.QueryIterator;
import org.infinispan.query.test.AnotherGrassEater;
import org.infinispan.query.test.Person;
import org.infinispan.test.SingleCacheManagerTest;
import org.infinispan.test.fwk.TestCacheManagerFactory;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import junit.framework.Assert;
import org.testng.annotations.Test;
import static java.util.Arrays.asList;
import static org.infinispan.config.Configuration.CacheMode.LOCAL;
import static org.infinispan.query.helper.TestQueryHelperFactory.*;
@Test(groups = "functional", testName = "query.blackbox.LocalCacheTest")
public class LocalCacheTest extends SingleCacheManagerTest {
protected Person person1;
protected Person person2;
protected Person person3;
protected Person person4;
protected Person person5;
protected Person person6;
protected AnotherGrassEater anotherGrassEater;
protected QueryParser queryParser;
protected String key1 = "Navin";
protected String key2 = "BigGoat";
protected String key3 = "MiniGoat";
protected String anotherGrassEaterKey = "anotherGrassEaterKey";
public LocalCacheTest() {
cleanup = CleanupPhase.AFTER_METHOD;
}
public void testSimple() throws ParseException {
loadTestingData();
CacheQuery cacheQuery = createCacheQuery(cache, "blurb", "playing" );
List<Object> found = cacheQuery.list();
int elems = found.size();
assert elems == 1 : "Expected 1 but was " + elems;
Object val = found.get(0);
assert val.equals(person1) : "Expected " + person1 + " but was " + val;
}
public void testEagerIterator() throws ParseException {
loadTestingData();
CacheQuery cacheQuery = createCacheQuery(cache, "blurb", "playing" );
QueryIterator found = cacheQuery.iterator();
assert found.isFirst();
assert found.isLast();
}
public void testMultipleResults() throws ParseException {
loadTestingData();
queryParser = createQueryParser("name");
Query luceneQuery = queryParser.parse("goat");
CacheQuery cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
List<Object> found = cacheQuery.list();
assert found.size() == 2;
assert found.get(0) == person2;
assert found.get(1) == person3;
}
public void testModified() throws ParseException {
loadTestingData();
queryParser = createQueryParser("blurb");
Query luceneQuery = queryParser.parse("playing");
CacheQuery cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
List<Object> found = cacheQuery.list();
assert found.size() == 1;
assert found.get(0).equals(person1);
person1.setBlurb("Likes pizza");
cache.put(key1, person1);
queryParser = createQueryParser("blurb");
luceneQuery = queryParser.parse("pizza");
cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
found = cacheQuery.list();
assert found.size() == 1;
assert found.get(0).equals(person1);
}
public void testAdded() throws ParseException {
assertIndexingKnows(cache);
loadTestingData();
assertIndexingKnows(cache, Person.class, AnotherGrassEater.class);
queryParser = createQueryParser("name");
Query luceneQuery = queryParser.parse("Goat");
CacheQuery cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
List<Object> found = cacheQuery.list();
assert found.size() == 2 : "Size of list should be 2";
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");
cache.put("mighty", person4);
luceneQuery = queryParser.parse("Goat");
cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
found = cacheQuery.list();
assert found.size() == 3 : "Size of list should be 3";
assert found.contains(person2);
assert found.contains(person3);
assert found.contains(person4) : "This should now contain object person4";
}
public void testRemoved() throws ParseException {
loadTestingData();
queryParser = createQueryParser("name");
Query luceneQuery = queryParser.parse("Goat");
CacheQuery cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
List<Object> found = cacheQuery.list();
assert found.size() == 2;
assert found.contains(person2);
assert found.contains(person3) : "This should still contain object person3";
cache.remove(key3);
luceneQuery = queryParser.parse("Goat");
cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
found = cacheQuery.list();
assert found.size() == 1;
assert found.contains(person2);
assert !found.contains(person3) : "The search should not return person3";
}
public void testUpdated() throws ParseException {
loadTestingData();
queryParser = createQueryParser("name");
Query luceneQuery = queryParser.parse("Goat");
CacheQuery cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
List<Object> found = cacheQuery.list();
assert found.size() == 2 : "Size of list should be 2";
assert found.contains(person2) : "The search should have person2";
cache.put(key2, person1);
luceneQuery = queryParser.parse("Goat");
cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
found = cacheQuery.list();
assert found.size() == 1 : "Size of list should be 1";
assert !found.contains(person2) : "Person 2 should not be found now";
assert !found.contains(person1) : "Person 1 should not be found because it does not meet the search criteria";
}
public void testSetSort() throws ParseException {
loadTestingData();
person2.setAge(35);
person3.setAge(12);
Sort sort = new Sort( new SortField("age", SortField.STRING));
queryParser = createQueryParser("name");
Query luceneQuery = queryParser.parse("Goat");
CacheQuery cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
List<Object> found = cacheQuery.list();
assert found.size() == 2;
cacheQuery.sort(sort);
found = cacheQuery.list();
assert found.size() == 2;
assert found.get(0).equals(person2);
assert found.get(1).equals(person3);
}
public void testSetFilter() throws ParseException {
loadTestingData();
queryParser = createQueryParser("name");
Query luceneQuery = queryParser.parse("goat");
CacheQuery cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
List<Object> found = cacheQuery.list();
assert found.size() == 2;
Filter filter = new PrefixFilter(new Term("blurb", "cheese"));
cacheQuery.filter(filter);
found = cacheQuery.list();
assert found.size() == 1;
}
public void testLazyIterator() throws ParseException {
loadTestingData();
queryParser = createQueryParser("blurb");
Query luceneQuery = queryParser.parse("playing");
CacheQuery cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
QueryIterator found = cacheQuery.lazyIterator();
assert found.isFirst();
assert found.isLast();
}
public void testGetResultSize() throws ParseException {
loadTestingData();
queryParser = createQueryParser("blurb");
Query luceneQuery = queryParser.parse("playing");
CacheQuery cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
assert cacheQuery.getResultSize() == 1;
}
public void testClear() {
loadTestingData();
// Create a term that will return me everyone called Navin.
Term navin = new Term("name", "navin");
// Create a term that I know will return me everything with name goat.
Term goat = new Term ("name", "goat");
Query[] queries = new Query[2];
queries[0] = new TermQuery(goat);
queries[1] = new TermQuery(navin);
Query luceneQuery = queries[0].combine(queries);
CacheQuery cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
// We know that we've got all 3 hits.
assert cacheQuery.getResultSize() == 3 : "Expected 3, got " + cacheQuery.getResultSize();
cache.clear();
cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
assert cacheQuery.getResultSize() == 0;
}
public void testTypeFiltering() throws ParseException {
loadTestingData();
queryParser = createQueryParser("blurb");
Query luceneQuery = queryParser.parse("grass");
CacheQuery cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery);
List<Object> found = cacheQuery.list();
assert found.size() == 2;
assert found.containsAll(asList(person2, anotherGrassEater));
queryParser = createQueryParser("blurb");
luceneQuery = queryParser.parse("grass");
cacheQuery = Search.getSearchManager(cache).getQuery(luceneQuery, AnotherGrassEater.class);
found = cacheQuery.list();
assert found.size() == 1;
assert found.get(0).equals(anotherGrassEater);
}
protected EmbeddedCacheManager createCacheManager() throws Exception {
FluentConfiguration cfg = getDefaultClusteredConfig(LOCAL, true).fluent();
cfg
.indexing()
.indexLocalOnly(false)
.addProperty("hibernate.search.default.directory_provider", "ram")
.addProperty("hibernate.search.lucene_version", "LUCENE_CURRENT");
enhanceConfig(cfg);
return TestCacheManagerFactory.createCacheManager(cfg.build());
}
public void testEntityDiscovery() {
assertIndexingKnows(cache);
Person p = new Person();
p.setName("Lucene developer");
p.setAge(30);
p.setBlurb("works best on weekends");
cache.put(p.getName(), p);
assertIndexingKnows(cache, Person.class);
}
/**
* Verifies if the indexing interceptor is aware of a specific list of types.
* @param cache
* @param types vararg listing the types the indexing engine should know
*/
private void assertIndexingKnows(Cache<Object, Object> cache, Class... types) {
ComponentRegistry cr = cache.getAdvancedCache().getComponentRegistry();
SearchFactoryImplementor searchFactoryIntegrator = (SearchFactoryImplementor) cr.getComponent(SearchFactoryIntegrator.class);
Assert.assertNotNull(searchFactoryIntegrator);
Map<Class<?>, EntityIndexBinder> indexBindingForEntity = searchFactoryIntegrator.getIndexBindingForEntity();
Assert.assertNotNull(indexBindingForEntity);
Set<Class<?>> keySet = indexBindingForEntity.keySet();
Assert.assertEquals(types.length, keySet.size());
Assert.assertTrue(keySet.containsAll(Arrays.asList(types)));
}
protected void loadTestingData() {
person1 = new Person();
person1.setName("Navin Surtani");
person1.setBlurb("Likes playing WoW");
person2 = new Person();
person2.setName("Big Goat");
person2.setBlurb("Eats grass");
person3 = new Person();
person3.setName("Mini Goat");
person3.setBlurb("Eats cheese");
person5 = new Person();
person5.setName("Smelly Cat");
person5.setBlurb("Eats fish");
anotherGrassEater = new AnotherGrassEater("Another grass-eater", "Eats grass");
cache.put(key1, person1);
// person2 is verified as number of matches in multiple tests,
// so verify duplicate insertion doesn't affect result counts:
cache.put(key2, person2);
cache.put(key2, person2);
cache.put(key2, person2);
cache.put(key3, person3);
cache.put(anotherGrassEaterKey, anotherGrassEater);
}
protected void enhanceConfig(FluentConfiguration c) {
// no op, meant to be overridden
}
}