/*
* Copyright (c) 2009-2010 Lockheed Martin Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eurekastreams.commons.search;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Query;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.FullTextQuery;
import org.hibernate.transform.ResultTransformer;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Test;
/**
* Test fixture for ProjectionSearchRequestBuilder.
*/
public class ProjectionSearchRequestBuilderTest
{
/**
* Context for mocking.
*/
private final JUnit4Mockery context = new JUnit4Mockery()
{
{
setImposteriser(ClassImposteriser.INSTANCE);
}
};
/**
* Test the escape() method.
*/
@Test
public void testEscape()
{
ProjectionSearchRequestBuilder sut = new ProjectionSearchRequestBuilder();
assertEquals("Hey now!", sut.escape("Hey now!"));
assertEquals("\\\\Hey \\:no\\^w\\|what's \\&up?", sut.escape("\\Hey :no^w|what's &up?"));
}
/**
* Test the paging method, setPaging().
*/
@Test
public void testSetPaging()
{
ProjectionSearchRequestBuilder sut = new ProjectionSearchRequestBuilder();
final FullTextQuery query = context.mock(FullTextQuery.class);
context.checking(new Expectations()
{
{
one(query).setFirstResult(3);
one(query).setMaxResults(7);
}
});
// invoke sut
sut.setPaging(query, 3, 9);
// all expectations met?
context.assertIsSatisfied();
}
/**
* Test the containsAdvancedSearchCharacters() method.
*/
@Test
public void testContainsAdvancedSearchCharacters()
{
ProjectionSearchRequestBuilder sut = new ProjectionSearchRequestBuilder();
assertTrue(sut.containsAdvancedSearchCharacters("(some text)"));
assertTrue(sut.containsAdvancedSearchCharacters("(some text"));
assertTrue(sut.containsAdvancedSearchCharacters("some text)"));
assertTrue(sut.containsAdvancedSearchCharacters("+some text"));
assertTrue(sut.containsAdvancedSearchCharacters("some-text"));
assertTrue(sut.containsAdvancedSearchCharacters("some +text"));
assertTrue(sut.containsAdvancedSearchCharacters("some text?"));
assertTrue(sut.containsAdvancedSearchCharacters("some text*"));
assertTrue(sut.containsAdvancedSearchCharacters("some \"text\""));
assertFalse(sut.containsAdvancedSearchCharacters("some text"));
assertFalse(sut.containsAdvancedSearchCharacters("hey now!"));
assertFalse(sut.containsAdvancedSearchCharacters("whoa there, buddy!"));
}
/**
* Test the escapeAllButWildcardCharacters() method.
*/
@Test
public void testEscapeAllButWildcardCharacters()
{
ProjectionSearchRequestBuilder sut = new ProjectionSearchRequestBuilder();
assertEquals("foo bar", sut.escapeAllButWildcardCharacters("foo bar"));
assertEquals("\\(foo bar\\)", sut.escapeAllButWildcardCharacters("(foo bar)"));
assertEquals("\\\\foo bar", sut.escapeAllButWildcardCharacters("\\foo bar"));
assertEquals("foo\\:bar", sut.escapeAllButWildcardCharacters("foo:bar"));
assertEquals("foo\\^bar", sut.escapeAllButWildcardCharacters("foo^bar"));
assertEquals("foo\\|bar", sut.escapeAllButWildcardCharacters("foo|bar"));
assertEquals("foo\\&bar", sut.escapeAllButWildcardCharacters("foo&bar"));
assertEquals("\\\"foo bar\\\"", sut.escapeAllButWildcardCharacters("\"foo bar\""));
assertEquals("foo\\+bar", sut.escapeAllButWildcardCharacters("foo+bar"));
assertEquals("foo\\-bar", sut.escapeAllButWildcardCharacters("foo-bar"));
assertEquals("\\!foo bar", sut.escapeAllButWildcardCharacters("!foo bar"));
// test valid wildcards
assertEquals("he?lo there", sut.escapeAllButWildcardCharacters("he?lo there"));
assertEquals("hello* there*", sut.escapeAllButWildcardCharacters("hello* there*"));
assertEquals("he**o th??e", sut.escapeAllButWildcardCharacters("he**o th??e"));
// test bare wildcards
assertEquals("hi* hi", sut.escapeAllButWildcardCharacters("hi* * hi"));
assertEquals("hi?* hi", sut.escapeAllButWildcardCharacters("hi?* ? hi"));
assertEquals(" asd hi", sut.escapeAllButWildcardCharacters("* asd hi"));
// test words composed of only wildcards
assertEquals(" hi hi", sut.escapeAllButWildcardCharacters("*** hi *** hi"));
assertEquals("", sut.escapeAllButWildcardCharacters("*"));
assertEquals("", sut.escapeAllButWildcardCharacters("*?*?*?*"));
assertEquals("hello there", sut.escapeAllButWildcardCharacters("*hello there"));
assertEquals("hello there", sut.escapeAllButWildcardCharacters("****hello there"));
assertEquals("hello there", sut.escapeAllButWildcardCharacters("?hello there"));
assertEquals(" hello there", sut.escapeAllButWildcardCharacters(" ?hello there"));
}
/**
* Test the buildFieldList() method.
*/
@Test
public void testBuildFieldList()
{
ProjectionSearchRequestBuilder sut = new ProjectionSearchRequestBuilder();
List<String> fields = sut.buildFieldList();
// make sure the default fields are populated, even if you don't specify any others
assertEquals(2, fields.size());
assertTrue(fields.contains(FullTextQuery.ID));
assertTrue(fields.contains(FullTextQuery.OBJECT_CLASS));
ArrayList<String> entityFields = new ArrayList<String>();
entityFields.add("foo");
entityFields.add("bar");
// test without the search score or managed entity
sut.setResultFields(entityFields);
fields = sut.buildFieldList();
assertEquals(4, fields.size());
assertTrue(fields.contains("foo"));
assertTrue(fields.contains("bar"));
assertTrue(fields.contains(FullTextQuery.ID));
assertTrue(fields.contains(FullTextQuery.OBJECT_CLASS));
}
/**
* Test the prepareQuery() method.
*
* This unit test won't really help anyone - it's pretty much white box.
*
* @throws ParseException
* on error
*/
@Test(expected = RuntimeException.class)
public void testPrepareQueryWithParseError() throws ParseException
{
ProjectionSearchRequestBuilderTestHelper sutSubclass = new ProjectionSearchRequestBuilderTestHelper();
final QueryParser queryParser = context.mock(QueryParser.class, "mockedQueryParser");
final String searchText = "foo now hey bar";
context.checking(new Expectations()
{
{
one(queryParser).parse(searchText);
will(throwException(new ParseException()));
}
});
// invoke sut
sutSubclass.prepareQuery(queryParser, searchText);
// all expectations met?
context.assertIsSatisfied();
}
/**
* Test the prepareQuery() method.
*
* This unit test won't really help anyone - it's pretty much white box.
*
* @throws ParseException
* when sad
*/
@Test
public void testPrepareQueryWithSuccess() throws ParseException
{
ProjectionSearchRequestBuilderTestHelper sutSubclass = new ProjectionSearchRequestBuilderTestHelper();
final String searchText = "foo now hey bar";
final Class< ? >[] resultTypes = { Integer.class };
final FullTextEntityManager ftem = context.mock(FullTextEntityManager.class, "mockedFtem");
final QueryParser queryParser = context.mock(QueryParser.class, "mockedQueryParser");
final Query luceneQuery = context.mock(Query.class, "mockedQuery");
final org.hibernate.search.jpa.FullTextQuery expectedReturnValue = context.mock(
org.hibernate.search.jpa.FullTextQuery.class, "mockedFullTextQuery");
final ResultTransformer resultTransformer = context.mock(ResultTransformer.class, "mockedResultTransformer");
ArrayList<String> entityFields = new ArrayList<String>();
entityFields.add("foo");
entityFields.add("bar");
context.checking(new Expectations()
{
{
one(queryParser).parse(searchText);
will(returnValue(luceneQuery));
one(ftem).createFullTextQuery(luceneQuery, resultTypes);
will(returnValue(expectedReturnValue));
one(expectedReturnValue).setProjection(with(any(String[].class)));
one(expectedReturnValue).setResultTransformer(resultTransformer);
}
});
// setup sut
sutSubclass.setFullTextEntityManager(ftem);
sutSubclass.setResultTypes(resultTypes);
sutSubclass.setResultFields(entityFields);
sutSubclass.setResultTransformer(resultTransformer);
assertEquals("Integer", sutSubclass.getEntityNames());
// invoke sut
org.hibernate.search.jpa.FullTextQuery returnedValue = sutSubclass.prepareQuery(queryParser, searchText);
// broken
assertTrue(returnedValue instanceof ProjectionFullTextQuery);
// all expectations met?
context.assertIsSatisfied();
}
/**
* Test the getEntityNames() method.
*/
@Test
public void testGetEntityNames()
{
final Class< ? >[] resultTypes = { Integer.class, Long.class };
ProjectionSearchRequestBuilderTestHelper sutSubclass = new ProjectionSearchRequestBuilderTestHelper();
sutSubclass.setResultTypes(resultTypes);
assertEquals("Integer, Long", sutSubclass.getEntityNames());
}
/**
* Test the buildQueryFromSearchText() method.
*/
@Test
public void testBuildQueryFromSearchTextWithAdvancedCharacters()
{
ProjectionSearchRequestBuilderTestHelper sutSubclass = new ProjectionSearchRequestBuilderTestHelper();
final org.hibernate.search.jpa.FullTextQuery preparedQuery = context.mock(
org.hibernate.search.jpa.FullTextQuery.class, "preparedQuery");
final QueryParserBuilder advancedQueryParserBuilder = context.mock(QueryParserBuilder.class,
"advanced query parser");
final QueryParser queryParser = context.mock(QueryParser.class);
final QueryParserBuilder basicQueryParserBuilder = context.mock(QueryParserBuilder.class, "basic query parser");
sutSubclass.setAdvancedQueryParserBuilder(advancedQueryParserBuilder);
sutSubclass.setQueryParserBuilder(basicQueryParserBuilder);
sutSubclass.setPreparedQuery(preparedQuery);
// Set up expectations
context.checking(new Expectations()
{
{
one(advancedQueryParserBuilder).buildQueryParser();
will(returnValue(queryParser));
}
});
// invoke sut
org.hibernate.search.jpa.FullTextQuery returnValue = sutSubclass
.buildQueryFromSearchText("(hi: there) (foo\\ bar)");
assertSame(preparedQuery, returnValue);
// make sure the expected params were passed into prepareQuery
assertSame(queryParser, sutSubclass.getPreparedQueryQueryParser());
assertEquals("(hi\\: there) (foo\\\\ bar)", sutSubclass.getPrepareQueryNativeSearchString());
context.assertIsSatisfied();
}
/**
* Test the buildQueryFromSearchText() method.
*/
@Test
public void testBuildQueryFromSearchTextWithStandardCharacters()
{
ProjectionSearchRequestBuilderTestHelper sutSubclass = new ProjectionSearchRequestBuilderTestHelper();
final org.hibernate.search.jpa.FullTextQuery preparedQuery = context.mock(
org.hibernate.search.jpa.FullTextQuery.class, "preparedQuery");
final QueryParserBuilder advancedQueryParserBuilder = context.mock(QueryParserBuilder.class,
"advanced query parser");
final QueryParserBuilder basicQueryParserBuilder = context.mock(QueryParserBuilder.class, "basic query parser");
final QueryParser queryParser = context.mock(QueryParser.class);
sutSubclass.setAdvancedQueryParserBuilder(advancedQueryParserBuilder);
sutSubclass.setQueryParserBuilder(basicQueryParserBuilder);
sutSubclass.setPreparedQuery(preparedQuery);
sutSubclass.setSearchStringFormat("field1:(%1$s) or field2:(%1$s)");
// Set up expectations
context.checking(new Expectations()
{
{
one(basicQueryParserBuilder).buildQueryParser();
will(returnValue(queryParser));
}
});
// invoke sut
org.hibernate.search.jpa.FullTextQuery returnValue = sutSubclass.buildQueryFromSearchText("hi there foo bar");
assertSame(preparedQuery, returnValue);
// make sure the expected params were passed into prepareQuery
assertSame(queryParser, sutSubclass.getPreparedQueryQueryParser());
assertEquals("field1:(hi there foo bar) or field2:(hi there foo bar)", sutSubclass
.getPrepareQueryNativeSearchString());
context.assertIsSatisfied();
}
/**
* Test the buildQueryFromNativeSearchString() method.
*/
@Test
public void testBuildQueryFromNativeSearchString()
{
ProjectionSearchRequestBuilderTestHelper sutSubclass = new ProjectionSearchRequestBuilderTestHelper();
final org.hibernate.search.jpa.FullTextQuery preparedQuery = context.mock(
org.hibernate.search.jpa.FullTextQuery.class, "preparedQuery");
sutSubclass.setPreparedQuery(preparedQuery);
final QueryParserBuilder basicQueryParserBuilder = context.mock(QueryParserBuilder.class, "basic query parser");
sutSubclass.setQueryParserBuilder(basicQueryParserBuilder);
final QueryParser queryParser = context.mock(QueryParser.class);
// Set up expectations
context.checking(new Expectations()
{
{
one(basicQueryParserBuilder).buildQueryParser();
will(returnValue(queryParser));
}
});
// invoke sut
sutSubclass.buildQueryFromNativeSearchString("field1:(hi there foo bar) or field2:(hi there foo bar)");
// make sure the expected params were passed into prepareQuery
assertSame(queryParser, sutSubclass.getPreparedQueryQueryParser());
assertEquals("field1:(hi there foo bar) or field2:(hi there foo bar)", sutSubclass
.getPrepareQueryNativeSearchString());
context.assertIsSatisfied();
}
/**
* Helper class for ProjectionSearchRequestBuilder - for stubbing out untestable stuff.
*/
private class ProjectionSearchRequestBuilderTestHelper extends ProjectionSearchRequestBuilder
{
/**
* Mocked out FullTextEntityManager.
*/
private FullTextEntityManager fullTextEntityManager;
/**
* Mocked prepared query.
*/
private org.hibernate.search.jpa.FullTextQuery preparedQuery;
/**
* Setter for preparedQuery.
*
* @param inPreparedQuery
* the preparedQuery
*/
public void setPreparedQuery(final org.hibernate.search.jpa.FullTextQuery inPreparedQuery)
{
preparedQuery = inPreparedQuery;
}
/**
* Setter for fullTextEntityManager.
*
* @param ftem
* the FullTextEntityManager
* @return
*/
public void setFullTextEntityManager(final FullTextEntityManager ftem)
{
fullTextEntityManager = ftem;
}
/**
* Override the parent class's getFullTextEntityManager() method to return a canned one.
*
* @return a FullTextEntityManager from the entityManager.
*/
@Override
protected FullTextEntityManager getFullTextEntityManager()
{
return fullTextEntityManager;
}
/**
* Prepare the input luceneQuery - return the mocked out one if not null, else call super.prepareQuery().
*
* @param inQueryParser
* the QueryParser to use
* @param nativeSearchString
* the query to prepare
* @return the fully prepared FullTextQuery
*/
@Override
protected org.hibernate.search.jpa.FullTextQuery prepareQuery(final QueryParser inQueryParser,
final String nativeSearchString)
{
if (preparedQuery != null)
{
// store these values for assertions
preparedQueryQueryParser = inQueryParser;
prepareQueryNativeSearchString = nativeSearchString;
// return the canned query
return preparedQuery;
}
else
{
return super.prepareQuery(inQueryParser, nativeSearchString);
}
}
/**
* The QueryParser passed into prepareQuery - stored for assertion.
*/
private QueryParser preparedQueryQueryParser;
/**
* The native search string passed into prepareQuery - stored for assertion.
*/
private String prepareQueryNativeSearchString;
/**
* Get the QueryParser passed into prepareQuery.
*
* @return the QueryParser passed into prepareQuery
*/
public QueryParser getPreparedQueryQueryParser()
{
return preparedQueryQueryParser;
}
/**
* Get the native search string passed into prepareQuery.
*
* @return the prepared query that was passed into the query parser
*/
public String getPrepareQueryNativeSearchString()
{
return prepareQueryNativeSearchString;
}
}
}