1
/*------------------------------------------------------------------------------
2
* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
4
* Distributable under the terms of either the Apache License (Version 2.0) or
5
* the GNU Lesser General Public License, as specified in the COPYING file.
6
------------------------------------------------------------------------------*/
9
class MQPTestFilter: public TokenFilter {
13
int32_t savedStart, savedEnd;
16
* Filter which discards the token 'stop' and which expands the
17
* token 'phrase' into 'phrase1 phrase2'
19
MQPTestFilter(TokenStream* in):
27
CL_NS(analysis)::Token* next(CL_NS(analysis)::Token* token) {
30
token->set( _T("phrase2"), savedStart, savedEnd);
33
while( input->next(token) ){
34
if ( _tcscmp(token->termBuffer(), _T("phrase")) == 0 ) {
36
savedStart = token->startOffset();
37
savedEnd = token->endOffset();
38
token->set( _T("phrase1"), savedStart, savedEnd);
40
}else if ( _tcscmp(token->termBuffer(), _T("stop") ) !=0 ){
49
class MQPTestAnalyzer: public Analyzer {
54
/** Filters LowerCaseTokenizer with StopFilter. */
55
TokenStream* tokenStream(const TCHAR* /*fieldName*/, Reader* reader) {
56
return _CLNEW MQPTestFilter(_CLNEW LowerCaseTokenizer(reader));
60
void assertQueryEquals(CuTest *tc,const TCHAR* result, Query* q) {
64
TCHAR* s = q->toString();
65
int ret = _tcscmp(s,result);
68
TCHAR buf[HUGE_STRING_LEN];
69
_sntprintf(buf, HUGE_STRING_LEN, _T("FAILED Query yielded /%s/, expecting /%s/\n"), s, result);
77
// verify parsing of query using a stopping analyzer
78
void assertStopQueryEquals(CuTest *tc, const TCHAR* qtxt, const TCHAR* expectedRes) {
79
const TCHAR* fields[] = {_T("b"), _T("t"), NULL };
80
const uint8_t occur[] = {BooleanClause::SHOULD, BooleanClause::SHOULD, NULL};
81
MQPTestAnalyzer *a = _CLNEW MQPTestAnalyzer();
82
MultiFieldQueryParser mfqp(fields, a);
84
Query *q = mfqp.parse(qtxt);
85
assertQueryEquals(tc, expectedRes, q);
87
q = MultiFieldQueryParser::parse(qtxt, reinterpret_cast<const TCHAR**>(&fields),
88
reinterpret_cast<const uint8_t*>(&occur), a);
89
assertQueryEquals(tc, expectedRes, q);
93
/** test stop words arsing for both the non static form, and for the
94
* corresponding static form (qtxt, fields[]). */
95
void tesStopwordsParsing(CuTest *tc) {
96
assertStopQueryEquals(tc, _T("one"), _T("b:one t:one"));
97
assertStopQueryEquals(tc, _T("one stop"), _T("b:one t:one"));
98
assertStopQueryEquals(tc, _T("one (stop)"), _T("b:one t:one"));
99
assertStopQueryEquals(tc, _T("one ((stop))"), _T("b:one t:one"));
100
assertStopQueryEquals(tc, _T("stop"), _T(""));
101
assertStopQueryEquals(tc, _T("(stop)"), _T(""));
102
assertStopQueryEquals(tc, _T("((stop))"), _T(""));
105
void testMFQPSimple(CuTest *tc) {
106
const TCHAR* fields[] = {_T("b"), _T("t"), NULL};
107
Analyzer* a = _CLNEW StandardAnalyzer();
108
MultiFieldQueryParser mfqp(fields, a);
110
Query *q = mfqp.parse(_T("one"));
111
assertQueryEquals(tc, _T("b:one t:one"), q);
113
q = mfqp.parse(_T("one two"));
114
assertQueryEquals(tc, _T("(b:one t:one) (b:two t:two)"),q);
116
q = mfqp.parse(_T("+one +two"));
117
assertQueryEquals(tc, _T("+(b:one t:one) +(b:two t:two)"), q);
119
q = mfqp.parse(_T("+one -two -three"));
120
assertQueryEquals(tc, _T("+(b:one t:one) -(b:two t:two) -(b:three t:three)"), q);
122
q = mfqp.parse(_T("one^2 two"));
123
assertQueryEquals(tc, _T("((b:one t:one)^2.0) (b:two t:two)"), q);
125
q = mfqp.parse(_T("one~ two"));
126
assertQueryEquals(tc, _T("(b:one~0.5 t:one~0.5) (b:two t:two)"), q);
128
q = mfqp.parse(_T("one~0.8 two^2"));
129
assertQueryEquals(tc, _T("(b:one~0.8 t:one~0.8) ((b:two t:two)^2.0)"), q);
131
q = mfqp.parse(_T("one* two*"));
132
assertQueryEquals(tc, _T("(b:one* t:one*) (b:two* t:two*)"), q);
134
q = mfqp.parse(_T("[a TO c] two"));
135
assertQueryEquals(tc, _T("(b:[a TO c] t:[a TO c]) (b:two t:two)"), q);
137
q = mfqp.parse(_T("w?ldcard"));
138
assertQueryEquals(tc, _T("b:w?ldcard t:w?ldcard"), q);
140
q = mfqp.parse(_T("\"foo bar\""));
141
assertQueryEquals(tc, _T("b:\"foo bar\" t:\"foo bar\""), q);
143
q = mfqp.parse(_T("\"aa bb cc\" \"dd ee\""));
144
assertQueryEquals(tc, _T("(b:\"aa bb cc\" t:\"aa bb cc\") (b:\"dd ee\" t:\"dd ee\")"), q);
146
q = mfqp.parse(_T("\"foo bar\"~4"));
147
assertQueryEquals(tc, _T("b:\"foo bar\"~4 t:\"foo bar\"~4"), q);
149
// make sure that terms which have a field are not touched:
150
q = mfqp.parse(_T("one f:two"));
151
assertQueryEquals(tc, _T("(b:one t:one) f:two"), q);
154
mfqp.setDefaultOperator(QueryParser::AND_OPERATOR);
155
q = mfqp.parse(_T("one two"));
156
assertQueryEquals(tc, _T("+(b:one t:one) +(b:two t:two)"), q);
157
q = mfqp.parse(_T("\"aa bb cc\" \"dd ee\""));
158
assertQueryEquals(tc, _T("+(b:\"aa bb cc\" t:\"aa bb cc\") +(b:\"dd ee\" t:\"dd ee\")"), q);
163
CuSuite *testMultiFieldQueryParser(void)
165
CuSuite *suite = CuSuiteNew(_T("CLucene Multi-Field QP Test"));
167
SUITE_ADD_TEST(suite, tesStopwordsParsing);
168
SUITE_ADD_TEST(suite, testMFQPSimple);