1 /* api_db.cc: tests which need a backend
3 * Copyright 1999,2000,2001 BrightStation PLC
4 * Copyright 2002 Ananova Ltd
5 * Copyright 2002,2003,2004,2005,2006,2007,2008,2009,2011,2012,2013,2015 Olly Betts
6 * Copyright 2006,2007,2008,2009 Lemur Consulting Ltd
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
33 #include "safesysstat.h" // For mkdir().
34 #include "safeunistd.h" // For sleep().
38 #include "backendmanager.h"
39 #include "backendmanager_local.h"
40 #include "testsuite.h"
41 #include "testutils.h"
49 query(const string
&t
)
51 return Xapian::Query(Xapian::Stem("english")(t
));
54 // #######################################################################
57 // tests Xapian::Database::get_termfreq() and Xapian::Database::term_exists()
58 DEFINE_TESTCASE(termstats
, backend
) {
59 Xapian::Database
db(get_database("apitest_simpledata"));
61 TEST(!db
.term_exists("corn"));
62 TEST_EQUAL(db
.get_termfreq("corn"), 0);
63 TEST(db
.term_exists("banana"));
64 TEST_EQUAL(db
.get_termfreq("banana"), 1);
65 TEST(db
.term_exists("paragraph"));
66 TEST_EQUAL(db
.get_termfreq("paragraph"), 5);
71 // Check that stub databases work.
72 DEFINE_TESTCASE(stubdb1
, backend
&& !inmemory
&& !remote
) {
73 // Only works for backends which have a path.
75 const char * dbpath
= ".stub/stubdb1";
78 out
<< "auto ../" << get_database_path("apitest_simpledata") << endl
;
82 Xapian::Database
db(dbpath
, Xapian::DB_BACKEND_STUB
);
83 Xapian::Enquire
enquire(db
);
84 enquire
.set_query(Xapian::Query("word"));
85 enquire
.get_mset(0, 10);
88 Xapian::Database
db(dbpath
);
89 Xapian::Enquire
enquire(db
);
90 enquire
.set_query(Xapian::Query("word"));
91 enquire
.get_mset(0, 10);
97 // Check that stub databases work remotely.
98 DEFINE_TESTCASE(stubdb2
, backend
&& !inmemory
&& !remote
) {
99 // Only works for backends which have a path.
100 mkdir(".stub", 0755);
101 const char * dbpath
= ".stub/stubdb2";
102 ofstream
out(dbpath
);
104 out
<< "remote :" << BackendManager::get_xapian_progsrv_command()
105 << ' ' << get_database_path("apitest_simpledata") << endl
;
109 Xapian::Database
db(dbpath
, Xapian::DB_BACKEND_STUB
);
110 Xapian::Enquire
enquire(db
);
111 enquire
.set_query(Xapian::Query("word"));
112 enquire
.get_mset(0, 10);
115 Xapian::Database
db(dbpath
);
116 Xapian::Enquire
enquire(db
);
117 enquire
.set_query(Xapian::Query("word"));
118 enquire
.get_mset(0, 10);
124 // Regression test - bad entries were ignored after a good entry prior to 1.0.8.
125 DEFINE_TESTCASE(stubdb3
, backend
&& !inmemory
&& !remote
) {
126 // Only works for backends which have a path.
127 mkdir(".stub", 0755);
128 const char * dbpath
= ".stub/stubdb3";
129 ofstream
out(dbpath
);
131 out
<< "auto ../" << get_database_path("apitest_simpledata") << "\n"
135 TEST_EXCEPTION(Xapian::DatabaseOpeningError
,
136 Xapian::Database
db(dbpath
, Xapian::DB_BACKEND_STUB
));
138 TEST_EXCEPTION(Xapian::DatabaseOpeningError
,
139 Xapian::Database
db(dbpath
));
144 // Test a stub database with just a bad entry.
145 DEFINE_TESTCASE(stubdb4
, backend
&& !inmemory
&& !remote
) {
146 // Only works for backends which have a path.
147 mkdir(".stub", 0755);
148 const char * dbpath
= ".stub/stubdb4";
149 ofstream
out(dbpath
);
151 out
<< "bad line here\n";
154 TEST_EXCEPTION(Xapian::DatabaseOpeningError
,
155 Xapian::Database
db(dbpath
, Xapian::DB_BACKEND_STUB
));
157 TEST_EXCEPTION(Xapian::DatabaseOpeningError
,
158 Xapian::Database
db(dbpath
));
163 // Test a stub database with a bad entry with no spaces (prior to 1.1.0 this
164 // was deliberately allowed, though not documented.
165 DEFINE_TESTCASE(stubdb5
, backend
&& !inmemory
&& !remote
) {
166 // Only works for backends which have a path.
167 mkdir(".stub", 0755);
168 const char * dbpath
= ".stub/stubdb5";
169 ofstream
out(dbpath
);
172 "auto ../" << get_database_path("apitest_simpledata") << endl
;
175 TEST_EXCEPTION(Xapian::DatabaseOpeningError
,
176 Xapian::Database
db(dbpath
, Xapian::DB_BACKEND_STUB
));
178 TEST_EXCEPTION(Xapian::DatabaseOpeningError
,
179 Xapian::Database
db(dbpath
));
184 // Test a stub database with an inmemory database (new feature in 1.1.0).
185 DEFINE_TESTCASE(stubdb6
, inmemory
) {
186 mkdir(".stub", 0755);
187 const char * dbpath
= ".stub/stubdb6";
188 ofstream
out(dbpath
);
195 Xapian::Database
db(dbpath
, Xapian::DB_BACKEND_STUB
);
196 TEST_EQUAL(db
.get_doccount(), 0);
197 Xapian::Enquire
enquire(db
);
198 enquire
.set_query(Xapian::Query("word"));
199 Xapian::MSet mset
= enquire
.get_mset(0, 10);
203 Xapian::Database
db(dbpath
);
204 TEST_EQUAL(db
.get_doccount(), 0);
205 Xapian::Enquire
enquire(db
);
206 enquire
.set_query(Xapian::Query("word"));
207 Xapian::MSet mset
= enquire
.get_mset(0, 10);
213 Xapian::WritableDatabase
db(dbpath
,
214 Xapian::DB_OPEN
|Xapian::DB_BACKEND_STUB
);
215 TEST_EQUAL(db
.get_doccount(), 0);
216 db
.add_document(Xapian::Document());
217 TEST_EQUAL(db
.get_doccount(), 1);
220 Xapian::WritableDatabase
db(dbpath
,
221 Xapian::DB_OPEN
|Xapian::DB_BACKEND_STUB
);
222 TEST_EQUAL(db
.get_doccount(), 0);
223 db
.add_document(Xapian::Document());
224 TEST_EQUAL(db
.get_doccount(), 1);
230 #if 0 // the "force error" mechanism is no longer in place...
231 class MyErrorHandler
: public Xapian::ErrorHandler
{
235 bool handle_error(Xapian::Error
& error
) {
237 tout
<< "Error handling caught: " << error
.get_description()
238 << ", count is now " << count
<< "\n";
242 MyErrorHandler() : count (0) {}
245 // tests error handler in multimatch().
246 DEFINE_TESTCASE(multierrhandler1
, backend
) {
247 MyErrorHandler myhandler
;
249 Xapian::Database
mydb2(get_database("apitest_simpledata"));
250 Xapian::Database
mydb3(get_database("apitest_simpledata2"));
252 for (int testcount
= 0; testcount
< 14; testcount
++) {
253 tout
<< "testcount=" << testcount
<< "\n";
254 Xapian::Database
mydb4(get_database("-e", "apitest_termorder"));
255 Xapian::Database
mydb5(get_network_database("apitest_termorder", 1));
256 Xapian::Database
mydb6(get_database("-e2", "apitest_termorder"));
257 Xapian::Database
mydb7(get_database("-e3", "apitest_simpledata"));
259 Xapian::Database dbs
;
262 dbs
.add_database(mydb2
);
263 dbs
.add_database(mydb3
);
264 dbs
.add_database(mydb4
);
267 dbs
.add_database(mydb4
);
268 dbs
.add_database(mydb2
);
269 dbs
.add_database(mydb3
);
272 dbs
.add_database(mydb3
);
273 dbs
.add_database(mydb4
);
274 dbs
.add_database(mydb2
);
277 dbs
.add_database(mydb2
);
278 dbs
.add_database(mydb3
);
279 dbs
.add_database(mydb5
);
283 dbs
.add_database(mydb5
);
284 dbs
.add_database(mydb2
);
285 dbs
.add_database(mydb3
);
289 dbs
.add_database(mydb3
);
290 dbs
.add_database(mydb5
);
291 dbs
.add_database(mydb2
);
295 dbs
.add_database(mydb2
);
296 dbs
.add_database(mydb3
);
297 dbs
.add_database(mydb6
);
300 dbs
.add_database(mydb6
);
301 dbs
.add_database(mydb2
);
302 dbs
.add_database(mydb3
);
305 dbs
.add_database(mydb3
);
306 dbs
.add_database(mydb6
);
307 dbs
.add_database(mydb2
);
310 dbs
.add_database(mydb2
);
311 dbs
.add_database(mydb3
);
312 dbs
.add_database(mydb7
);
315 dbs
.add_database(mydb7
);
316 dbs
.add_database(mydb2
);
317 dbs
.add_database(mydb3
);
320 dbs
.add_database(mydb3
);
321 dbs
.add_database(mydb7
);
322 dbs
.add_database(mydb2
);
325 dbs
.add_database(mydb2
);
326 dbs
.add_database(mydb6
);
327 dbs
.add_database(mydb7
);
330 dbs
.add_database(mydb2
);
331 dbs
.add_database(mydb7
);
332 dbs
.add_database(mydb6
);
335 tout
<< "db=" << dbs
<< "\n";
336 Xapian::Enquire
enquire(dbs
, &myhandler
);
339 Xapian::Query myquery
= query(Xapian::Query::OP_OR
, "inmemory", "word");
340 enquire
.set_weighting_scheme(Xapian::BoolWeight());
341 enquire
.set_query(myquery
);
343 tout
<< "query=" << myquery
<< "\n";
344 // retrieve the top ten results
345 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
348 case 0: case 3: case 6: case 9:
349 mset_expect_order(mymset
, 2, 4, 10);
351 case 1: case 4: case 7: case 10:
352 mset_expect_order(mymset
, 3, 5, 11);
354 case 2: case 5: case 8: case 11:
355 mset_expect_order(mymset
, 1, 6, 12);
359 mset_expect_order(mymset
, 4, 10);
363 TEST_EQUAL(myhandler
.count
, errcount
);
371 class myMatchDecider
: public Xapian::MatchDecider
{
373 bool operator()(const Xapian::Document
&doc
) const {
374 // Note that this is not recommended usage of get_data()
375 return doc
.get_data().find("This is") != string::npos
;
379 // Test Xapian::MatchDecider functor.
380 DEFINE_TESTCASE(matchdecider1
, backend
&& !remote
) {
381 Xapian::Database
db(get_database("apitest_simpledata"));
382 Xapian::Enquire
enquire(db
);
383 enquire
.set_query(Xapian::Query("this"));
385 myMatchDecider myfunctor
;
387 Xapian::MSet mymset
= enquire
.get_mset(0, 100, 0, &myfunctor
);
389 vector
<bool> docid_checked(db
.get_lastdocid());
391 // Check that we get the expected number of matches, and that they
392 // satisfy the condition.
393 Xapian::MSetIterator i
= mymset
.begin();
394 TEST(i
!= mymset
.end());
395 TEST_EQUAL(mymset
.size(), 3);
396 TEST_EQUAL(mymset
.get_matches_lower_bound(), 3);
397 TEST_EQUAL(mymset
.get_matches_upper_bound(), 3);
398 TEST_EQUAL(mymset
.get_matches_estimated(), 3);
399 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 3);
400 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 3);
401 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 3);
402 for ( ; i
!= mymset
.end(); ++i
) {
403 const Xapian::Document
doc(i
.get_document());
404 TEST(myfunctor(doc
));
405 docid_checked
[*i
] = true;
408 // Check that there are some documents which aren't accepted by the match
410 mymset
= enquire
.get_mset(0, 100);
411 TEST(mymset
.size() > 3);
413 // Check that the bounds are appropriate even if we don't ask for any
415 mymset
= enquire
.get_mset(0, 0, 0, &myfunctor
);
416 TEST_EQUAL(mymset
.size(), 0);
417 TEST_EQUAL(mymset
.get_matches_lower_bound(), 0);
418 TEST_EQUAL(mymset
.get_matches_upper_bound(), 6);
419 TEST_REL(mymset
.get_matches_estimated(),>,0);
420 TEST_REL(mymset
.get_matches_estimated(),<=,6);
421 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 0);
422 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 6);
423 TEST_REL(mymset
.get_uncollapsed_matches_estimated(),>,0);
424 TEST_REL(mymset
.get_uncollapsed_matches_estimated(),<=,6);
426 // Check that the bounds are appropriate if we ask for only one hit.
427 // (Regression test - until SVN 10256, we didn't reduce the lower_bound
428 // appropriately, and returned 6 here.)
429 mymset
= enquire
.get_mset(0, 1, 0, &myfunctor
);
430 TEST_EQUAL(mymset
.size(), 1);
431 TEST_REL(mymset
.get_matches_lower_bound(),>=,1);
432 TEST_REL(mymset
.get_matches_lower_bound(),<=,3);
433 TEST_REL(mymset
.get_matches_upper_bound(),>=,3);
434 TEST_REL(mymset
.get_matches_upper_bound(),<=,6);
435 TEST_REL(mymset
.get_matches_estimated(),>,0);
436 TEST_REL(mymset
.get_matches_estimated(),<=,6);
437 TEST_REL(mymset
.get_uncollapsed_matches_lower_bound(),>=,1);
438 TEST_REL(mymset
.get_uncollapsed_matches_lower_bound(),<=,3);
439 TEST_REL(mymset
.get_uncollapsed_matches_upper_bound(),>=,3);
440 TEST_REL(mymset
.get_uncollapsed_matches_upper_bound(),<=,6);
441 TEST_REL(mymset
.get_uncollapsed_matches_estimated(),>,0);
442 TEST_REL(mymset
.get_uncollapsed_matches_estimated(),<=,6);
444 // Check that the other documents don't satisfy the condition.
445 for (Xapian::docid did
= 1; did
< docid_checked
.size(); ++did
) {
446 if (!docid_checked
[did
]) {
447 TEST(!myfunctor(db
.get_document(did
)));
451 // Check that the bounds are appropriate if a collapse key is used.
452 // Use a value which is never set so we don't actually discard anything.
453 enquire
.set_collapse_key(99);
454 mymset
= enquire
.get_mset(0, 1, 0, &myfunctor
);
455 TEST_EQUAL(mymset
.size(), 1);
456 TEST_REL(mymset
.get_matches_lower_bound(),>=,1);
457 TEST_REL(mymset
.get_matches_lower_bound(),<=,3);
458 TEST_REL(mymset
.get_matches_upper_bound(),>=,3);
459 TEST_REL(mymset
.get_matches_upper_bound(),<=,6);
460 TEST_REL(mymset
.get_matches_estimated(),>,0);
461 TEST_REL(mymset
.get_matches_estimated(),<=,6);
462 TEST_REL(mymset
.get_uncollapsed_matches_lower_bound(),>=,1);
463 TEST_REL(mymset
.get_uncollapsed_matches_lower_bound(),<=,3);
464 TEST_REL(mymset
.get_uncollapsed_matches_upper_bound(),>=,3);
465 TEST_REL(mymset
.get_uncollapsed_matches_upper_bound(),<=,6);
466 TEST_REL(mymset
.get_uncollapsed_matches_estimated(),>,0);
467 TEST_REL(mymset
.get_uncollapsed_matches_estimated(),<=,6);
469 // Check that the bounds are appropriate if a percentage cutoff is in
470 // use. Set a 1% threshold so we don't actually discard anything.
471 enquire
.set_collapse_key(Xapian::BAD_VALUENO
);
472 enquire
.set_cutoff(1);
473 mymset
= enquire
.get_mset(0, 1, 0, &myfunctor
);
474 TEST_EQUAL(mymset
.size(), 1);
475 TEST_REL(mymset
.get_matches_lower_bound(),>=,1);
476 TEST_REL(mymset
.get_matches_lower_bound(),<=,3);
477 TEST_REL(mymset
.get_matches_upper_bound(),>=,3);
478 TEST_REL(mymset
.get_matches_upper_bound(),<=,6);
479 TEST_REL(mymset
.get_matches_estimated(),>,0);
480 TEST_REL(mymset
.get_matches_estimated(),<=,6);
481 TEST_REL(mymset
.get_uncollapsed_matches_lower_bound(),>=,1);
482 TEST_REL(mymset
.get_uncollapsed_matches_lower_bound(),<=,3);
483 TEST_REL(mymset
.get_uncollapsed_matches_upper_bound(),>=,3);
484 TEST_REL(mymset
.get_uncollapsed_matches_upper_bound(),<=,6);
485 TEST_REL(mymset
.get_uncollapsed_matches_estimated(),>,0);
486 TEST_REL(mymset
.get_uncollapsed_matches_estimated(),<=,6);
488 // And now with both a collapse key and percentage cutoff.
489 enquire
.set_collapse_key(99);
490 mymset
= enquire
.get_mset(0, 1, 0, &myfunctor
);
491 TEST_EQUAL(mymset
.size(), 1);
492 TEST_REL(mymset
.get_matches_lower_bound(),>=,1);
493 TEST_REL(mymset
.get_matches_lower_bound(),<=,3);
494 TEST_REL(mymset
.get_matches_upper_bound(),>=,3);
495 TEST_REL(mymset
.get_matches_upper_bound(),<=,6);
496 TEST_REL(mymset
.get_matches_estimated(),>,0);
497 TEST_REL(mymset
.get_matches_estimated(),<=,6);
498 TEST_REL(mymset
.get_uncollapsed_matches_lower_bound(),>=,1);
499 TEST_REL(mymset
.get_uncollapsed_matches_lower_bound(),<=,3);
500 TEST_REL(mymset
.get_uncollapsed_matches_upper_bound(),>=,3);
501 TEST_REL(mymset
.get_uncollapsed_matches_upper_bound(),<=,6);
502 TEST_REL(mymset
.get_uncollapsed_matches_estimated(),>,0);
503 TEST_REL(mymset
.get_uncollapsed_matches_estimated(),<=,6);
508 // Test Xapian::MatchDecider functor used as a match spy.
509 DEFINE_TESTCASE(matchdecider2
, backend
&& !remote
) {
510 Xapian::Database
db(get_database("apitest_simpledata"));
511 Xapian::Enquire
enquire(db
);
512 enquire
.set_query(Xapian::Query("this"));
514 myMatchDecider myfunctor
;
516 Xapian::MSet mymset
= enquire
.get_mset(0, 100, 0, NULL
, &myfunctor
);
518 vector
<bool> docid_checked(db
.get_lastdocid());
520 // Check that we get the expected number of matches, and that they
521 // satisfy the condition.
522 Xapian::MSetIterator i
= mymset
.begin();
523 TEST(i
!= mymset
.end());
524 TEST_EQUAL(mymset
.size(), 3);
525 for ( ; i
!= mymset
.end(); ++i
) {
526 const Xapian::Document
doc(i
.get_document());
527 TEST(myfunctor(doc
));
528 docid_checked
[*i
] = true;
531 // Check that the other documents don't satisfy the condition.
532 for (Xapian::docid did
= 1; did
< docid_checked
.size(); ++did
) {
533 if (!docid_checked
[did
]) {
534 TEST(!myfunctor(db
.get_document(did
)));
541 class myMatchDecider2
: public Xapian::MatchDecider
{
543 bool operator()(const Xapian::Document
&doc
) const {
544 // Note that this is not recommended usage of get_data()
545 return doc
.get_data().find("We produce") == string::npos
;
550 // Regression test for lower bound using functor, sorting and collapsing.
551 DEFINE_TESTCASE(matchdecider3
, backend
&& !remote
) {
552 Xapian::Database
db(get_database("etext"));
553 Xapian::Enquire
enquire(db
);
554 enquire
.set_query(Xapian::Query(""));
555 enquire
.set_collapse_key(12);
556 enquire
.set_sort_by_value(11, true);
558 myMatchDecider2 myfunctor
;
560 Xapian::MSet mset1
= enquire
.get_mset(0, 2, 0, NULL
, &myfunctor
);
561 Xapian::MSet mset2
= enquire
.get_mset(0, 1000, 0, NULL
, &myfunctor
);
563 // mset2 should contain all the hits, so the statistics should be exact.
564 TEST_EQUAL(mset2
.get_matches_estimated(), mset2
.size());
565 TEST_EQUAL(mset2
.get_matches_lower_bound(), mset2
.get_matches_estimated());
566 TEST_EQUAL(mset2
.get_matches_estimated(), mset2
.get_matches_upper_bound());
568 TEST_REL(mset2
.get_uncollapsed_matches_lower_bound(),<=,mset2
.get_uncollapsed_matches_estimated());
569 TEST_REL(mset2
.get_uncollapsed_matches_estimated(),<=,mset2
.get_uncollapsed_matches_upper_bound());
571 // Check that the lower bound in mset1 is not greater than the known
572 // number of hits. This failed until revision 10811.
573 TEST_REL(mset1
.get_matches_lower_bound(),<=,mset2
.size());
575 // Check that the bounds for mset1 make sense.
576 TEST_REL(mset1
.get_matches_lower_bound(),<=,mset1
.get_matches_estimated());
577 TEST_REL(mset1
.get_matches_estimated(),<=,mset1
.get_matches_upper_bound());
578 TEST_REL(mset1
.size(),<=,mset1
.get_matches_upper_bound());
580 TEST_REL(mset1
.get_uncollapsed_matches_lower_bound(),<=,mset1
.get_uncollapsed_matches_estimated());
581 TEST_REL(mset1
.get_uncollapsed_matches_estimated(),<=,mset1
.get_uncollapsed_matches_upper_bound());
583 // The uncollapsed match would match all documents but the one the
584 // matchdecider rejects.
585 TEST_REL(mset1
.get_uncollapsed_matches_upper_bound(),>=,db
.get_doccount() - 1);
586 TEST_REL(mset1
.get_uncollapsed_matches_upper_bound(),<=,db
.get_doccount());
587 TEST_REL(mset2
.get_uncollapsed_matches_upper_bound(),>=,db
.get_doccount() - 1);
588 TEST_REL(mset2
.get_uncollapsed_matches_upper_bound(),<=,db
.get_doccount());
593 // tests that mset iterators on msets compare correctly.
594 DEFINE_TESTCASE(msetiterator1
, backend
) {
595 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
596 enquire
.set_query(Xapian::Query("this"));
597 Xapian::MSet mymset
= enquire
.get_mset(0, 2);
599 Xapian::MSetIterator j
;
601 Xapian::MSetIterator k
= mymset
.end();
602 Xapian::MSetIterator
l(j
);
603 Xapian::MSetIterator
m(k
);
604 Xapian::MSetIterator n
= mymset
.begin();
605 Xapian::MSetIterator o
= mymset
.begin();
606 TEST_NOT_EQUAL(j
, k
);
607 TEST_NOT_EQUAL(l
, m
);
617 TEST_NOT_EQUAL(j
, k
);
618 TEST_NOT_EQUAL(k
, l
);
619 TEST_NOT_EQUAL(k
, m
);
620 TEST_NOT_EQUAL(k
, o
);
624 TEST_NOT_EQUAL(j
, k
);
625 TEST_NOT_EQUAL(k
, l
);
630 TEST_NOT_EQUAL(n
, l
);
632 TEST_NOT_EQUAL(n
, mymset
.begin());
633 TEST_EQUAL(n
, mymset
.end());
638 // tests that mset iterators on empty msets compare equal.
639 DEFINE_TESTCASE(msetiterator2
, backend
) {
640 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
641 enquire
.set_query(Xapian::Query("this"));
642 Xapian::MSet mymset
= enquire
.get_mset(0, 0);
644 Xapian::MSetIterator j
= mymset
.begin();
645 Xapian::MSetIterator k
= mymset
.end();
646 Xapian::MSetIterator
l(j
);
647 Xapian::MSetIterator
m(k
);
658 // tests that begin().get_document() works when first != 0
659 DEFINE_TESTCASE(msetiterator3
, backend
) {
660 Xapian::Database
mydb(get_database("apitest_simpledata"));
661 Xapian::Enquire
enquire(mydb
);
662 enquire
.set_query(Xapian::Query("this"));
664 Xapian::MSet mymset
= enquire
.get_mset(2, 10);
666 TEST(!mymset
.empty());
667 Xapian::Document
doc(mymset
.begin().get_document());
668 TEST(!doc
.get_data().empty());
673 // tests that eset iterators on empty esets compare equal.
674 DEFINE_TESTCASE(esetiterator1
, backend
) {
675 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
676 enquire
.set_query(Xapian::Query("this"));
678 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
679 TEST(mymset
.size() >= 2);
682 Xapian::MSetIterator i
= mymset
.begin();
683 myrset
.add_document(*i
);
684 myrset
.add_document(*(++i
));
686 Xapian::ESet myeset
= enquire
.get_eset(2, myrset
);
687 Xapian::ESetIterator j
;
689 Xapian::ESetIterator k
= myeset
.end();
690 Xapian::ESetIterator
l(j
);
691 Xapian::ESetIterator
m(k
);
692 Xapian::ESetIterator n
= myeset
.begin();
694 TEST_NOT_EQUAL(j
, k
);
695 TEST_NOT_EQUAL(l
, m
);
704 TEST_NOT_EQUAL(j
, k
);
705 TEST_NOT_EQUAL(k
, l
);
706 TEST_NOT_EQUAL(k
, m
);
708 TEST_NOT_EQUAL(j
, k
);
709 TEST_NOT_EQUAL(k
, l
);
714 TEST_NOT_EQUAL(n
, l
);
716 TEST_NOT_EQUAL(n
, myeset
.begin());
717 TEST_EQUAL(n
, myeset
.end());
722 // tests that eset iterators on empty esets compare equal.
723 DEFINE_TESTCASE(esetiterator2
, backend
) {
724 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
725 enquire
.set_query(Xapian::Query("this"));
727 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
728 TEST(mymset
.size() >= 2);
731 Xapian::MSetIterator i
= mymset
.begin();
732 myrset
.add_document(*i
);
733 myrset
.add_document(*(++i
));
735 Xapian::ESet myeset
= enquire
.get_eset(0, myrset
);
736 Xapian::ESetIterator j
= myeset
.begin();
737 Xapian::ESetIterator k
= myeset
.end();
738 Xapian::ESetIterator
l(j
);
739 Xapian::ESetIterator
m(k
);
750 // tests the collapse-on-key
751 DEFINE_TESTCASE(collapsekey1
, backend
) {
752 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
753 enquire
.set_query(Xapian::Query("this"));
755 Xapian::MSet mymset1
= enquire
.get_mset(0, 100);
756 Xapian::doccount mymsize1
= mymset1
.size();
758 for (Xapian::valueno value_no
= 1; value_no
< 7; ++value_no
) {
759 enquire
.set_collapse_key(value_no
);
760 Xapian::MSet mymset
= enquire
.get_mset(0, 100);
762 TEST_AND_EXPLAIN(mymsize1
> mymset
.size(),
763 "Had no fewer items when performing collapse: don't know whether it worked.");
765 map
<string
, Xapian::docid
> values
;
766 Xapian::MSetIterator i
= mymset
.begin();
767 for ( ; i
!= mymset
.end(); ++i
) {
768 string value
= i
.get_document().get_value(value_no
);
769 TEST(values
[value
] == 0 || value
.empty());
777 // tests that collapse-on-key modifies the predicted bounds for the number of
778 // matches appropriately.
779 DEFINE_TESTCASE(collapsekey2
, backend
) {
780 SKIP_TEST("Don't have a suitable database currently");
781 // FIXME: this needs an appropriate database creating, but that's quite
782 // subtle to do it seems.
783 Xapian::Enquire
enquire(get_database("apitest_simpledata2"));
784 enquire
.set_query(Xapian::Query("this"));
786 Xapian::MSet mset1
= enquire
.get_mset(0, 1);
788 // Test that if no duplicates are found, then the upper bound remains
789 // unchanged and the lower bound drops.
791 enquire
.set_query(Xapian::Query("this"));
792 Xapian::valueno value_no
= 3;
793 enquire
.set_collapse_key(value_no
);
794 Xapian::MSet mset
= enquire
.get_mset(0, 1);
796 TEST_REL(mset
.get_matches_lower_bound(),<,mset1
.get_matches_lower_bound());
797 TEST_EQUAL(mset
.get_matches_upper_bound(), mset1
.get_matches_upper_bound());
803 // tests that collapse-on-key modifies the predicted bounds for the number of
804 // matches appropriately.
805 DEFINE_TESTCASE(collapsekey3
, backend
) {
806 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
807 enquire
.set_query(Xapian::Query("this"));
809 Xapian::MSet mymset1
= enquire
.get_mset(0, 3);
811 for (Xapian::valueno value_no
= 1; value_no
< 7; ++value_no
) {
812 enquire
.set_collapse_key(value_no
);
813 Xapian::MSet mymset
= enquire
.get_mset(0, 3);
815 TEST_AND_EXPLAIN(mymset1
.get_matches_lower_bound() > mymset
.get_matches_lower_bound(),
816 "Lower bound was not lower when performing collapse: don't know whether it worked.");
817 TEST_AND_EXPLAIN(mymset1
.get_matches_upper_bound() > mymset
.get_matches_upper_bound(),
818 "Upper bound was not lower when performing collapse: don't know whether it worked.");
820 map
<string
, Xapian::docid
> values
;
821 Xapian::MSetIterator i
= mymset
.begin();
822 for ( ; i
!= mymset
.end(); ++i
) {
823 string value
= i
.get_document().get_value(value_no
);
824 TEST(values
[value
] == 0 || value
.empty());
829 // Test that if the collapse value is always empty, then the upper bound
830 // remains unchanged, and the lower bound is the same or lower (it can be
831 // lower because the matcher counts the number of documents with empty
832 // collapse keys, but may have rejected a document because its weight is
833 // too low for the proto-MSet before it even looks at its collapse key).
835 Xapian::valueno value_no
= 1000;
836 enquire
.set_collapse_key(value_no
);
837 Xapian::MSet mymset
= enquire
.get_mset(0, 3);
839 TEST(mymset
.get_matches_lower_bound() <= mymset1
.get_matches_lower_bound());
840 TEST_EQUAL(mymset
.get_matches_upper_bound(), mymset1
.get_matches_upper_bound());
842 map
<string
, Xapian::docid
> values
;
843 Xapian::MSetIterator i
= mymset
.begin();
844 for ( ; i
!= mymset
.end(); ++i
) {
845 string value
= i
.get_document().get_value(value_no
);
846 TEST(values
[value
] == 0 || value
.empty());
854 // tests that collapse-on-key modifies the predicted bounds for the number of
855 // matches appropriately even when no results are requested.
856 DEFINE_TESTCASE(collapsekey4
, backend
) {
857 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
858 enquire
.set_query(Xapian::Query("this"));
860 Xapian::MSet mymset1
= enquire
.get_mset(0, 0);
862 for (Xapian::valueno value_no
= 1; value_no
< 7; ++value_no
) {
863 enquire
.set_collapse_key(value_no
);
864 Xapian::MSet mymset
= enquire
.get_mset(0, 0);
866 TEST_AND_EXPLAIN(mymset
.get_matches_lower_bound() == 1,
867 "Lower bound was not 1 when performing collapse but not asking for any results.");
868 TEST_AND_EXPLAIN(mymset1
.get_matches_upper_bound() == mymset
.get_matches_upper_bound(),
869 "Upper bound was changed when performing collapse but not asking for any results.");
871 map
<string
, Xapian::docid
> values
;
872 Xapian::MSetIterator i
= mymset
.begin();
873 for ( ; i
!= mymset
.end(); ++i
) {
874 string value
= i
.get_document().get_value(value_no
);
875 TEST(values
[value
] == 0 || value
.empty());
883 // test for keepalives
884 DEFINE_TESTCASE(keepalive1
, remote
) {
885 Xapian::Database
db(get_remote_database("apitest_simpledata", 5000));
887 /* Test that keep-alives work */
888 for (int i
= 0; i
< 10; ++i
) {
892 Xapian::Enquire
enquire(db
);
893 enquire
.set_query(Xapian::Query("word"));
894 enquire
.get_mset(0, 10);
896 /* Test that things break without keepalives */
898 enquire
.set_query(Xapian::Query("word"));
899 TEST_EXCEPTION(Xapian::NetworkError
,
900 enquire
.get_mset(0, 10));
905 // test that iterating through all terms in a database works.
906 DEFINE_TESTCASE(allterms1
, backend
) {
907 Xapian::Database
db(get_database("apitest_allterms"));
908 Xapian::TermIterator ati
= db
.allterms_begin();
909 TEST(ati
!= db
.allterms_end());
910 TEST_EQUAL(*ati
, "one");
911 TEST_EQUAL(ati
.get_termfreq(), 1);
913 Xapian::TermIterator ati2
= ati
;
916 TEST(ati
!= db
.allterms_end());
918 tout
<< "*ati = '" << *ati
<< "'\n";
919 tout
<< "*ati.length = '" << (*ati
).length() << "'\n";
920 tout
<< "*ati == \"one\" = " << (*ati
== "one") << "\n";
921 tout
<< "*ati[3] = " << ((*ati
)[3]) << "\n";
922 tout
<< "*ati = '" << *ati
<< "'\n";
924 TEST(*ati
== "three");
925 TEST(ati
.get_termfreq() == 3);
928 TEST(ati2
!= db
.allterms_end());
929 TEST(*ati2
== "one");
930 TEST(ati2
.get_termfreq() == 1);
937 TEST(ati
!= db
.allterms_end());
939 TEST(ati
.get_termfreq() == 2);
942 TEST(ati2
!= db
.allterms_end());
943 TEST(*ati2
== "three");
944 TEST(ati2
.get_termfreq() == 3);
948 TEST(ati
== db
.allterms_end());
953 // test that iterating through all terms in two databases works.
954 DEFINE_TESTCASE(allterms2
, backend
) {
956 db
.add_database(get_database("apitest_allterms"));
957 db
.add_database(get_database("apitest_allterms2"));
958 Xapian::TermIterator ati
= db
.allterms_begin();
960 TEST(ati
!= db
.allterms_end());
961 TEST(*ati
== "five");
962 TEST(ati
.get_termfreq() == 2);
965 TEST(ati
!= db
.allterms_end());
966 TEST(*ati
== "four");
967 TEST(ati
.get_termfreq() == 1);
970 TEST(ati
!= db
.allterms_end());
972 TEST(ati
.get_termfreq() == 1);
975 TEST(ati
!= db
.allterms_end());
977 TEST(ati
.get_termfreq() == 3);
980 TEST(ati
!= db
.allterms_end());
981 TEST(*ati
== "three");
982 TEST(ati
.get_termfreq() == 3);
985 TEST(ati
!= db
.allterms_end());
987 TEST(ati
.get_termfreq() == 2);
990 TEST(ati
== db
.allterms_end());
995 // test that skip_to sets at_end (regression test)
996 DEFINE_TESTCASE(allterms3
, backend
) {
998 db
.add_database(get_database("apitest_allterms"));
999 Xapian::TermIterator ati
= db
.allterms_begin();
1001 ati
.skip_to(string("zzzzzz"));
1002 TEST(ati
== db
.allterms_end());
1007 // test that next ignores extra entries due to long posting lists being
1008 // chunked (regression test for quartz)
1009 DEFINE_TESTCASE(allterms4
, backend
) {
1010 // apitest_allterms4 contains 682 documents each containing just the word
1011 // "foo". 682 was the magic number which started to cause Quartz problems.
1012 Xapian::Database db
= get_database("apitest_allterms4");
1014 Xapian::TermIterator i
= db
.allterms_begin();
1015 TEST(i
!= db
.allterms_end());
1017 TEST(i
.get_termfreq() == 682);
1019 TEST(i
== db
.allterms_end());
1024 // test that skip_to with an exact match sets the current term (regression test
1026 DEFINE_TESTCASE(allterms5
, backend
) {
1027 Xapian::Database db
;
1028 db
.add_database(get_database("apitest_allterms"));
1029 Xapian::TermIterator ati
= db
.allterms_begin();
1030 ati
.skip_to("three");
1031 TEST(ati
!= db
.allterms_end());
1032 TEST_EQUAL(*ati
, "three");
1037 // test allterms iterators with prefixes
1038 DEFINE_TESTCASE(allterms6
, backend
) {
1039 Xapian::Database db
;
1040 db
.add_database(get_database("apitest_allterms"));
1041 db
.add_database(get_database("apitest_allterms2"));
1043 Xapian::TermIterator ati
= db
.allterms_begin("three");
1044 TEST(ati
!= db
.allterms_end("three"));
1045 TEST_EQUAL(*ati
, "three");
1046 ati
.skip_to("three");
1047 TEST(ati
!= db
.allterms_end("three"));
1048 TEST_EQUAL(*ati
, "three");
1050 TEST(ati
== db
.allterms_end("three"));
1052 ati
= db
.allterms_begin("thre");
1053 TEST(ati
!= db
.allterms_end("thre"));
1054 TEST_EQUAL(*ati
, "three");
1055 ati
.skip_to("three");
1056 TEST(ati
!= db
.allterms_end("thre"));
1057 TEST_EQUAL(*ati
, "three");
1059 TEST(ati
== db
.allterms_end("thre"));
1061 ati
= db
.allterms_begin("f");
1062 TEST(ati
!= db
.allterms_end("f"));
1063 TEST_EQUAL(*ati
, "five");
1064 TEST(ati
!= db
.allterms_end("f"));
1065 ati
.skip_to("three");
1066 TEST(ati
== db
.allterms_end("f"));
1068 ati
= db
.allterms_begin("f");
1069 TEST(ati
!= db
.allterms_end("f"));
1070 TEST_EQUAL(*ati
, "five");
1072 TEST(ati
!= db
.allterms_end("f"));
1073 TEST_EQUAL(*ati
, "four");
1075 TEST(ati
== db
.allterms_end("f"));
1077 ati
= db
.allterms_begin("absent");
1078 TEST(ati
== db
.allterms_end("absent"));
1083 // test that searching for a term with a special characters in it works
1084 DEFINE_TESTCASE(specialterms1
, backend
) {
1085 Xapian::Enquire
enquire(get_database("apitest_space"));
1086 Xapian::MSet mymset
;
1087 Xapian::doccount count
;
1088 Xapian::MSetIterator m
;
1089 Xapian::Stem
stemmer("english");
1091 enquire
.set_query(stemmer("new\nline"));
1092 mymset
= enquire
.get_mset(0, 10);
1093 TEST_MSET_SIZE(mymset
, 1);
1095 for (m
= mymset
.begin(); m
!= mymset
.end(); ++m
) ++count
;
1096 TEST_EQUAL(count
, 1);
1098 for (Xapian::valueno value_no
= 0; value_no
< 7; ++value_no
) {
1099 string value
= mymset
.begin().get_document().get_value(value_no
);
1100 TEST_NOT_EQUAL(value
, "");
1101 if (value_no
== 0) {
1102 TEST(value
.size() > 263);
1103 TEST_EQUAL(static_cast<unsigned char>(value
[262]), 255);
1104 for (int k
= 0; k
< 256; k
++) {
1105 TEST_EQUAL(static_cast<unsigned char>(value
[k
+7]), k
);
1110 enquire
.set_query(stemmer(string("big\0zero", 8)));
1111 mymset
= enquire
.get_mset(0, 10);
1112 TEST_MSET_SIZE(mymset
, 1);
1114 for (m
= mymset
.begin(); m
!= mymset
.end(); ++m
) ++count
;
1115 TEST_EQUAL(count
, 1);
1120 // test that terms with a special characters in appear correctly when iterating
1122 DEFINE_TESTCASE(specialterms2
, backend
) {
1123 Xapian::Database
db(get_database("apitest_space"));
1125 // Check the terms are all as expected (after stemming) and that allterms
1126 // copes with iterating over them.
1127 Xapian::TermIterator t
;
1128 t
= db
.allterms_begin();
1129 TEST_EQUAL(*t
, "back\\slash"); ++t
; TEST_NOT_EQUAL(t
, db
.allterms_end());
1130 TEST_EQUAL(*t
, string("big\0zero", 8)); ++t
; TEST_NOT_EQUAL(t
, db
.allterms_end());
1131 TEST_EQUAL(*t
, "new\nlin"); ++t
; TEST_NOT_EQUAL(t
, db
.allterms_end());
1132 TEST_EQUAL(*t
, "one\x01on"); ++t
; TEST_NOT_EQUAL(t
, db
.allterms_end());
1133 TEST_EQUAL(*t
, "space man"); ++t
; TEST_NOT_EQUAL(t
, db
.allterms_end());
1134 TEST_EQUAL(*t
, "tab\tbi"); ++t
; TEST_NOT_EQUAL(t
, db
.allterms_end());
1135 TEST_EQUAL(*t
, "tu\x02tu"); ++t
; TEST_EQUAL(t
, db
.allterms_end());
1137 // Now check that skip_to exactly a term containing a zero byte works.
1138 // This is a regression test for flint and quartz - an Assert() used to
1139 // fire in debug builds (the Assert was wrong - the actual code handled
1141 t
= db
.allterms_begin();
1142 t
.skip_to(string("big\0zero", 8));
1143 TEST_NOT_EQUAL(t
, db
.allterms_end());
1144 TEST_EQUAL(*t
, string("big\0zero", 8));
1149 // test that rsets behave correctly with multiDBs
1150 DEFINE_TESTCASE(rsetmultidb2
, backend
&& !multi
) {
1151 Xapian::Database
mydb1(get_database("apitest_rset", "apitest_simpledata2"));
1152 Xapian::Database
mydb2(get_database("apitest_rset"));
1153 mydb2
.add_database(get_database("apitest_simpledata2"));
1155 Xapian::Enquire
enquire1(mydb1
);
1156 Xapian::Enquire
enquire2(mydb2
);
1158 Xapian::Query myquery
= query("is");
1160 enquire1
.set_query(myquery
);
1161 enquire2
.set_query(myquery
);
1163 Xapian::RSet myrset1
;
1164 Xapian::RSet myrset2
;
1165 myrset1
.add_document(4);
1166 myrset2
.add_document(2);
1168 Xapian::MSet mymset1a
= enquire1
.get_mset(0, 10);
1169 Xapian::MSet mymset1b
= enquire1
.get_mset(0, 10, &myrset1
);
1170 Xapian::MSet mymset2a
= enquire2
.get_mset(0, 10);
1171 Xapian::MSet mymset2b
= enquire2
.get_mset(0, 10, &myrset2
);
1173 mset_expect_order(mymset1a
, 4, 3);
1174 mset_expect_order(mymset1b
, 4, 3);
1175 mset_expect_order(mymset2a
, 2, 5);
1176 mset_expect_order(mymset2b
, 2, 5);
1178 TEST(mset_range_is_same_weights(mymset1a
, 0, mymset2a
, 0, 2));
1179 TEST(mset_range_is_same_weights(mymset1b
, 0, mymset2b
, 0, 2));
1180 TEST_NOT_EQUAL(mymset1a
, mymset1b
);
1181 TEST_NOT_EQUAL(mymset2a
, mymset2b
);
1186 // tests an expand across multiple databases
1187 DEFINE_TESTCASE(multiexpand1
, backend
&& !multi
) {
1188 Xapian::Database
mydb1(get_database("apitest_simpledata", "apitest_simpledata2"));
1189 Xapian::Enquire
enquire1(mydb1
);
1191 Xapian::Database
mydb2(get_database("apitest_simpledata"));
1192 mydb2
.add_database(get_database("apitest_simpledata2"));
1193 Xapian::Enquire
enquire2(mydb2
);
1195 // make simple equivalent rsets, with a document from each database in each.
1198 rset1
.add_document(1);
1199 rset1
.add_document(7);
1200 rset2
.add_document(1);
1201 rset2
.add_document(2);
1203 // Retrieve all the ESet results in each of the three setups:
1205 // This is the single database one.
1206 Xapian::ESet eset1
= enquire1
.get_eset(1000, rset1
);
1208 // This is the multi database with approximation
1209 Xapian::ESet eset2
= enquire2
.get_eset(1000, rset2
);
1211 // This is the multi database without approximation
1212 Xapian::ESet eset3
= enquire2
.get_eset(1000, rset2
, Xapian::Enquire::USE_EXACT_TERMFREQ
);
1214 TEST_EQUAL(eset1
.size(), eset3
.size());
1216 Xapian::ESetIterator i
= eset1
.begin();
1217 Xapian::ESetIterator j
= eset3
.begin();
1218 while (i
!= eset1
.end() && j
!= eset3
.end()) {
1220 TEST_EQUAL(i
.get_weight(), j
.get_weight());
1224 TEST(i
== eset1
.end());
1225 TEST(j
== eset3
.end());
1227 bool eset1_eq_eset2
= true;
1230 while (i
!= eset1
.end() && j
!= eset2
.end()) {
1231 if (i
.get_weight() != j
.get_weight()) {
1232 eset1_eq_eset2
= false;
1238 TEST(!eset1_eq_eset2
);
1243 // tests that opening a non-existent postlist returns an empty list
1244 DEFINE_TESTCASE(postlist1
, backend
) {
1245 Xapian::Database
db(get_database("apitest_simpledata"));
1247 TEST_EQUAL(db
.postlist_begin("rosebud"), db
.postlist_end("rosebud"));
1249 string s
= "let_us_see_if_we_can_break_it_with_a_really_really_long_term.";
1250 for (int i
= 0; i
< 8; ++i
) {
1252 TEST_EQUAL(db
.postlist_begin(s
), db
.postlist_end(s
));
1255 // A regression test (no, really!)
1256 TEST_NOT_EQUAL(db
.postlist_begin("a"), db
.postlist_end("a"));
1261 // tests that a Xapian::PostingIterator works as an STL iterator
1262 DEFINE_TESTCASE(postlist2
, backend
) {
1263 Xapian::Database
db(get_database("apitest_simpledata"));
1264 Xapian::PostingIterator p
;
1265 p
= db
.postlist_begin("this");
1266 Xapian::PostingIterator pend
= db
.postlist_end("this");
1268 TEST(p
.get_description() != "PostingIterator()");
1270 // test operator= creates a copy which compares equal
1271 Xapian::PostingIterator p_copy
= p
;
1272 TEST_EQUAL(p
, p_copy
);
1274 TEST(p_copy
.get_description() != "PostingIterator()");
1276 // test copy constructor creates a copy which compares equal
1277 Xapian::PostingIterator
p_clone(p
);
1278 TEST_EQUAL(p
, p_clone
);
1280 TEST(p_clone
.get_description() != "PostingIterator()");
1282 vector
<Xapian::docid
> v(p
, pend
);
1284 p
= db
.postlist_begin("this");
1285 pend
= db
.postlist_end("this");
1286 vector
<Xapian::docid
>::const_iterator i
;
1287 for (i
= v
.begin(); i
!= v
.end(); ++i
) {
1288 TEST_NOT_EQUAL(p
, pend
);
1292 TEST_EQUAL(p
, pend
);
1294 TEST_STRINGS_EQUAL(p
.get_description(), "PostingIterator()");
1295 TEST_STRINGS_EQUAL(pend
.get_description(), "PostingIterator()");
1300 // tests that a Xapian::PostingIterator still works when the DB is deleted
1301 DEFINE_TESTCASE(postlist3
, backend
) {
1302 Xapian::PostingIterator u
;
1304 Xapian::Database
db_temp(get_database("apitest_simpledata"));
1305 u
= db_temp
.postlist_begin("this");
1308 Xapian::Database
db(get_database("apitest_simpledata"));
1309 Xapian::PostingIterator p
= db
.postlist_begin("this");
1310 Xapian::PostingIterator pend
= db
.postlist_end("this");
1321 DEFINE_TESTCASE(postlist4
, backend
) {
1322 Xapian::Database
db(get_database("apitest_simpledata"));
1323 Xapian::PostingIterator i
= db
.postlist_begin("this");
1325 i
.skip_to(999999999);
1326 TEST(i
== db
.postlist_end("this"));
1330 // tests long postlists
1331 DEFINE_TESTCASE(postlist5
, backend
) {
1332 Xapian::Database
db(get_database("apitest_manydocs"));
1333 // Allow for databases which don't support length
1334 if (db
.get_avlength() != 1)
1335 TEST_EQUAL_DOUBLE(db
.get_avlength(), 4);
1336 Xapian::PostingIterator i
= db
.postlist_begin("this");
1338 while (i
!= db
.postlist_end("this")) {
1347 // tests document length in postlists
1348 DEFINE_TESTCASE(postlist6
, backend
) {
1349 Xapian::Database
db(get_database("apitest_simpledata"));
1350 Xapian::PostingIterator i
= db
.postlist_begin("this");
1351 TEST(i
!= db
.postlist_end("this"));
1352 while (i
!= db
.postlist_end("this")) {
1353 TEST_EQUAL(i
.get_doclength(), db
.get_doclength(*i
));
1354 TEST_EQUAL(i
.get_unique_terms(), db
.get_unique_terms(*i
));
1355 TEST_REL(i
.get_wdf(),<=,i
.get_doclength());
1356 TEST_REL(1,<=,i
.get_unique_terms());
1357 // The next two aren't necessarily true if there are terms with wdf=0
1358 // in the document, but that isn't the case here.
1359 TEST_REL(i
.get_unique_terms(),<=,i
.get_doclength());
1360 TEST_REL(i
.get_wdf() + i
.get_unique_terms() - 1,<=,i
.get_doclength());
1366 // tests collection frequency
1367 DEFINE_TESTCASE(collfreq1
, backend
) {
1368 Xapian::Database
db(get_database("apitest_simpledata"));
1370 TEST_EQUAL(db
.get_collection_freq("this"), 11);
1371 TEST_EQUAL(db
.get_collection_freq("first"), 1);
1372 TEST_EQUAL(db
.get_collection_freq("last"), 0);
1373 TEST_EQUAL(db
.get_collection_freq("word"), 9);
1375 Xapian::Database
db1(get_database("apitest_simpledata", "apitest_simpledata2"));
1376 Xapian::Database
db2(get_database("apitest_simpledata"));
1377 db2
.add_database(get_database("apitest_simpledata2"));
1379 TEST_EQUAL(db1
.get_collection_freq("this"), 15);
1380 TEST_EQUAL(db1
.get_collection_freq("first"), 1);
1381 TEST_EQUAL(db1
.get_collection_freq("last"), 0);
1382 TEST_EQUAL(db1
.get_collection_freq("word"), 11);
1383 TEST_EQUAL(db2
.get_collection_freq("this"), 15);
1384 TEST_EQUAL(db2
.get_collection_freq("first"), 1);
1385 TEST_EQUAL(db2
.get_collection_freq("last"), 0);
1386 TEST_EQUAL(db2
.get_collection_freq("word"), 11);
1391 // Regression test for split msets being incorrect when sorting
1392 DEFINE_TESTCASE(sortvalue1
, backend
) {
1393 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1394 enquire
.set_query(Xapian::Query("this"));
1396 for (int pass
= 1; pass
<= 2; ++pass
) {
1397 for (Xapian::valueno value_no
= 1; value_no
< 7; ++value_no
) {
1398 tout
<< "Sorting on value " << value_no
<< endl
;
1399 enquire
.set_sort_by_value(value_no
, true);
1400 Xapian::MSet allbset
= enquire
.get_mset(0, 100);
1401 Xapian::MSet partbset1
= enquire
.get_mset(0, 3);
1402 Xapian::MSet partbset2
= enquire
.get_mset(3, 97);
1403 TEST_EQUAL(allbset
.size(), partbset1
.size() + partbset2
.size());
1407 Xapian::MSetIterator i
, j
;
1408 j
= allbset
.begin();
1409 for (i
= partbset1
.begin(); i
!= partbset1
.end(); ++i
) {
1410 tout
<< "Entry " << n
<< ": " << *i
<< " | " << *j
<< endl
;
1411 TEST(j
!= allbset
.end());
1412 if (*i
!= *j
) ok
= false;
1417 for (i
= partbset2
.begin(); i
!= partbset2
.end(); ++i
) {
1418 tout
<< "Entry " << n
<< ": " << *i
<< " | " << *j
<< endl
;
1419 TEST(j
!= allbset
.end());
1420 if (*i
!= *j
) ok
= false;
1424 TEST(j
== allbset
.end());
1426 FAIL_TEST("Split msets aren't consistent with unsplit");
1428 enquire
.set_docid_order(Xapian::Enquire::DESCENDING
);
1434 // consistency check match - vary mset size and check results agree.
1435 // consistency1 will run on the remote backend, but it's particularly slow
1436 // with that, and testing it there doesn't actually improve the test
1438 DEFINE_TESTCASE(consistency1
, backend
&& !remote
) {
1439 Xapian::Database
db(get_database("etext"));
1440 Xapian::Enquire
enquire(db
);
1441 enquire
.set_query(Xapian::Query(Xapian::Query::OP_OR
, Xapian::Query("the"), Xapian::Query("sky")));
1442 Xapian::doccount lots
= 214;
1443 Xapian::MSet bigmset
= enquire
.get_mset(0, lots
);
1444 TEST_EQUAL(bigmset
.size(), lots
);
1446 for (Xapian::doccount start
= 0; start
< lots
; ++start
) {
1447 for (Xapian::doccount size
= 0; size
< lots
- start
; ++size
) {
1448 Xapian::MSet mset
= enquire
.get_mset(start
, size
);
1450 TEST_EQUAL(start
+ mset
.size(),
1451 min(start
+ size
, bigmset
.size()));
1453 // tout << start << mset.size() << bigmset.size() << endl;
1454 TEST(start
>= bigmset
.size());
1456 for (Xapian::doccount i
= 0; i
< mset
.size(); ++i
) {
1457 TEST_EQUAL(*mset
[i
], *bigmset
[start
+ i
]);
1458 TEST_EQUAL_DOUBLE(mset
[i
].get_weight(),
1459 bigmset
[start
+ i
].get_weight());
1464 catch (const Xapian::NetworkTimeoutError
&) {
1465 // consistency1 is a long test - may timeout with the remote backend...
1466 SKIP_TEST("Test taking too long");
1471 // tests that specifying a nonexistent input file throws an exception.
1472 DEFINE_TESTCASE(chertdatabaseopeningerror1
, chert
) {
1473 #ifdef XAPIAN_HAS_CHERT_BACKEND
1474 mkdir(".chert", 0755);
1476 TEST_EXCEPTION(Xapian::DatabaseOpeningError
,
1477 Xapian::Database(".chert/nosuchdirectory",
1478 Xapian::DB_BACKEND_CHERT
));
1479 TEST_EXCEPTION(Xapian::DatabaseOpeningError
,
1480 Xapian::WritableDatabase(".chert/nosuchdirectory",
1481 Xapian::DB_OPEN
|Xapian::DB_BACKEND_CHERT
));
1483 mkdir(".chert/emptydirectory", 0700);
1484 TEST_EXCEPTION(Xapian::DatabaseOpeningError
,
1485 Xapian::Database(".chert/emptydirectory",
1486 Xapian::DB_BACKEND_CHERT
));
1488 touch(".chert/somefile");
1489 TEST_EXCEPTION(Xapian::DatabaseOpeningError
,
1490 Xapian::Database(".chert/somefile",
1491 Xapian::DB_BACKEND_CHERT
));
1492 TEST_EXCEPTION(Xapian::DatabaseOpeningError
,
1493 Xapian::WritableDatabase(".chert/somefile",
1494 Xapian::DB_OPEN
|Xapian::DB_BACKEND_CHERT
));
1495 TEST_EXCEPTION(Xapian::DatabaseCreateError
,
1496 Xapian::WritableDatabase(".chert/somefile",
1497 Xapian::DB_CREATE
|Xapian::DB_BACKEND_CHERT
));
1498 TEST_EXCEPTION(Xapian::DatabaseCreateError
,
1499 Xapian::WritableDatabase(".chert/somefile",
1500 Xapian::DB_CREATE_OR_OPEN
|Xapian::DB_BACKEND_CHERT
));
1501 TEST_EXCEPTION(Xapian::DatabaseCreateError
,
1502 Xapian::WritableDatabase(".chert/somefile",
1503 Xapian::DB_CREATE_OR_OVERWRITE
|Xapian::DB_BACKEND_CHERT
));
1509 /// Test opening of a chert database
1510 DEFINE_TESTCASE(chertdatabaseopen1
, chert
) {
1511 #ifdef XAPIAN_HAS_CHERT_BACKEND
1512 const string dbdir
= ".chert/test_chertdatabaseopen1";
1513 mkdir(".chert", 0755);
1517 Xapian::WritableDatabase
wdb(dbdir
,
1518 Xapian::DB_CREATE
|Xapian::DB_BACKEND_CHERT
);
1519 TEST_EXCEPTION(Xapian::DatabaseLockError
,
1520 Xapian::WritableDatabase(dbdir
,
1521 Xapian::DB_OPEN
|Xapian::DB_BACKEND_CHERT
));
1522 Xapian::Database(dbdir
, Xapian::DB_BACKEND_CHERT
);
1527 Xapian::WritableDatabase
wdb(dbdir
,
1528 Xapian::DB_CREATE_OR_OPEN
|Xapian::DB_BACKEND_CHERT
);
1529 TEST_EXCEPTION(Xapian::DatabaseLockError
,
1530 Xapian::WritableDatabase(dbdir
,
1531 Xapian::DB_CREATE_OR_OVERWRITE
|Xapian::DB_BACKEND_CHERT
));
1532 Xapian::Database(dbdir
, Xapian::DB_BACKEND_CHERT
);
1537 Xapian::WritableDatabase
wdb(dbdir
,
1538 Xapian::DB_CREATE_OR_OVERWRITE
|Xapian::DB_BACKEND_CHERT
);
1539 TEST_EXCEPTION(Xapian::DatabaseLockError
,
1540 Xapian::WritableDatabase(dbdir
,
1541 Xapian::DB_CREATE_OR_OPEN
|Xapian::DB_BACKEND_CHERT
));
1542 Xapian::Database(dbdir
, Xapian::DB_BACKEND_CHERT
);
1546 TEST_EXCEPTION(Xapian::DatabaseCreateError
,
1547 Xapian::WritableDatabase(dbdir
,
1548 Xapian::DB_CREATE
|Xapian::DB_BACKEND_CHERT
));
1549 Xapian::WritableDatabase
wdb(dbdir
,
1550 Xapian::DB_CREATE_OR_OVERWRITE
|Xapian::DB_BACKEND_CHERT
);
1551 Xapian::Database(dbdir
, Xapian::DB_BACKEND_CHERT
);
1555 Xapian::WritableDatabase
wdb(dbdir
,
1556 Xapian::DB_CREATE_OR_OPEN
|Xapian::DB_BACKEND_CHERT
);
1557 Xapian::Database(dbdir
, Xapian::DB_BACKEND_CHERT
);
1561 Xapian::WritableDatabase
wdb(dbdir
,
1562 Xapian::DB_OPEN
|Xapian::DB_BACKEND_CHERT
);
1563 Xapian::Database(dbdir
, Xapian::DB_BACKEND_CHERT
);
1570 // feature test for Enquire:
1571 // set_sort_by_value
1572 // set_sort_by_value_then_relevance
1573 // set_sort_by_relevance_then_value
1574 // Prior to 1.2.17 and 1.3.2, order8 and order9 were swapped, and
1575 // set_sort_by_relevance_then_value was buggy, so this testcase now serves as
1576 // a regression test for that bug.
1577 DEFINE_TESTCASE(sortrel1
, backend
) {
1578 Xapian::Enquire
enquire(get_database("apitest_sortrel"));
1579 enquire
.set_sort_by_value(1, true);
1580 enquire
.set_query(Xapian::Query("woman"));
1582 const Xapian::docid order1
[] = { 1,2,3,4,5,6,7,8,9 };
1583 const Xapian::docid order2
[] = { 2,1,3,6,5,4,7,9,8 };
1584 const Xapian::docid order3
[] = { 3,2,1,6,5,4,9,8,7 };
1585 const Xapian::docid order4
[] = { 7,8,9,4,5,6,1,2,3 };
1586 const Xapian::docid order5
[] = { 9,8,7,6,5,4,3,2,1 };
1587 const Xapian::docid order6
[] = { 7,9,8,6,5,4,2,1,3 };
1588 const Xapian::docid order7
[] = { 7,9,8,6,5,4,2,1,3 };
1589 const Xapian::docid order8
[] = { 2,6,7,1,5,9,3,4,8 };
1590 const Xapian::docid order9
[] = { 7,6,2,9,5,1,8,4,3 };
1595 mset
= enquire
.get_mset(0, 10);
1596 TEST_EQUAL(mset
.size(), sizeof(order1
) / sizeof(Xapian::docid
));
1597 for (i
= 0; i
< sizeof(order1
) / sizeof(Xapian::docid
); ++i
) {
1598 TEST_EQUAL(*mset
[i
], order1
[i
]);
1601 enquire
.set_sort_by_value_then_relevance(1, true);
1603 mset
= enquire
.get_mset(0, 10);
1604 TEST_EQUAL(mset
.size(), sizeof(order2
) / sizeof(Xapian::docid
));
1605 for (i
= 0; i
< sizeof(order2
) / sizeof(Xapian::docid
); ++i
) {
1606 TEST_EQUAL(*mset
[i
], order2
[i
]);
1609 enquire
.set_sort_by_value(1, true);
1611 mset
= enquire
.get_mset(0, 10);
1612 TEST_EQUAL(mset
.size(), sizeof(order1
) / sizeof(Xapian::docid
));
1613 for (i
= 0; i
< sizeof(order1
) / sizeof(Xapian::docid
); ++i
) {
1614 TEST_EQUAL(*mset
[i
], order1
[i
]);
1617 enquire
.set_sort_by_value_then_relevance(1, true);
1618 enquire
.set_docid_order(Xapian::Enquire::DESCENDING
);
1620 mset
= enquire
.get_mset(0, 10);
1621 TEST_EQUAL(mset
.size(), sizeof(order2
) / sizeof(Xapian::docid
));
1622 for (i
= 0; i
< sizeof(order2
) / sizeof(Xapian::docid
); ++i
) {
1623 TEST_EQUAL(*mset
[i
], order2
[i
]);
1626 enquire
.set_sort_by_value(1, true);
1627 enquire
.set_docid_order(Xapian::Enquire::DESCENDING
);
1629 mset
= enquire
.get_mset(0, 10);
1630 TEST_EQUAL(mset
.size(), sizeof(order3
) / sizeof(Xapian::docid
));
1631 for (i
= 0; i
< sizeof(order3
) / sizeof(Xapian::docid
); ++i
) {
1632 TEST_EQUAL(*mset
[i
], order3
[i
]);
1635 enquire
.set_sort_by_value(1, false);
1636 enquire
.set_docid_order(Xapian::Enquire::ASCENDING
);
1637 mset
= enquire
.get_mset(0, 10);
1638 TEST_EQUAL(mset
.size(), sizeof(order4
) / sizeof(Xapian::docid
));
1639 for (i
= 0; i
< sizeof(order4
) / sizeof(Xapian::docid
); ++i
) {
1640 TEST_EQUAL(*mset
[i
], order4
[i
]);
1643 enquire
.set_sort_by_value(1, false);
1644 enquire
.set_docid_order(Xapian::Enquire::DESCENDING
);
1645 mset
= enquire
.get_mset(0, 10);
1646 TEST_EQUAL(mset
.size(), sizeof(order5
) / sizeof(Xapian::docid
));
1647 for (i
= 0; i
< sizeof(order5
) / sizeof(Xapian::docid
); ++i
) {
1648 TEST_EQUAL(*mset
[i
], order5
[i
]);
1651 enquire
.set_sort_by_value_then_relevance(1, false);
1652 enquire
.set_docid_order(Xapian::Enquire::ASCENDING
);
1653 mset
= enquire
.get_mset(0, 10);
1654 TEST_EQUAL(mset
.size(), sizeof(order6
) / sizeof(Xapian::docid
));
1655 for (i
= 0; i
< sizeof(order6
) / sizeof(Xapian::docid
); ++i
) {
1656 TEST_EQUAL(*mset
[i
], order6
[i
]);
1659 enquire
.set_sort_by_value_then_relevance(1, false);
1660 enquire
.set_docid_order(Xapian::Enquire::DESCENDING
);
1661 mset
= enquire
.get_mset(0, 10);
1662 TEST_EQUAL(mset
.size(), sizeof(order7
) / sizeof(Xapian::docid
));
1663 for (i
= 0; i
< sizeof(order7
) / sizeof(Xapian::docid
); ++i
) {
1664 TEST_EQUAL(*mset
[i
], order7
[i
]);
1667 enquire
.set_sort_by_relevance_then_value(1, true);
1668 enquire
.set_docid_order(Xapian::Enquire::ASCENDING
);
1669 mset
= enquire
.get_mset(0, 10);
1670 TEST_EQUAL(mset
.size(), sizeof(order8
) / sizeof(Xapian::docid
));
1671 for (i
= 0; i
< sizeof(order8
) / sizeof(Xapian::docid
); ++i
) {
1672 TEST_EQUAL(*mset
[i
], order8
[i
]);
1675 enquire
.set_sort_by_relevance_then_value(1, true);
1676 enquire
.set_docid_order(Xapian::Enquire::DESCENDING
);
1677 mset
= enquire
.get_mset(0, 10);
1678 TEST_EQUAL(mset
.size(), sizeof(order8
) / sizeof(Xapian::docid
));
1679 for (i
= 0; i
< sizeof(order8
) / sizeof(Xapian::docid
); ++i
) {
1680 TEST_EQUAL(*mset
[i
], order8
[i
]);
1683 enquire
.set_sort_by_relevance_then_value(1, false);
1684 enquire
.set_docid_order(Xapian::Enquire::ASCENDING
);
1685 mset
= enquire
.get_mset(0, 10);
1686 TEST_EQUAL(mset
.size(), sizeof(order9
) / sizeof(Xapian::docid
));
1687 for (i
= 0; i
< sizeof(order9
) / sizeof(Xapian::docid
); ++i
) {
1688 TEST_EQUAL(*mset
[i
], order9
[i
]);
1691 enquire
.set_sort_by_relevance_then_value(1, false);
1692 enquire
.set_docid_order(Xapian::Enquire::DESCENDING
);
1693 mset
= enquire
.get_mset(0, 10);
1694 TEST_EQUAL(mset
.size(), sizeof(order9
) / sizeof(Xapian::docid
));
1695 for (i
= 0; i
< sizeof(order9
) / sizeof(Xapian::docid
); ++i
) {
1696 TEST_EQUAL(*mset
[i
], order9
[i
]);
1702 // Test network stats and local stats give the same results.
1703 DEFINE_TESTCASE(netstats1
, remote
) {
1704 BackendManagerLocal local_manager
;
1705 local_manager
.set_datadir(test_driver::get_srcdir() + "/testdata/");
1707 const char * words
[] = { "paragraph", "word" };
1708 Xapian::Query
query(Xapian::Query::OP_OR
, words
, words
+ 2);
1709 const size_t MSET_SIZE
= 10;
1712 rset
.add_document(4);
1713 rset
.add_document(9);
1715 Xapian::MSet mset_alllocal
;
1717 Xapian::Database db
;
1718 db
.add_database(local_manager
.get_database("apitest_simpledata"));
1719 db
.add_database(local_manager
.get_database("apitest_simpledata2"));
1721 Xapian::Enquire
enq(db
);
1722 enq
.set_query(query
);
1723 mset_alllocal
= enq
.get_mset(0, MSET_SIZE
, &rset
);
1727 Xapian::Database db
;
1728 db
.add_database(local_manager
.get_database("apitest_simpledata"));
1729 db
.add_database(get_database("apitest_simpledata2"));
1731 Xapian::Enquire
enq(db
);
1732 enq
.set_query(query
);
1733 Xapian::MSet mset
= enq
.get_mset(0, MSET_SIZE
, &rset
);
1734 TEST_EQUAL(mset
.get_matches_lower_bound(), mset_alllocal
.get_matches_lower_bound());
1735 TEST_EQUAL(mset
.get_matches_upper_bound(), mset_alllocal
.get_matches_upper_bound());
1736 TEST_EQUAL(mset
.get_matches_estimated(), mset_alllocal
.get_matches_estimated());
1737 TEST_EQUAL(mset
.get_max_attained(), mset_alllocal
.get_max_attained());
1738 TEST_EQUAL(mset
.size(), mset_alllocal
.size());
1739 TEST(mset_range_is_same(mset
, 0, mset_alllocal
, 0, mset
.size()));
1743 Xapian::Database db
;
1744 db
.add_database(get_database("apitest_simpledata"));
1745 db
.add_database(local_manager
.get_database("apitest_simpledata2"));
1747 Xapian::Enquire
enq(db
);
1748 enq
.set_query(query
);
1749 Xapian::MSet mset
= enq
.get_mset(0, MSET_SIZE
, &rset
);
1750 TEST_EQUAL(mset
.get_matches_lower_bound(), mset_alllocal
.get_matches_lower_bound());
1751 TEST_EQUAL(mset
.get_matches_upper_bound(), mset_alllocal
.get_matches_upper_bound());
1752 TEST_EQUAL(mset
.get_matches_estimated(), mset_alllocal
.get_matches_estimated());
1753 TEST_EQUAL(mset
.get_max_attained(), mset_alllocal
.get_max_attained());
1754 TEST_EQUAL(mset
.size(), mset_alllocal
.size());
1755 TEST(mset_range_is_same(mset
, 0, mset_alllocal
, 0, mset
.size()));
1759 Xapian::Database db
;
1760 db
.add_database(get_database("apitest_simpledata"));
1761 db
.add_database(get_database("apitest_simpledata2"));
1763 Xapian::Enquire
enq(db
);
1764 enq
.set_query(query
);
1765 Xapian::MSet mset
= enq
.get_mset(0, MSET_SIZE
, &rset
);
1766 TEST_EQUAL(mset
.get_matches_lower_bound(), mset_alllocal
.get_matches_lower_bound());
1767 TEST_EQUAL(mset
.get_matches_upper_bound(), mset_alllocal
.get_matches_upper_bound());
1768 TEST_EQUAL(mset
.get_matches_estimated(), mset_alllocal
.get_matches_estimated());
1769 TEST_EQUAL(mset
.get_max_attained(), mset_alllocal
.get_max_attained());
1770 TEST_EQUAL(mset
.size(), mset_alllocal
.size());
1771 TEST(mset_range_is_same(mset
, 0, mset_alllocal
, 0, mset
.size()));
1777 // Coordinate matching - scores 1 for each matching term
1778 class MyWeight
: public Xapian::Weight
{
1779 double scale_factor
;
1782 MyWeight
* clone() const {
1783 return new MyWeight
;
1785 void init(double factor
) {
1786 scale_factor
= factor
;
1790 std::string
name() const { return "MyWeight"; }
1791 string
serialise() const { return string(); }
1792 MyWeight
* unserialise(const string
&) const { return new MyWeight
; }
1793 double get_sumpart(Xapian::termcount
, Xapian::termcount
) const {
1794 return scale_factor
;
1796 double get_sumpart(Xapian::termcount
, Xapian::termcount
, Xapian::termcount
) const {
1797 return scale_factor
;
1799 double get_maxpart() const { return scale_factor
; }
1801 double get_sumextra(Xapian::termcount
, Xapian::termcount
) const { return 0; }
1802 double get_maxextra() const { return 0; }
1805 // tests user weighting scheme.
1806 // Would work with remote if we registered the weighting scheme.
1807 // FIXME: do this so we also test that functionality...
1808 DEFINE_TESTCASE(userweight1
, backend
&& !remote
) {
1809 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1810 enquire
.set_weighting_scheme(MyWeight());
1811 const char * query
[] = { "this", "line", "paragraph", "rubbish" };
1812 enquire
.set_query(Xapian::Query(Xapian::Query::OP_OR
, query
,
1813 query
+ sizeof(query
) / sizeof(query
[0])));
1814 Xapian::MSet mymset1
= enquire
.get_mset(0, 100);
1815 // MyWeight scores 1 for each matching term, so the weight should equal
1816 // the number of matching terms.
1817 for (Xapian::MSetIterator i
= mymset1
.begin(); i
!= mymset1
.end(); ++i
) {
1818 Xapian::termcount matching_terms
= 0;
1819 Xapian::TermIterator t
= enquire
.get_matching_terms_begin(i
);
1820 while (t
!= enquire
.get_matching_terms_end(i
)) {
1824 TEST_EQUAL(i
.get_weight(), matching_terms
);
1830 // tests MatchAll queries
1831 // This is a regression test, which failed with assertion failures in
1832 // revision 9094. Also check that the results aren't ranked by relevance
1833 // (regression test for bug fixed in 1.0.9).
1834 DEFINE_TESTCASE(matchall1
, backend
) {
1835 Xapian::Database
db(get_database("apitest_simpledata"));
1836 Xapian::Enquire
enquire(db
);
1837 enquire
.set_query(Xapian::Query::MatchAll
);
1838 Xapian::MSet mset
= enquire
.get_mset(0, 10);
1839 TEST_EQUAL(mset
.get_matches_lower_bound(), db
.get_doccount());
1840 TEST_EQUAL(mset
.get_uncollapsed_matches_lower_bound(), db
.get_doccount());
1842 enquire
.set_query(Xapian::Query(Xapian::Query::OP_OR
,
1843 Xapian::Query("nosuchterm"),
1844 Xapian::Query::MatchAll
));
1845 mset
= enquire
.get_mset(0, 10);
1846 TEST_EQUAL(mset
.get_matches_lower_bound(), db
.get_doccount());
1847 TEST_EQUAL(mset
.get_uncollapsed_matches_lower_bound(), db
.get_doccount());
1849 // Check that the results aren't ranked by relevance (fixed in 1.0.9).
1850 TEST(mset
.size() > 1);
1851 TEST_EQUAL(mset
[mset
.size() - 1].get_weight(), 0);
1852 TEST_EQUAL(*mset
[0], 1);
1853 TEST_EQUAL(*mset
[mset
.size() - 1], mset
.size());
1858 // Test using a ValueSetMatchDecider
1859 DEFINE_TESTCASE(valuesetmatchdecider2
, backend
&& !remote
) {
1860 Xapian::Database
db(get_database("apitest_phrase"));
1861 Xapian::Enquire
enq(db
);
1862 enq
.set_query(Xapian::Query("leav"));
1864 Xapian::ValueSetMatchDecider
vsmd1(1, true);
1865 vsmd1
.add_value("n");
1866 Xapian::ValueSetMatchDecider
vsmd2(1, false);
1867 vsmd2
.add_value("n");
1869 Xapian::MSet mymset
= enq
.get_mset(0, 20);
1870 mset_expect_order(mymset
, 8, 6, 4, 5, 7, 10, 12, 11, 13, 9, 14);
1871 mymset
= enq
.get_mset(0, 20, 0, NULL
, &vsmd1
);
1872 mset_expect_order(mymset
, 6, 12);
1873 mymset
= enq
.get_mset(0, 20, 0, NULL
, &vsmd2
);
1874 mset_expect_order(mymset
, 8, 4, 5, 7, 10, 11, 13, 9, 14);