324 lines
12 KiB
C++
324 lines
12 KiB
C++
/*------------------------------------------------------------------------------
|
|
* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
|
|
*
|
|
* Distributable under the terms of either the Apache License (Version 2.0) or
|
|
* the GNU Lesser General Public License, as specified in the COPYING file.
|
|
------------------------------------------------------------------------------*/
|
|
#include "test.h"
|
|
|
|
class QPTestFilter: public TokenFilter {
|
|
public:
|
|
|
|
bool inPhrase;
|
|
int32_t savedStart, savedEnd;
|
|
|
|
/**
|
|
* Filter which discards the token 'stop' and which expands the
|
|
* token 'phrase' into 'phrase1 phrase2'
|
|
*/
|
|
QPTestFilter(TokenStream* in):
|
|
TokenFilter(in,true),
|
|
inPhrase(false),
|
|
savedStart(0),
|
|
savedEnd(0)
|
|
{
|
|
}
|
|
|
|
bool next(Token* token) {
|
|
if (inPhrase) {
|
|
inPhrase = false;
|
|
token->set( _T("phrase2"), savedStart, savedEnd);
|
|
return true;
|
|
}else{
|
|
while( input->next(token) ){
|
|
if ( _tcscmp(token->termText(), _T("phrase")) == 0 ) {
|
|
inPhrase = true;
|
|
savedStart = token->startOffset();
|
|
savedEnd = token->endOffset();
|
|
token->set( _T("phrase1"), savedStart, savedEnd);
|
|
return true;
|
|
}else if ( _tcscmp(token->termText(), _T("stop") ) !=0 ){
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
class QPTestAnalyzer: public Analyzer {
|
|
public:
|
|
QPTestAnalyzer() {
|
|
}
|
|
|
|
/** Filters LowerCaseTokenizer with StopFilter. */
|
|
TokenStream* tokenStream(const TCHAR* fieldName, Reader* reader) {
|
|
return _CLNEW QPTestFilter(_CLNEW LowerCaseTokenizer(reader));
|
|
}
|
|
};
|
|
|
|
Query* getQuery(CuTest *tc,const TCHAR* query, Analyzer* a) {
|
|
try{
|
|
bool del = (a==NULL);
|
|
if (a == NULL)
|
|
a = _CLNEW SimpleAnalyzer();
|
|
|
|
QueryParser qp(_T("field"), a);
|
|
Query* ret = qp.parse(query);
|
|
|
|
if ( del )
|
|
_CLDELETE(a);
|
|
return ret;
|
|
}catch(CLuceneError& e){
|
|
CuFail(tc,_T("/%s/ threw an error: %s - "),query, e.twhat());
|
|
CuFail(tc,_T("%s\n"),e.twhat());
|
|
return NULL;
|
|
}catch(...){
|
|
CuFail(tc,_T("/%s/ threw an error.\n"),query);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
void assertQueryEquals(CuTest *tc,const TCHAR* query, Analyzer* a, const TCHAR* result) {
|
|
|
|
Query* q = getQuery(tc,query, a);
|
|
if ( q == NULL )
|
|
return;
|
|
|
|
const TCHAR* s = q->toString(_T("field"));
|
|
if ( _tcscmp(s,result) != 0 ) {
|
|
CuFail(tc, _T("FAILED Query /%s/ yielded /%s/, expecting /%s/\n"), query, s,
|
|
result);
|
|
}
|
|
_CLDELETE_CARRAY(s);
|
|
_CLDELETE(q);
|
|
|
|
}
|
|
|
|
void assertTrue(CuTest *tc,const TCHAR* query, Analyzer* a, const TCHAR* inst, const TCHAR* msg){
|
|
Query* q = getQuery(tc,query,a);
|
|
bool success = q->instanceOf(inst);
|
|
_CLDELETE(q);
|
|
CuAssert(tc,msg,success);
|
|
}
|
|
|
|
void testSimple(CuTest *tc) {
|
|
StandardAnalyzer a;
|
|
assertQueryEquals(tc,_T("term term term"), NULL, _T("term term term"));
|
|
|
|
TCHAR tmp1[100];
|
|
|
|
#ifdef _UCS2
|
|
lucene_utf8towcs(tmp1,"t\xc3\xbcrm term term",100);
|
|
assertQueryEquals(tc,tmp1, NULL, tmp1);
|
|
assertQueryEquals(tc,tmp1, &a, tmp1);
|
|
|
|
lucene_utf8towcs(tmp1,"\xc3\xbcmlaut",100);
|
|
assertQueryEquals(tc,tmp1, NULL, tmp1);
|
|
assertQueryEquals(tc,tmp1, &a, tmp1);
|
|
#endif
|
|
|
|
assertQueryEquals(tc,_T("a AND b"), NULL, _T("+a +b"));
|
|
assertQueryEquals(tc,_T("(a AND b)"), NULL, _T("+a +b"));
|
|
assertQueryEquals(tc,_T("c OR (a AND b)"), NULL, _T("c (+a +b)"));
|
|
assertQueryEquals(tc,_T("a AND NOT b"), NULL, _T("+a -b"));
|
|
assertQueryEquals(tc,_T("a AND -b"), NULL, _T("+a -b"));
|
|
assertQueryEquals(tc,_T("a AND !b"), NULL, _T("+a -b"));
|
|
assertQueryEquals(tc,_T("a && b"), NULL, _T("+a +b"));
|
|
assertQueryEquals(tc,_T("a && ! b"), NULL, _T("+a -b"));
|
|
|
|
assertQueryEquals(tc,_T("a OR b"), NULL, _T("a b"));
|
|
assertQueryEquals(tc,_T("a || b"), NULL, _T("a b"));
|
|
assertQueryEquals(tc,_T("a OR !b"), NULL, _T("a -b"));
|
|
assertQueryEquals(tc,_T("a OR ! b"), NULL, _T("a -b"));
|
|
assertQueryEquals(tc,_T("a OR -b"), NULL, _T("a -b"));
|
|
|
|
assertQueryEquals(tc,_T("+term -term term"), NULL, _T("+term -term term"));
|
|
assertQueryEquals(tc,_T("foo:term AND field:anotherTerm"), NULL,
|
|
_T("+foo:term +anotherterm"));
|
|
assertQueryEquals(tc,_T("term AND \"phrase phrase\""), NULL,
|
|
_T("+term +\"phrase phrase\"") );
|
|
assertQueryEquals(tc,_T("\"hello there\""), NULL, _T("\"hello there\"") );
|
|
|
|
assertTrue(tc, _T("a AND b"), NULL,_T("BooleanQuery"),_T("a AND b") );
|
|
assertTrue(tc, _T("hello"), NULL,_T("TermQuery"), _T("hello"));
|
|
assertTrue(tc, _T("\"hello there\""), NULL,_T("PhraseQuery"), _T("\"hello there\""));
|
|
|
|
assertQueryEquals(tc,_T("germ term^2.0"), NULL, _T("germ term^2.0"));
|
|
assertQueryEquals(tc,_T("term^2.0"), NULL, _T("term^2.0"));
|
|
assertQueryEquals(tc,_T("term^2"), NULL, _T("term^2.0"));
|
|
assertQueryEquals(tc,_T("term^2.3"), NULL, _T("term^2.3"));
|
|
assertQueryEquals(tc,_T("\"germ term\"^2.0"), NULL, _T("\"germ term\"^2.0"));
|
|
assertQueryEquals(tc,_T("\"term germ\"^2"), NULL, _T("\"term germ\"^2.0") );
|
|
|
|
assertQueryEquals(tc,_T("(foo OR bar) AND (baz OR boo)"), NULL,
|
|
_T("+(foo bar) +(baz boo)"));
|
|
assertQueryEquals(tc,_T("((a OR b) AND NOT c) OR d"), NULL,
|
|
_T("(+(a b) -c) d"));
|
|
assertQueryEquals(tc,_T("+(apple \"steve jobs\") -(foo bar baz)"), NULL,
|
|
_T("+(apple \"steve jobs\") -(foo bar baz)") );
|
|
assertQueryEquals(tc,_T("+title:(dog OR cat) -author:\"bob dole\""), NULL,
|
|
_T("+(title:dog title:cat) -author:\"bob dole\"") );
|
|
|
|
}
|
|
|
|
void testPunct(CuTest *tc) {
|
|
WhitespaceAnalyzer a;
|
|
assertQueryEquals(tc,_T("a&b"), &a, _T("a&b"));
|
|
assertQueryEquals(tc,_T("a&&b"), &a, _T("a&&b"));
|
|
assertQueryEquals(tc,_T(".NET"), &a, _T(".NET"));
|
|
}
|
|
|
|
void testSlop(CuTest *tc) {
|
|
assertQueryEquals(tc,_T("\"term germ\"~2"), NULL, _T("\"term germ\"~2") );
|
|
assertQueryEquals(tc,_T("\"term germ\"~2 flork"), NULL, _T("\"term germ\"~2 flork") );
|
|
assertQueryEquals(tc,_T("\"term\"~2"), NULL, _T("term"));
|
|
assertQueryEquals(tc,_T("\" \"~2 germ"), NULL, _T("germ"));
|
|
assertQueryEquals(tc,_T("\"term germ\"~2^2"), NULL, _T("\"term germ\"~2^2.0") );
|
|
}
|
|
|
|
void testNumber(CuTest *tc) {
|
|
// The numbers go away because SimpleAnalzyer ignores them
|
|
assertQueryEquals(tc,_T("3"), NULL, _T(""));
|
|
assertQueryEquals(tc,_T("term 1.0 1 2"), NULL, _T("term"));
|
|
assertQueryEquals(tc,_T("term term1 term2"), NULL, _T("term term term"));
|
|
|
|
StandardAnalyzer a;
|
|
assertQueryEquals(tc,_T("3"), &a, _T("3"));
|
|
assertQueryEquals(tc,_T("term 1.0 1 2"), &a, _T("term 1.0 1 2"));
|
|
assertQueryEquals(tc,_T("term term1 term2"), &a, _T("term term1 term2"));
|
|
}
|
|
|
|
void testWildcard(CuTest *tc) {
|
|
|
|
assertQueryEquals(tc,_T("term*"), NULL, _T("term*"));
|
|
assertQueryEquals(tc,_T("term*^2"), NULL, _T("term*^2.0"));
|
|
|
|
#ifndef NO_FUZZY_QUERY
|
|
assertQueryEquals(tc,_T("term~"), NULL, _T("term~0.5"));
|
|
assertQueryEquals(tc,_T("term~^2"), NULL, _T("term^2.0~0.5"));
|
|
assertQueryEquals(tc,_T("term^2~"), NULL, _T("term^2.0~0.5"));
|
|
assertTrue(tc, _T("term~"), NULL,_T("FuzzyQuery"), _T("term~0.5"));
|
|
#endif
|
|
assertQueryEquals(tc,_T("term*germ"), NULL, _T("term*germ"));
|
|
assertQueryEquals(tc,_T("term*germ^3"), NULL, _T("term*germ^3.0"));
|
|
|
|
assertTrue(tc, _T("term*"), NULL,_T("PrefixQuery"), _T("term*"));
|
|
assertTrue(tc, _T("term*^2"), NULL,_T("PrefixQuery"), _T("term*^2.0"));
|
|
assertTrue(tc, _T("term*germ"), NULL,_T("WildcardQuery"), _T("term*germ"));
|
|
}
|
|
|
|
void testQPA(CuTest *tc) {
|
|
QPTestAnalyzer qpAnalyzer;
|
|
assertQueryEquals(tc,_T("term term term"), &qpAnalyzer, _T("term term term") );
|
|
assertQueryEquals(tc,_T("term +stop term"), &qpAnalyzer, _T("term term") );
|
|
assertQueryEquals(tc,_T("term -stop term"), &qpAnalyzer, _T("term term") );
|
|
assertQueryEquals(tc,_T("drop AND stop AND roll"), &qpAnalyzer, _T("+drop +roll") );
|
|
assertQueryEquals(tc,_T("term phrase term"), &qpAnalyzer,
|
|
_T("term \"phrase1 phrase2\" term") );
|
|
assertQueryEquals(tc,_T("term AND NOT phrase term"), &qpAnalyzer,
|
|
_T("+term -\"phrase1 phrase2\" term") );
|
|
assertQueryEquals(tc,_T("stop"), &qpAnalyzer, _T("") );
|
|
assertTrue(tc, _T("term term term"), &qpAnalyzer,_T("BooleanQuery"), _T("term term term"));
|
|
assertTrue(tc, _T("term +stop"), &qpAnalyzer,_T("TermQuery"), _T("term +stop"));
|
|
}
|
|
|
|
void testRange(CuTest *tc) {
|
|
StandardAnalyzer a;
|
|
|
|
assertQueryEquals(tc,_T("[ a z]"), NULL, _T("[a TO z]"));
|
|
assertTrue(tc, _T("[ a z]"), NULL, _T("RangeQuery"), _T("[ a z]") );
|
|
assertQueryEquals(tc,_T("[ a z ]"), NULL, _T("[a TO z]"));
|
|
assertQueryEquals(tc,_T("{ a z}"), NULL, _T("{a TO z}"));
|
|
assertQueryEquals(tc,_T("{ a z }"), NULL, _T("{a TO z}"));
|
|
assertQueryEquals(tc,_T("{ a z }^2.0"), NULL, _T("{a TO z}^2.0"));
|
|
assertQueryEquals(tc,_T("[ a z] OR bar"), NULL, _T("[a TO z] bar"));
|
|
assertQueryEquals(tc,_T("[ a z] AND bar"), NULL, _T("+[a TO z] +bar"));
|
|
assertQueryEquals(tc,_T("( bar blar { a z}) "), NULL, _T("bar blar {a TO z}"));
|
|
assertQueryEquals(tc,_T("gack ( bar blar { a z}) "), NULL, _T("gack (bar blar {a TO z})"));
|
|
|
|
assertQueryEquals(tc,_T("[050-070]"), &a, _T("[050 TO -070]"));
|
|
}
|
|
|
|
void testEscaped(CuTest *tc) {
|
|
WhitespaceAnalyzer a;
|
|
/*assertQueryEquals("\\[brackets"), &a, _T("\\[brackets") );
|
|
assertQueryEquals(tc,_T("\\[brackets"), null, _T("brackets") );
|
|
assertQueryEquals(tc,_T("\\\\"), &a, _T("\\\\") );
|
|
assertQueryEquals(tc,_T("\\+blah"), &a, _T("\\+blah") );
|
|
assertQueryEquals(tc,_T("\\(blah"), &a, _T("\\(blah") );
|
|
|
|
assertQueryEquals(tc,_T("\\-blah"), &a, _T("\\-blah") );
|
|
assertQueryEquals(tc,_T("\\!blah"), &a, _T("\\!blah") );
|
|
assertQueryEquals(tc,_T("\\{blah"), &a, _T("\\{blah") );
|
|
assertQueryEquals(tc,_T("\\}blah"), &a, _T("\\}blah") );
|
|
assertQueryEquals(tc,_T("\\:blah"), &a, _T("\\:blah") );
|
|
assertQueryEquals(tc,_T("\\^blah"), &a, _T("\\^blah") );
|
|
assertQueryEquals(tc,_T("\\[blah"), &a, _T("\\[blah") );
|
|
assertQueryEquals(tc,_T("\\]blah"), &a, _T("\\]blah") );
|
|
assertQueryEquals(tc,_T("\\\"blah"), &a, _T("\\\"blah") );
|
|
assertQueryEquals(tc,_T("\\(blah"), &a, _T("\\(blah") );
|
|
assertQueryEquals(tc,_T("\\)blah"), &a, _T("\\)blah") );
|
|
assertQueryEquals(tc,_T("\\~blah"), &a, _T("\\~blah") );
|
|
assertQueryEquals(tc,_T("\\*blah"), &a, _T("\\*blah") );
|
|
assertQueryEquals(tc,_T("\\?blah"), &a, _T("\\?blah") );
|
|
//assertQueryEquals(tc,_T("foo \\&\\& bar"), &a, _T("foo \\&\\& bar") );
|
|
//assertQueryEquals(tc,_T("foo \\|| bar"), &a, _T("foo \\|| bar") );
|
|
//assertQueryEquals(tc,_T("foo \\AND bar"), &a, _T("foo \\AND bar") );*/
|
|
|
|
assertQueryEquals(tc,_T("a\\-b:c"), &a, _T("a-b:c") );
|
|
assertQueryEquals(tc,_T("a\\+b:c"), &a, _T("a+b:c") );
|
|
assertQueryEquals(tc,_T("a\\:b:c"), &a, _T("a:b:c") );
|
|
assertQueryEquals(tc,_T("a\\\\b:c"), &a, _T("a\\b:c") );
|
|
|
|
assertQueryEquals(tc,_T("a:b\\-c"), &a, _T("a:b-c") );
|
|
assertQueryEquals(tc,_T("a:b\\+c"), &a, _T("a:b+c") );
|
|
assertQueryEquals(tc,_T("a:b\\:c"), &a, _T("a:b:c") );
|
|
assertQueryEquals(tc,_T("a:b\\\\c"), &a, _T("a:b\\c") );
|
|
|
|
assertQueryEquals(tc,_T("a:b\\-c*"), &a, _T("a:b-c*") );
|
|
assertQueryEquals(tc,_T("a:b\\+c*"), &a, _T("a:b+c*") );
|
|
assertQueryEquals(tc,_T("a:b\\:c*"), &a, _T("a:b:c*") );
|
|
|
|
assertQueryEquals(tc,_T("a:b\\\\c*"), &a, _T("a:b\\c*") );
|
|
|
|
assertQueryEquals(tc,_T("a:b\\-?c"), &a, _T("a:b-?c") );
|
|
assertQueryEquals(tc,_T("a:b\\+?c"), &a, _T("a:b+?c") );
|
|
assertQueryEquals(tc,_T("a:b\\:?c"), &a, _T("a:b:?c") );
|
|
|
|
assertQueryEquals(tc,_T("a:b\\\\?c"), &a, _T("a:b\\?c") );
|
|
|
|
assertQueryEquals(tc,_T("a:b\\-c~"), &a, _T("a:b-c~0.5") );
|
|
assertQueryEquals(tc,_T("a:b\\+c~"), &a, _T("a:b+c~0.5") );
|
|
assertQueryEquals(tc,_T("a:b\\:c~"), &a, _T("a:b:c~0.5") );
|
|
assertQueryEquals(tc,_T("a:b\\\\c~"), &a, _T("a:b\\c~0.5") );
|
|
|
|
assertQueryEquals(tc,_T("[ a\\- TO a\\+ ]"), &a, _T("[a- TO a+]") );
|
|
assertQueryEquals(tc,_T("[ a\\: TO a\\~ ]"), &a, _T("[a: TO a~]") );
|
|
assertQueryEquals(tc,_T("[ a\\\\ TO a\\* ]"), &a, _T("[a\\ TO a*]") );
|
|
}
|
|
|
|
|
|
CuSuite *testQueryParser(void)
|
|
{
|
|
CuSuite *suite = CuSuiteNew(_T("CLucene Query Parser Test"));
|
|
|
|
SUITE_ADD_TEST(suite, testSimple);
|
|
SUITE_ADD_TEST(suite, testQPA);
|
|
SUITE_ADD_TEST(suite, testEscaped);
|
|
SUITE_ADD_TEST(suite, testNumber);
|
|
SUITE_ADD_TEST(suite, testPunct);
|
|
|
|
#ifndef NO_FUZZY_QUERY
|
|
SUITE_ADD_TEST(suite, testSlop);
|
|
#endif
|
|
#ifndef NO_RANGE_QUERY
|
|
SUITE_ADD_TEST(suite, testRange);
|
|
#endif
|
|
#ifndef NO_WILDCARD_QUERY
|
|
SUITE_ADD_TEST(suite, testWildcard);
|
|
#endif
|
|
return suite;
|
|
}
|
|
// EOF
|