1 /* api_anydb.cc: tests which work with any backend
3 * Copyright 1999,2000,2001 BrightStation PLC
4 * Copyright 2002 Ananova Ltd
5 * Copyright 2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2015,2016 Olly Betts
6 * Copyright 2006,2008 Lemur Consulting Ltd
7 * Copyright 2011 Action Without Borders
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
27 #include "api_anydb.h"
32 #define XAPIAN_DEPRECATED(X) X
34 #include "backendmanager_local.h"
35 #include "testsuite.h"
36 #include "testutils.h"
45 print_mset_weights(const Xapian::MSet
&mset
)
47 Xapian::MSetIterator i
= mset
.begin();
48 for ( ; i
!= mset
.end(); ++i
) {
49 tout
<< " " << i
.get_weight();
54 print_mset_percentages(const Xapian::MSet
&mset
)
56 Xapian::MSetIterator i
= mset
.begin();
57 for ( ; i
!= mset
.end(); ++i
) {
58 tout
<< " " << mset
.convert_to_percent(i
);
63 query(Xapian::Query::op op
,
64 const string
& t1
= string(), const string
& t2
= string(),
65 const string
& t3
= string(), const string
& t4
= string(),
66 const string
& t5
= string(), const string
& t6
= string(),
67 const string
& t7
= string(), const string
& t8
= string(),
68 const string
& t9
= string(), const string
& t10
= string())
71 Xapian::Stem
stemmer("english");
72 if (!t1
.empty()) v
.push_back(stemmer(t1
));
73 if (!t2
.empty()) v
.push_back(stemmer(t2
));
74 if (!t3
.empty()) v
.push_back(stemmer(t3
));
75 if (!t4
.empty()) v
.push_back(stemmer(t4
));
76 if (!t5
.empty()) v
.push_back(stemmer(t5
));
77 if (!t6
.empty()) v
.push_back(stemmer(t6
));
78 if (!t7
.empty()) v
.push_back(stemmer(t7
));
79 if (!t8
.empty()) v
.push_back(stemmer(t8
));
80 if (!t9
.empty()) v
.push_back(stemmer(t9
));
81 if (!t10
.empty()) v
.push_back(stemmer(t10
));
82 return Xapian::Query(op
, v
.begin(), v
.end());
86 query(Xapian::Query::op op
, Xapian::termcount parameter
,
87 const string
& t1
= string(), const string
& t2
= string(),
88 const string
& t3
= string(), const string
& t4
= string(),
89 const string
& t5
= string(), const string
& t6
= string(),
90 const string
& t7
= string(), const string
& t8
= string(),
91 const string
& t9
= string(), const string
& t10
= string())
94 Xapian::Stem
stemmer("english");
95 if (!t1
.empty()) v
.push_back(stemmer(t1
));
96 if (!t2
.empty()) v
.push_back(stemmer(t2
));
97 if (!t3
.empty()) v
.push_back(stemmer(t3
));
98 if (!t4
.empty()) v
.push_back(stemmer(t4
));
99 if (!t5
.empty()) v
.push_back(stemmer(t5
));
100 if (!t6
.empty()) v
.push_back(stemmer(t6
));
101 if (!t7
.empty()) v
.push_back(stemmer(t7
));
102 if (!t8
.empty()) v
.push_back(stemmer(t8
));
103 if (!t9
.empty()) v
.push_back(stemmer(t9
));
104 if (!t10
.empty()) v
.push_back(stemmer(t10
));
105 return Xapian::Query(op
, v
.begin(), v
.end(), parameter
);
109 query(const string
&t
)
111 return Xapian::Query(Xapian::Stem("english")(t
));
114 // #######################################################################
115 // # Tests start here
117 // tests that the backend doesn't return zero docids
118 DEFINE_TESTCASE(zerodocid1
, backend
) {
119 // open the database (in this case a simple text file
120 // we prepared earlier)
122 Xapian::Database
mydb(get_database("apitest_onedoc"));
124 Xapian::Enquire
enquire(mydb
);
126 // make a simple query, with one word in it - "word".
127 enquire
.set_query(Xapian::Query("word"));
129 // retrieve the top ten results (we only expect one)
130 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
132 // We've done the query, now check that the result is what
133 // we expect (1 document, with non-zero docid)
134 TEST_MSET_SIZE(mymset
, 1);
136 TEST_AND_EXPLAIN(*(mymset
.begin()) != 0,
137 "A query on a database returned a zero docid");
142 // tests that an empty query returns no matches
143 DEFINE_TESTCASE(emptyquery1
, backend
) {
144 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
146 enquire
.set_query(Xapian::Query());
147 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
148 TEST_MSET_SIZE(mymset
, 0);
149 TEST_EQUAL(mymset
.get_matches_lower_bound(), 0);
150 TEST_EQUAL(mymset
.get_matches_upper_bound(), 0);
151 TEST_EQUAL(mymset
.get_matches_estimated(), 0);
152 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 0);
153 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 0);
154 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 0);
156 vector
<Xapian::Query
> v
;
157 enquire
.set_query(Xapian::Query(Xapian::Query::OP_AND
, v
.begin(), v
.end()));
158 mymset
= enquire
.get_mset(0, 10);
159 TEST_MSET_SIZE(mymset
, 0);
160 TEST_EQUAL(mymset
.get_matches_lower_bound(), 0);
161 TEST_EQUAL(mymset
.get_matches_upper_bound(), 0);
162 TEST_EQUAL(mymset
.get_matches_estimated(), 0);
163 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 0);
164 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 0);
165 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 0);
170 // tests the document count for a simple query
171 DEFINE_TESTCASE(simplequery1
, backend
) {
172 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
173 enquire
.set_query(Xapian::Query("word"));
174 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
175 TEST_MSET_SIZE(mymset
, 2);
179 // tests for the right documents and weights returned with simple query
180 DEFINE_TESTCASE(simplequery2
, backend
) {
181 // open the database (in this case a simple text file
182 // we prepared earlier)
183 Xapian::Database db
= get_database("apitest_simpledata");
184 Xapian::Enquire
enquire(db
);
185 enquire
.set_query(Xapian::Query("word"));
187 // retrieve the top results
188 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
190 // We've done the query, now check that the result is what
191 // we expect (documents 2 and 4)
192 mset_expect_order(mymset
, 2, 4);
195 Xapian::MSetIterator i
= mymset
.begin();
196 // These weights are for BM25Weight(1,0,1,0.5,0.5)
197 TEST_EQUAL_DOUBLE(i
.get_weight(), 1.04648168717725);
199 TEST_EQUAL_DOUBLE(i
.get_weight(), 0.640987686595914);
204 // tests for the right document count for another simple query
205 DEFINE_TESTCASE(simplequery3
, backend
) {
206 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
207 enquire
.set_query(query("this"));
208 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
210 // Check that 6 documents were returned.
211 TEST_MSET_SIZE(mymset
, 6);
216 // tests for the right document count for a wildcard query
217 // FIXME: move this to querytest (and just use an InMemory DB).
218 DEFINE_TESTCASE(wildquery1
, backend
) {
219 Xapian::QueryParser queryparser
;
220 unsigned flags
= Xapian::QueryParser::FLAG_WILDCARD
|
221 Xapian::QueryParser::FLAG_LOVEHATE
;
222 queryparser
.set_stemmer(Xapian::Stem("english"));
223 queryparser
.set_stemming_strategy(Xapian::QueryParser::STEM_ALL
);
224 Xapian::Database db
= get_database("apitest_simpledata");
225 queryparser
.set_database(db
);
226 Xapian::Enquire
enquire(db
);
228 Xapian::Query qobj
= queryparser
.parse_query("th*", flags
);
229 tout
<< qobj
.get_description() << endl
;
230 enquire
.set_query(qobj
);
231 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
232 // Check that 6 documents were returned.
233 TEST_MSET_SIZE(mymset
, 6);
235 qobj
= queryparser
.parse_query("notindb* \"this\"", flags
);
236 tout
<< qobj
.get_description() << endl
;
237 enquire
.set_query(qobj
);
238 mymset
= enquire
.get_mset(0, 10);
239 // Check that 6 documents were returned.
240 TEST_MSET_SIZE(mymset
, 6);
242 qobj
= queryparser
.parse_query("+notindb* \"this\"", flags
);
243 tout
<< qobj
.get_description() << endl
;
244 enquire
.set_query(qobj
);
245 mymset
= enquire
.get_mset(0, 10);
246 // Check that 0 documents were returned.
247 TEST_MSET_SIZE(mymset
, 0);
252 // multidb1 and multidb2 no longer exist.
254 // test that a multidb with 2 dbs query returns correct docids
255 DEFINE_TESTCASE(multidb3
, backend
&& !multi
) {
256 Xapian::Database
mydb2(get_database("apitest_simpledata"));
257 mydb2
.add_database(get_database("apitest_simpledata2"));
258 Xapian::Enquire
enquire(mydb2
);
261 Xapian::Query myquery
= query(Xapian::Query::OP_OR
, "inmemory", "word");
262 enquire
.set_weighting_scheme(Xapian::BoolWeight());
263 enquire
.set_query(myquery
);
265 // retrieve the top ten results
266 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
267 mset_expect_order(mymset
, 2, 3, 7);
272 // test that a multidb with 3 dbs query returns correct docids
273 DEFINE_TESTCASE(multidb4
, backend
&& !multi
) {
274 Xapian::Database
mydb2(get_database("apitest_simpledata"));
275 mydb2
.add_database(get_database("apitest_simpledata2"));
276 mydb2
.add_database(get_database("apitest_termorder"));
277 Xapian::Enquire
enquire(mydb2
);
280 Xapian::Query myquery
= query(Xapian::Query::OP_OR
, "inmemory", "word");
281 enquire
.set_weighting_scheme(Xapian::BoolWeight());
282 enquire
.set_query(myquery
);
284 // retrieve the top ten results
285 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
286 mset_expect_order(mymset
, 2, 3, 4, 10);
291 // tests MultiPostList::skip_to().
292 DEFINE_TESTCASE(multidb5
, backend
&& !multi
) {
293 Xapian::Database
mydb2(get_database("apitest_simpledata"));
294 mydb2
.add_database(get_database("apitest_simpledata2"));
295 Xapian::Enquire
enquire(mydb2
);
298 Xapian::Query myquery
= query(Xapian::Query::OP_AND
, "inmemory", "word");
299 enquire
.set_weighting_scheme(Xapian::BoolWeight());
300 enquire
.set_query(myquery
);
302 // retrieve the top ten results
303 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
304 mset_expect_order(mymset
, 2);
309 // tests that when specifying maxitems to get_mset, no more than
310 // that are returned.
311 DEFINE_TESTCASE(msetmaxitems1
, backend
) {
312 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
313 enquire
.set_query(query("this"));
314 Xapian::MSet mymset
= enquire
.get_mset(0, 1);
315 TEST_MSET_SIZE(mymset
, 1);
317 mymset
= enquire
.get_mset(0, 5);
318 TEST_MSET_SIZE(mymset
, 5);
323 // tests the returned weights are as expected (regression test for remote
324 // backend which was using the average weight rather than the actual document
325 // weight for computing weights - fixed in 1.0.0).
326 DEFINE_TESTCASE(expandweights1
, backend
) {
327 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
328 enquire
.set_query(Xapian::Query("this"));
330 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
333 Xapian::MSetIterator i
= mymset
.begin();
334 myrset
.add_document(*i
);
335 myrset
.add_document(*(++i
));
337 Xapian::ESet eset
= enquire
.get_eset(3, myrset
, enquire
.USE_EXACT_TERMFREQ
);
338 TEST_EQUAL(eset
.size(), 3);
339 TEST_EQUAL_DOUBLE(eset
[0].get_weight(), 6.08904001099445);
340 TEST_EQUAL_DOUBLE(eset
[1].get_weight(), 6.08904001099445);
341 TEST_EQUAL_DOUBLE(eset
[2].get_weight(), 4.73383620844021);
343 // Test non-default k too.
344 eset
= enquire
.get_eset(3, myrset
, enquire
.USE_EXACT_TERMFREQ
, 2.0);
345 TEST_EQUAL(eset
.size(), 3);
346 TEST_EQUAL_DOUBLE(eset
[0].get_weight(), 5.88109547674955);
347 TEST_EQUAL_DOUBLE(eset
[1].get_weight(), 5.88109547674955);
348 TEST_EQUAL_DOUBLE(eset
[2].get_weight(), 5.44473599216144);
353 // Just like test_expandweights1 but without USE_EXACT_TERMFREQ.
354 DEFINE_TESTCASE(expandweights2
, backend
) {
355 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
356 enquire
.set_query(Xapian::Query("this"));
358 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
361 Xapian::MSetIterator i
= mymset
.begin();
362 myrset
.add_document(*i
);
363 myrset
.add_document(*(++i
));
365 Xapian::ESet eset
= enquire
.get_eset(3, myrset
);
366 TEST_EQUAL(eset
.size(), 3);
367 if (!startswith(get_dbtype(), "multi")) {
368 // For a single database, the weights should be the same with or
369 // without USE_EXACT_TERMFREQ.
370 TEST_EQUAL_DOUBLE(eset
[0].get_weight(), 6.08904001099445);
371 TEST_EQUAL_DOUBLE(eset
[1].get_weight(), 6.08904001099445);
372 TEST_EQUAL_DOUBLE(eset
[2].get_weight(), 4.73383620844021);
374 // For multiple databases, we expect that using USE_EXACT_TERMFREQ
375 // will result in different weights in some cases.
376 TEST_NOT_EQUAL_DOUBLE(eset
[0].get_weight(), 6.08904001099445);
377 TEST_EQUAL_DOUBLE(eset
[1].get_weight(), 6.08904001099445);
378 TEST_NOT_EQUAL_DOUBLE(eset
[2].get_weight(), 4.73383620844021);
384 DEFINE_TESTCASE(expandweights3
, backend
) {
385 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
386 enquire
.set_query(Xapian::Query("this"));
388 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
391 Xapian::MSetIterator i
= mymset
.begin();
392 myrset
.add_document(*i
);
393 myrset
.add_document(*(++i
));
396 Xapian::ESet eset
= enquire
.get_eset(50, myrset
, 0, 0, 0.0);
397 if (!startswith(get_dbtype(), "multi")) {
398 // For a single database, the weights should be the same with or
399 // without USE_EXACT_TERMFREQ.
400 TEST_EQUAL_DOUBLE(eset
[0].get_weight(), 6.08904001099445);
401 TEST_EQUAL_DOUBLE(eset
[1].get_weight(), 6.08904001099445);
402 TEST_EQUAL_DOUBLE(eset
[2].get_weight(), 4.73383620844021);
404 // For multiple databases, we expect that using USE_EXACT_TERMFREQ
405 // will result in different weights in some cases.
406 TEST_NOT_EQUAL_DOUBLE(eset
[0].get_weight(), 6.08904001099445);
407 TEST_EQUAL_DOUBLE(eset
[1].get_weight(), 6.08904001099445);
408 TEST_NOT_EQUAL_DOUBLE(eset
[2].get_weight(), 4.73383620844021);
410 TEST_REL(eset
.back().get_weight(),>=,0);
416 // tests that negative weights are returned
417 DEFINE_TESTCASE(expandweights4
, backend
) {
418 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
419 enquire
.set_query(Xapian::Query("paragraph"));
421 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
424 Xapian::MSetIterator i
= mymset
.begin();
425 myrset
.add_document(*i
);
426 myrset
.add_document(*(++i
));
428 Xapian::ESet eset
= enquire
.get_eset(37, myrset
, 0, 0, -100);
429 // Now include negative weights
430 TEST_EQUAL(eset
.size(), 37);
431 TEST_REL(eset
[36].get_weight(),<,0);
432 TEST_REL(eset
[36].get_weight(),>=,-100);
437 // test for Bo1EWeight
438 DEFINE_TESTCASE(expandweights5
, backend
) {
439 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
440 enquire
.set_query(Xapian::Query("this"));
442 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
445 Xapian::MSetIterator i
= mymset
.begin();
446 myrset
.add_document(*i
);
447 myrset
.add_document(*(++i
));
449 enquire
.set_expansion_scheme("bo1");
450 Xapian::ESet eset
= enquire
.get_eset(3, myrset
);
452 TEST_EQUAL(eset
.size(), 3);
453 TEST_EQUAL_DOUBLE(eset
[0].get_weight(), 7.21765284821702);
454 TEST_EQUAL_DOUBLE(eset
[1].get_weight(), 6.661623193760022);
455 TEST_EQUAL_DOUBLE(eset
[2].get_weight(), 5.58090119783738);
460 // test that "trad" can be set as an expansion scheme.
461 DEFINE_TESTCASE(expandweights6
, backend
) {
462 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
463 enquire
.set_query(Xapian::Query("this"));
465 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
468 Xapian::MSetIterator i
= mymset
.begin();
469 myrset
.add_document(*i
);
470 myrset
.add_document(*(++i
));
472 enquire
.set_expansion_scheme("trad");
473 Xapian::ESet eset
= enquire
.get_eset(3, myrset
, enquire
.USE_EXACT_TERMFREQ
);
475 TEST_EQUAL(eset
.size(), 3);
476 TEST_EQUAL_DOUBLE(eset
[0].get_weight(), 6.08904001099445);
477 TEST_EQUAL_DOUBLE(eset
[1].get_weight(), 6.08904001099445);
478 TEST_EQUAL_DOUBLE(eset
[2].get_weight(), 4.73383620844021);
483 // test that invalid scheme names are not accepted
484 DEFINE_TESTCASE(expandweights7
, backend
) {
485 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
487 TEST_EXCEPTION(Xapian::InvalidArgumentError
,
488 enquire
.set_expansion_scheme("no_such_scheme"));
493 // test that "expand_k" can be passed as a parameter to get_eset
494 DEFINE_TESTCASE(expandweights8
, backend
) {
495 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
496 enquire
.set_query(Xapian::Query("this"));
498 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
501 Xapian::MSetIterator i
= mymset
.begin();
502 myrset
.add_document(*i
);
503 myrset
.add_document(*(++i
));
505 // Set expand_k to 1.0 and min_wt to 0
506 Xapian::ESet eset
= enquire
.get_eset(50, myrset
, 0, 1.0, 0, 0);
507 if (!startswith(get_dbtype(), "multi")) {
508 // For a single database, the weights should be the same with or
509 // without USE_EXACT_TERMFREQ.
510 TEST_EQUAL_DOUBLE(eset
[0].get_weight(), 6.08904001099445);
511 TEST_EQUAL_DOUBLE(eset
[1].get_weight(), 6.08904001099445);
512 TEST_EQUAL_DOUBLE(eset
[2].get_weight(), 4.73383620844021);
514 // For multiple databases, we expect that using USE_EXACT_TERMFREQ
515 // will result in different weights in some cases.
516 TEST_NOT_EQUAL_DOUBLE(eset
[0].get_weight(), 6.08904001099445);
517 TEST_EQUAL_DOUBLE(eset
[1].get_weight(), 6.08904001099445);
518 TEST_NOT_EQUAL_DOUBLE(eset
[2].get_weight(), 4.73383620844021);
520 TEST_REL(eset
.back().get_weight(),>=,0);
525 // tests that when specifying maxitems to get_eset, no more than
526 // that are returned.
527 DEFINE_TESTCASE(expandmaxitems1
, backend
) {
528 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
529 enquire
.set_query(Xapian::Query("this"));
531 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
532 tout
<< "mymset.size() = " << mymset
.size() << endl
;
533 TEST(mymset
.size() >= 2);
536 Xapian::MSetIterator i
= mymset
.begin();
537 myrset
.add_document(*i
);
538 myrset
.add_document(*(++i
));
540 Xapian::ESet myeset
= enquire
.get_eset(1, myrset
);
541 TEST_EQUAL(myeset
.size(), 1);
546 // tests that a pure boolean query has all weights set to 0
547 DEFINE_TESTCASE(boolquery1
, backend
) {
548 Xapian::Query
myboolquery(query("this"));
550 // open the database (in this case a simple text file
551 // we prepared earlier)
552 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
553 enquire
.set_query(myboolquery
);
554 enquire
.set_weighting_scheme(Xapian::BoolWeight());
556 // retrieve the top results
557 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
559 TEST_NOT_EQUAL(mymset
.size(), 0);
560 TEST_EQUAL(mymset
.get_max_possible(), 0);
561 for (Xapian::MSetIterator i
= mymset
.begin(); i
!= mymset
.end(); ++i
) {
562 TEST_EQUAL(i
.get_weight(), 0);
567 // tests that get_mset() specifying "this" works as expected
568 DEFINE_TESTCASE(msetfirst1
, backend
) {
569 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
570 enquire
.set_query(query("this"));
571 Xapian::MSet mymset1
= enquire
.get_mset(0, 6);
572 Xapian::MSet mymset2
= enquire
.get_mset(3, 3);
573 TEST(mset_range_is_same(mymset1
, 3, mymset2
, 0, 3));
575 // Regression test - we weren't adjusting the index into items[] by
576 // firstitem in api/omenquire.cc.
577 TEST_EQUAL(mymset1
[5].get_document().get_data(),
578 mymset2
[2].get_document().get_data());
582 // tests the converting-to-percent functions
583 DEFINE_TESTCASE(topercent1
, backend
) {
584 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
585 enquire
.set_query(query("this"));
586 Xapian::MSet mymset
= enquire
.get_mset(0, 20);
589 Xapian::MSetIterator i
= mymset
.begin();
590 for ( ; i
!= mymset
.end(); ++i
) {
591 int pct
= mymset
.convert_to_percent(i
);
592 TEST_AND_EXPLAIN(pct
== i
.get_percent(),
593 "convert_to_%(msetitor) != convert_to_%(wt)");
594 TEST_AND_EXPLAIN(pct
== mymset
.convert_to_percent(i
.get_weight()),
595 "convert_to_%(msetitor) != convert_to_%(wt)");
596 TEST_AND_EXPLAIN(pct
>= 0 && pct
<= 100,
597 "percentage out of range: " << pct
);
598 TEST_AND_EXPLAIN(pct
<= last_pct
, "percentage increased down mset");
604 // tests the percentage values returned
605 DEFINE_TESTCASE(topercent2
, backend
) {
606 BackendManagerLocal local_manager
;
607 local_manager
.set_datadir(test_driver::get_srcdir() + "/testdata/");
608 Xapian::Enquire
localenq(local_manager
.get_database("apitest_simpledata"));
609 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
613 // First, test a search in which the top document scores 100%.
614 enquire
.set_query(query("this"));
615 localenq
.set_query(query("this"));
616 Xapian::MSet mymset
= enquire
.get_mset(0, 20);
617 Xapian::MSet localmset
= localenq
.get_mset(0, 20);
619 Xapian::MSetIterator i
= mymset
.begin();
620 TEST(i
!= mymset
.end());
621 pct
= mymset
.convert_to_percent(i
);
622 TEST_EQUAL(pct
, 100);
624 TEST_EQUAL(mymset
.get_matches_lower_bound(), localmset
.get_matches_lower_bound());
625 TEST_EQUAL(mymset
.get_matches_upper_bound(), localmset
.get_matches_upper_bound());
626 TEST_EQUAL(mymset
.get_matches_estimated(), localmset
.get_matches_estimated());
627 TEST_EQUAL_DOUBLE(mymset
.get_max_attained(), localmset
.get_max_attained());
628 TEST_EQUAL(mymset
.size(), localmset
.size());
629 TEST(mset_range_is_same(mymset
, 0, localmset
, 0, mymset
.size()));
631 // A search in which the top document doesn't have 100%
632 Xapian::Query q
= query(Xapian::Query::OP_OR
,
633 "this", "line", "paragraph", "rubbish");
634 enquire
.set_query(q
);
635 localenq
.set_query(q
);
636 mymset
= enquire
.get_mset(0, 20);
637 localmset
= localenq
.get_mset(0, 20);
640 TEST(i
!= mymset
.end());
641 pct
= mymset
.convert_to_percent(i
);
647 TEST(i
!= mymset
.end());
648 pct
= mymset
.convert_to_percent(i
);
652 TEST_EQUAL(mymset
.get_matches_lower_bound(), localmset
.get_matches_lower_bound());
653 TEST_EQUAL(mymset
.get_matches_upper_bound(), localmset
.get_matches_upper_bound());
654 TEST_EQUAL(mymset
.get_matches_estimated(), localmset
.get_matches_estimated());
655 TEST_EQUAL_DOUBLE(mymset
.get_max_attained(), localmset
.get_max_attained());
656 TEST_EQUAL(mymset
.size(), localmset
.size());
657 TEST(mset_range_is_same(mymset
, 0, localmset
, 0, mymset
.size()));
662 class myExpandFunctor
: public Xapian::ExpandDecider
{
664 bool operator()(const string
& tname
) const {
665 unsigned long sum
= 0;
666 for (string::const_iterator i
=tname
.begin(); i
!=tname
.end(); ++i
) {
670 // tout << tname << "==> " << sum << "\n";
672 return (sum
% 2) == 0;
676 // tests the expand decision functor
677 DEFINE_TESTCASE(expandfunctor1
, backend
) {
678 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
679 enquire
.set_query(Xapian::Query("this"));
681 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
682 TEST(mymset
.size() >= 2);
685 Xapian::MSetIterator i
= mymset
.begin();
686 myrset
.add_document(*i
);
687 myrset
.add_document(*(++i
));
689 myExpandFunctor myfunctor
;
691 Xapian::ESet myeset_orig
= enquire
.get_eset(1000, myrset
);
692 unsigned int neweset_size
= 0;
693 Xapian::ESetIterator j
= myeset_orig
.begin();
694 for ( ; j
!= myeset_orig
.end(); ++j
) {
695 if (myfunctor(*j
)) neweset_size
++;
697 Xapian::ESet myeset
= enquire
.get_eset(neweset_size
, myrset
, &myfunctor
);
700 // Compare myeset with the hand-filtered version of myeset_orig.
702 tout
<< "orig_eset: ";
703 copy(myeset_orig
.begin(), myeset_orig
.end(),
704 ostream_iterator
<Xapian::ESetItem
>(tout
, " "));
707 tout
<< "new_eset: ";
708 copy(myeset
.begin(), myeset
.end(),
709 ostream_iterator
<Xapian::ESetItem
>(tout
, " "));
713 Xapian::ESetIterator orig
= myeset_orig
.begin();
714 Xapian::ESetIterator filt
= myeset
.begin();
715 for (; orig
!= myeset_orig
.end() && filt
!= myeset
.end(); ++orig
, ++filt
) {
716 // skip over items that shouldn't be in myeset
717 while (orig
!= myeset_orig
.end() && !myfunctor(*orig
)) {
721 TEST_AND_EXPLAIN(*orig
== *filt
&&
722 orig
.get_weight() == filt
.get_weight(),
723 "Mismatch in items " << *orig
<< " vs. " << *filt
724 << " after filtering");
727 while (orig
!= myeset_orig
.end() && !myfunctor(*orig
)) {
731 TEST_EQUAL(orig
, myeset_orig
.end());
732 TEST_AND_EXPLAIN(filt
== myeset
.end(),
733 "Extra items in the filtered eset.");
737 DEFINE_TESTCASE(expanddeciderfilterprefix2
, backend
) {
738 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
739 enquire
.set_query(Xapian::Query("this"));
741 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
742 TEST(mymset
.size() >= 2);
745 Xapian::MSetIterator i
= mymset
.begin();
746 myrset
.add_document(*i
);
747 myrset
.add_document(*(++i
));
749 Xapian::ESet myeset_orig
= enquire
.get_eset(1000, myrset
);
750 unsigned int neweset_size
= 0;
752 // Choose the first char in the first term as prefix.
753 Xapian::ESetIterator j
= myeset_orig
.begin();
754 TEST(myeset_orig
.size() >= 1);
755 string
prefix(*j
, 0, 1);
756 Xapian::ExpandDeciderFilterPrefix
myfunctor(prefix
);
758 for ( ; j
!= myeset_orig
.end(); ++j
) {
759 if (myfunctor(*j
)) neweset_size
++;
761 Xapian::ESet myeset
= enquire
.get_eset(neweset_size
, myrset
, &myfunctor
);
763 Xapian::ESetIterator orig
= myeset_orig
.begin();
764 Xapian::ESetIterator filt
= myeset
.begin();
765 for (; orig
!= myeset_orig
.end() && filt
!= myeset
.end(); ++orig
, ++filt
) {
766 // skip over items that shouldn't be in myeset
767 while (orig
!= myeset_orig
.end() && !myfunctor(*orig
)) {
771 TEST_AND_EXPLAIN(*orig
== *filt
&&
772 orig
.get_weight() == filt
.get_weight(),
773 "Mismatch in items " << *orig
<< " vs. " << *filt
774 << " after filtering");
777 while (orig
!= myeset_orig
.end() && !myfunctor(*orig
)) {
781 TEST_EQUAL(orig
, myeset_orig
.end());
782 TEST_AND_EXPLAIN(filt
== myeset
.end(),
783 "Extra items in the filtered eset.");
788 // tests the percent cutoff option
789 DEFINE_TESTCASE(pctcutoff1
, backend
) {
790 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
791 enquire
.set_query(query(Xapian::Query::OP_OR
,
792 "this", "line", "paragraph", "rubbish"));
793 Xapian::MSet mymset1
= enquire
.get_mset(0, 100);
796 tout
<< "Original mset pcts:";
797 print_mset_percentages(mymset1
);
801 unsigned int num_items
= 0;
804 Xapian::MSetIterator i
= mymset1
.begin();
806 for ( ; i
!= mymset1
.end(); ++i
, ++c
) {
807 int new_pct
= mymset1
.convert_to_percent(i
);
808 if (new_pct
!= my_pct
) {
810 if (changes
> 3) break;
816 TEST_AND_EXPLAIN(changes
> 3, "MSet not varied enough to test");
818 tout
<< "Cutoff percent: " << my_pct
<< "\n";
821 enquire
.set_cutoff(my_pct
);
822 Xapian::MSet mymset2
= enquire
.get_mset(0, 100);
825 tout
<< "Percentages after cutoff:";
826 print_mset_percentages(mymset2
);
830 TEST_AND_EXPLAIN(mymset2
.size() >= num_items
,
831 "Match with % cutoff lost too many items");
833 TEST_AND_EXPLAIN(mymset2
.size() == num_items
||
834 (mymset2
.convert_to_percent(mymset2
[num_items
]) == my_pct
&&
835 mymset2
.convert_to_percent(mymset2
.back()) == my_pct
),
836 "Match with % cutoff returned too many items");
841 // Tests the percent cutoff option combined with collapsing
842 DEFINE_TESTCASE(pctcutoff2
, backend
) {
843 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
844 enquire
.set_query(Xapian::Query("this"));
845 enquire
.set_query(Xapian::Query(Xapian::Query::OP_AND_NOT
, Xapian::Query("this"), Xapian::Query("banana")));
846 Xapian::MSet mset
= enquire
.get_mset(0, 100);
849 tout
<< "Original mset pcts:";
850 print_mset_percentages(mset
);
854 TEST(mset
.size() >= 2);
855 TEST(mset
[0].get_percent() - mset
[1].get_percent() >= 2);
857 int cutoff
= mset
[0].get_percent() + mset
[1].get_percent();
860 enquire
.set_cutoff(cutoff
);
861 enquire
.set_collapse_key(1234); // Value which is always empty.
863 Xapian::MSet mset2
= enquire
.get_mset(0, 1);
864 TEST_EQUAL(mset2
.size(), 1);
865 TEST_EQUAL(mset2
.get_matches_lower_bound(), 1);
866 TEST_REL(mset2
.get_uncollapsed_matches_lower_bound(),>=,1);
867 TEST_REL(mset2
.get_uncollapsed_matches_lower_bound(),<=,mset
.size());
868 TEST_REL(mset2
.get_uncollapsed_matches_upper_bound(),>=,mset
.size());
869 TEST_REL(mset2
.get_uncollapsed_matches_lower_bound(),<=,mset2
.get_uncollapsed_matches_estimated());
870 TEST_REL(mset2
.get_uncollapsed_matches_upper_bound(),>=,mset2
.get_uncollapsed_matches_estimated());
875 // Test that the percent cutoff option returns all the answers it should.
876 DEFINE_TESTCASE(pctcutoff3
, backend
) {
877 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
878 enquire
.set_query(Xapian::Query("this"));
879 Xapian::MSet mset1
= enquire
.get_mset(0, 10);
882 tout
<< "Original mset pcts:";
883 print_mset_percentages(mset1
);
888 for (Xapian::MSetIterator i
= mset1
.begin(); i
!= mset1
.end(); ++i
) {
889 int new_percent
= mset1
.convert_to_percent(i
);
890 if (new_percent
!= percent
) {
891 enquire
.set_cutoff(percent
);
892 Xapian::MSet mset2
= enquire
.get_mset(0, 10);
893 TEST_EQUAL(mset2
.size(), i
.get_rank());
894 percent
= new_percent
;
901 // tests the cutoff option
902 DEFINE_TESTCASE(cutoff1
, backend
) {
903 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
904 enquire
.set_query(query(Xapian::Query::OP_OR
,
905 "this", "line", "paragraph", "rubbish"));
906 Xapian::MSet mymset1
= enquire
.get_mset(0, 100);
909 tout
<< "Original mset weights:";
910 print_mset_weights(mymset1
);
914 unsigned int num_items
= 0;
917 Xapian::MSetIterator i
= mymset1
.begin();
919 for ( ; i
!= mymset1
.end(); ++i
, ++c
) {
920 double new_wt
= i
.get_weight();
921 if (new_wt
!= my_wt
) {
923 if (changes
> 3) break;
929 TEST_AND_EXPLAIN(changes
> 3, "MSet not varied enough to test");
931 tout
<< "Cutoff weight: " << my_wt
<< "\n";
934 enquire
.set_cutoff(0, my_wt
);
935 Xapian::MSet mymset2
= enquire
.get_mset(0, 100);
938 tout
<< "Weights after cutoff:";
939 print_mset_weights(mymset2
);
943 TEST_AND_EXPLAIN(mymset2
.size() >= num_items
,
944 "Match with cutoff lost too many items");
946 TEST_AND_EXPLAIN(mymset2
.size() == num_items
||
947 (mymset2
[num_items
].get_weight() == my_wt
&&
948 mymset2
.back().get_weight() == my_wt
),
949 "Match with cutoff returned too many items");
954 // tests the allow query terms expand option
955 DEFINE_TESTCASE(allowqterms1
, backend
) {
956 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
957 string term
= "paragraph";
958 enquire
.set_query(Xapian::Query(term
));
960 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
961 TEST(mymset
.size() >= 2);
964 Xapian::MSetIterator i
= mymset
.begin();
965 myrset
.add_document(*i
);
966 myrset
.add_document(*(++i
));
968 Xapian::ESet myeset
= enquire
.get_eset(1000, myrset
);
969 Xapian::ESetIterator j
= myeset
.begin();
970 for ( ; j
!= myeset
.end(); ++j
) {
971 TEST_NOT_EQUAL(*j
, term
);
974 Xapian::ESet myeset2
= enquire
.get_eset(1000, myrset
, Xapian::Enquire::INCLUDE_QUERY_TERMS
);
976 for ( ; j
!= myeset2
.end(); ++j
) {
977 if (*j
== term
) break;
979 TEST(j
!= myeset2
.end());
983 // tests that the MSet max_attained works
984 DEFINE_TESTCASE(maxattain1
, backend
) {
985 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
986 enquire
.set_query(query("this"));
987 Xapian::MSet mymset
= enquire
.get_mset(0, 100);
990 Xapian::MSetIterator i
= mymset
.begin();
991 for ( ; i
!= mymset
.end(); ++i
) {
992 if (i
.get_weight() > mymax
) mymax
= i
.get_weight();
994 TEST_EQUAL(mymax
, mymset
.get_max_attained());
999 // tests a reversed boolean query
1000 DEFINE_TESTCASE(reversebool1
, backend
) {
1001 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1002 enquire
.set_query(Xapian::Query("this"));
1003 enquire
.set_weighting_scheme(Xapian::BoolWeight());
1005 Xapian::MSet mymset1
= enquire
.get_mset(0, 100);
1006 TEST_AND_EXPLAIN(mymset1
.size() > 1,
1007 "Mset was too small to test properly");
1009 enquire
.set_docid_order(Xapian::Enquire::ASCENDING
);
1010 Xapian::MSet mymset2
= enquire
.get_mset(0, 100);
1011 enquire
.set_docid_order(Xapian::Enquire::DESCENDING
);
1012 Xapian::MSet mymset3
= enquire
.get_mset(0, 100);
1014 // mymset1 and mymset2 should be identical
1015 TEST_EQUAL(mymset1
.size(), mymset2
.size());
1018 Xapian::MSetIterator i
= mymset1
.begin();
1019 Xapian::MSetIterator j
= mymset2
.begin();
1020 for ( ; i
!= mymset1
.end(); ++i
, j
++) {
1021 TEST(j
!= mymset2
.end());
1022 // if this fails, then setting match_sort_forward=true was not
1023 // the same as the default.
1026 TEST(j
== mymset2
.end());
1029 // mymset1 and mymset3 should be same but reversed
1030 TEST_EQUAL(mymset1
.size(), mymset3
.size());
1033 Xapian::MSetIterator i
= mymset1
.begin();
1034 Xapian::MSetIterator j
= mymset3
.end();
1035 for ( ; i
!= mymset1
.end(); ++i
) {
1036 // if this fails, then setting match_sort_forward=false didn't
1037 // reverse the results.
1038 TEST_EQUAL(*i
, *--j
);
1045 // tests a reversed boolean query, where the full mset isn't returned
1046 DEFINE_TESTCASE(reversebool2
, backend
) {
1047 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1048 enquire
.set_query(Xapian::Query("this"));
1049 enquire
.set_weighting_scheme(Xapian::BoolWeight());
1051 Xapian::MSet mymset1
= enquire
.get_mset(0, 100);
1053 TEST_AND_EXPLAIN(mymset1
.size() > 1,
1054 "Mset was too small to test properly");
1056 enquire
.set_docid_order(Xapian::Enquire::ASCENDING
);
1057 Xapian::doccount msize
= mymset1
.size() / 2;
1058 Xapian::MSet mymset2
= enquire
.get_mset(0, msize
);
1059 enquire
.set_docid_order(Xapian::Enquire::DESCENDING
);
1060 Xapian::MSet mymset3
= enquire
.get_mset(0, msize
);
1062 // mymset2 should be first msize items of mymset1
1063 TEST_EQUAL(msize
, mymset2
.size());
1065 Xapian::MSetIterator i
= mymset1
.begin();
1066 Xapian::MSetIterator j
= mymset2
.begin();
1067 for ( ; j
!= mymset2
.end(); ++i
, j
++) {
1068 TEST(i
!= mymset1
.end());
1069 // if this fails, then setting match_sort_forward=true was not
1070 // the same as the default.
1073 // mymset1 should be larger.
1074 TEST(i
!= mymset1
.end());
1077 // mymset3 should be last msize items of mymset1, in reverse order
1078 TEST_EQUAL(msize
, mymset3
.size());
1080 Xapian::MSetIterator i
= mymset1
.end();
1081 Xapian::MSetIterator j
;
1082 for (j
= mymset3
.begin(); j
!= mymset3
.end(); j
++) {
1083 // if this fails, then setting match_sort_forward=false didn't
1084 // reverse the results.
1085 TEST_EQUAL(*--i
, *j
);
1092 // tests that get_matching_terms() returns the terms in the right order
1093 DEFINE_TESTCASE(getmterms1
, backend
) {
1094 list
<string
> answers_list
;
1095 answers_list
.push_back("one");
1096 answers_list
.push_back("two");
1097 answers_list
.push_back("three");
1098 answers_list
.push_back("four");
1100 Xapian::Database
mydb(get_database("apitest_termorder"));
1101 Xapian::Enquire
enquire(mydb
);
1103 Xapian::Query
myquery(Xapian::Query::OP_OR
,
1104 Xapian::Query(Xapian::Query::OP_AND
,
1105 Xapian::Query("one", 1, 1),
1106 Xapian::Query("three", 1, 3)),
1107 Xapian::Query(Xapian::Query::OP_OR
,
1108 Xapian::Query("four", 1, 4),
1109 Xapian::Query("two", 1, 2)));
1111 enquire
.set_query(myquery
);
1113 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
1115 TEST_MSET_SIZE(mymset
, 1);
1116 list
<string
> list(enquire
.get_matching_terms_begin(mymset
.begin()),
1117 enquire
.get_matching_terms_end(mymset
.begin()));
1118 TEST(list
== answers_list
);
1123 // tests that get_matching_terms() returns the terms only once
1124 DEFINE_TESTCASE(getmterms2
, backend
) {
1125 list
<string
> answers_list
;
1126 answers_list
.push_back("one");
1127 answers_list
.push_back("two");
1128 answers_list
.push_back("three");
1130 Xapian::Database
mydb(get_database("apitest_termorder"));
1131 Xapian::Enquire
enquire(mydb
);
1133 Xapian::Query
myquery(Xapian::Query::OP_OR
,
1134 Xapian::Query(Xapian::Query::OP_AND
,
1135 Xapian::Query("one", 1, 1),
1136 Xapian::Query("three", 1, 3)),
1137 Xapian::Query(Xapian::Query::OP_OR
,
1138 Xapian::Query("one", 1, 4),
1139 Xapian::Query("two", 1, 2)));
1141 enquire
.set_query(myquery
);
1143 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
1145 TEST_MSET_SIZE(mymset
, 1);
1146 list
<string
> list(enquire
.get_matching_terms_begin(mymset
.begin()),
1147 enquire
.get_matching_terms_end(mymset
.begin()));
1148 TEST(list
== answers_list
);
1153 // test that running a query twice returns the same results
1154 DEFINE_TESTCASE(repeatquery1
, backend
) {
1155 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1156 enquire
.set_query(Xapian::Query("this"));
1158 enquire
.set_query(query(Xapian::Query::OP_OR
, "this", "word"));
1160 Xapian::MSet mymset1
= enquire
.get_mset(0, 10);
1161 Xapian::MSet mymset2
= enquire
.get_mset(0, 10);
1162 TEST_EQUAL(mymset1
, mymset2
);
1167 // test that prefetching documents works (at least, gives same results)
1168 DEFINE_TESTCASE(fetchdocs1
, backend
) {
1169 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1170 enquire
.set_query(Xapian::Query("this"));
1172 enquire
.set_query(query(Xapian::Query::OP_OR
, "this", "word"));
1174 Xapian::MSet mymset1
= enquire
.get_mset(0, 10);
1175 Xapian::MSet mymset2
= enquire
.get_mset(0, 10);
1176 TEST_EQUAL(mymset1
, mymset2
);
1177 mymset2
.fetch(mymset2
[0], mymset2
[mymset2
.size() - 1]);
1178 mymset2
.fetch(mymset2
.begin(), mymset2
.end());
1179 mymset2
.fetch(mymset2
.begin());
1182 Xapian::MSetIterator it1
= mymset1
.begin();
1183 Xapian::MSetIterator it2
= mymset2
.begin();
1185 while (it1
!= mymset1
.end() && it2
!= mymset2
.end()) {
1186 TEST_EQUAL(it1
.get_document().get_data(),
1187 it2
.get_document().get_data());
1188 TEST_NOT_EQUAL(it1
.get_document().get_data(), "");
1189 TEST_NOT_EQUAL(it2
.get_document().get_data(), "");
1193 TEST_EQUAL(it1
, mymset1
.end());
1194 TEST_EQUAL(it1
, mymset2
.end());
1199 // test that searching for a term not in the database fails nicely
1200 DEFINE_TESTCASE(absentterm1
, backend
) {
1201 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1202 enquire
.set_weighting_scheme(Xapian::BoolWeight());
1203 enquire
.set_query(Xapian::Query("frink"));
1205 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
1206 mset_expect_order(mymset
);
1211 // as absentterm1, but setting query from a vector of terms
1212 DEFINE_TESTCASE(absentterm2
, backend
) {
1213 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1214 vector
<string
> terms
;
1215 terms
.push_back("frink");
1217 Xapian::Query
query(Xapian::Query::OP_OR
, terms
.begin(), terms
.end());
1218 enquire
.set_query(query
);
1220 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
1221 mset_expect_order(mymset
);
1226 // test that rsets do sensible things
1227 DEFINE_TESTCASE(rset1
, backend
) {
1228 Xapian::Database
mydb(get_database("apitest_rset"));
1229 Xapian::Enquire
enquire(mydb
);
1230 Xapian::Query myquery
= query(Xapian::Query::OP_OR
, "giraffe", "tiger");
1231 enquire
.set_query(myquery
);
1233 Xapian::MSet mymset1
= enquire
.get_mset(0, 10);
1235 Xapian::RSet myrset
;
1236 myrset
.add_document(1);
1238 Xapian::MSet mymset2
= enquire
.get_mset(0, 10, &myrset
);
1240 // We should have the same documents turn up, but 1 and 3 should
1241 // have higher weights with the RSet.
1242 TEST_MSET_SIZE(mymset1
, 3);
1243 TEST_MSET_SIZE(mymset2
, 3);
1248 // test that rsets do more sensible things
1249 DEFINE_TESTCASE(rset2
, backend
) {
1250 Xapian::Database
mydb(get_database("apitest_rset"));
1251 Xapian::Enquire
enquire(mydb
);
1252 Xapian::Query myquery
= query(Xapian::Query::OP_OR
, "cuddly", "people");
1253 enquire
.set_query(myquery
);
1255 Xapian::MSet mymset1
= enquire
.get_mset(0, 10);
1257 Xapian::RSet myrset
;
1258 myrset
.add_document(2);
1260 Xapian::MSet mymset2
= enquire
.get_mset(0, 10, &myrset
);
1262 mset_expect_order(mymset1
, 1, 2);
1263 mset_expect_order(mymset2
, 2, 1);
1268 // test that rsets behave correctly with multiDBs
1269 DEFINE_TESTCASE(rsetmultidb1
, backend
&& !multi
) {
1270 Xapian::Database
mydb1(get_database("apitest_rset", "apitest_simpledata2"));
1271 Xapian::Database
mydb2(get_database("apitest_rset"));
1272 mydb2
.add_database(get_database("apitest_simpledata2"));
1274 Xapian::Enquire
enquire1(mydb1
);
1275 Xapian::Enquire
enquire2(mydb2
);
1277 Xapian::Query myquery
= query(Xapian::Query::OP_OR
, "cuddly", "multiple");
1279 enquire1
.set_query(myquery
);
1280 enquire2
.set_query(myquery
);
1282 Xapian::RSet myrset1
;
1283 Xapian::RSet myrset2
;
1284 myrset1
.add_document(4);
1285 myrset2
.add_document(2);
1287 Xapian::MSet mymset1a
= enquire1
.get_mset(0, 10);
1288 Xapian::MSet mymset1b
= enquire1
.get_mset(0, 10, &myrset1
);
1289 Xapian::MSet mymset2a
= enquire2
.get_mset(0, 10);
1290 Xapian::MSet mymset2b
= enquire2
.get_mset(0, 10, &myrset2
);
1292 mset_expect_order(mymset1a
, 1, 4);
1293 mset_expect_order(mymset1b
, 4, 1);
1294 mset_expect_order(mymset2a
, 1, 2);
1295 mset_expect_order(mymset2b
, 2, 1);
1297 TEST(mset_range_is_same_weights(mymset1a
, 0, mymset2a
, 0, 2));
1298 TEST(mset_range_is_same_weights(mymset1b
, 0, mymset2b
, 0, 2));
1299 TEST_NOT_EQUAL(mymset1a
, mymset1b
);
1300 TEST_NOT_EQUAL(mymset2a
, mymset2b
);
1305 // regression tests - used to cause assertion in stats.h to fail
1306 // Doesn't actually fail for multi but it doesn't make sense to run there.
1307 DEFINE_TESTCASE(rsetmultidb3
, backend
&& !multi
) {
1308 Xapian::Enquire
enquire(get_database("apitest_simpledata2"));
1309 enquire
.set_query(query(Xapian::Query::OP_OR
, "cuddly", "people"));
1310 Xapian::MSet mset
= enquire
.get_mset(0, 10); // used to fail assertion
1314 /// Simple test of the elite set operator.
1315 DEFINE_TESTCASE(eliteset1
, backend
) {
1316 Xapian::Database
mydb(get_database("apitest_simpledata"));
1317 Xapian::Enquire
enquire(mydb
);
1319 Xapian::Query myquery1
= query(Xapian::Query::OP_OR
, "word");
1321 Xapian::Query myquery2
= query(Xapian::Query::OP_ELITE_SET
, 1,
1324 enquire
.set_query(myquery1
, 2); // So the query lengths are the same.
1325 Xapian::MSet mymset1
= enquire
.get_mset(0, 10);
1327 enquire
.set_query(myquery2
);
1328 Xapian::MSet mymset2
= enquire
.get_mset(0, 10);
1330 TEST_EQUAL(mymset1
, mymset2
);
1334 /// Test that the elite set operator works if the set contains
1335 /// sub-expressions (regression test)
1336 DEFINE_TESTCASE(eliteset2
, backend
) {
1337 Xapian::Database
mydb(get_database("apitest_simpledata"));
1338 Xapian::Enquire
enquire(mydb
);
1340 Xapian::Query myquery1
= query(Xapian::Query::OP_AND
, "word", "search");
1342 vector
<Xapian::Query
> qs
;
1343 qs
.push_back(query("this"));
1344 qs
.push_back(query(Xapian::Query::OP_AND
, "word", "search"));
1345 Xapian::Query
myquery2(Xapian::Query::OP_ELITE_SET
,
1346 qs
.begin(), qs
.end(), 1);
1348 enquire
.set_query(myquery1
);
1349 Xapian::MSet mymset1
= enquire
.get_mset(0, 10);
1351 enquire
.set_query(myquery2
);
1352 Xapian::MSet mymset2
= enquire
.get_mset(0, 10);
1354 TEST_EQUAL(mymset1
, mymset2
);
1355 // query lengths differ so mset weights not the same (with some weighting
1357 //test_mset_order_equal(mymset1, mymset2);
1362 /// Test that elite set doesn't affect query results if we have fewer
1363 /// terms than the threshold
1364 DEFINE_TESTCASE(eliteset3
, backend
) {
1365 Xapian::Database
mydb1(get_database("apitest_simpledata"));
1366 Xapian::Enquire
enquire1(mydb1
);
1368 Xapian::Database
mydb2(get_database("apitest_simpledata"));
1369 Xapian::Enquire
enquire2(mydb2
);
1372 Xapian::Stem
stemmer("english");
1374 string term1
= stemmer("word");
1375 string term2
= stemmer("rubbish");
1376 string term3
= stemmer("banana");
1378 vector
<string
> terms
;
1379 terms
.push_back(term1
);
1380 terms
.push_back(term2
);
1381 terms
.push_back(term3
);
1383 Xapian::Query
myquery1(Xapian::Query::OP_OR
, terms
.begin(), terms
.end());
1384 enquire1
.set_query(myquery1
);
1386 Xapian::Query
myquery2(Xapian::Query::OP_ELITE_SET
, terms
.begin(), terms
.end(), 3);
1387 enquire2
.set_query(myquery2
);
1389 // retrieve the results
1390 Xapian::MSet mymset1
= enquire1
.get_mset(0, 10);
1391 Xapian::MSet mymset2
= enquire2
.get_mset(0, 10);
1393 TEST_EQUAL(mymset1
.get_termfreq(term1
),
1394 mymset2
.get_termfreq(term1
));
1395 TEST_EQUAL(mymset1
.get_termweight(term1
),
1396 mymset2
.get_termweight(term1
));
1397 TEST_EQUAL(mymset1
.get_termfreq(term2
),
1398 mymset2
.get_termfreq(term2
));
1399 TEST_EQUAL(mymset1
.get_termweight(term2
),
1400 mymset2
.get_termweight(term2
));
1401 TEST_EQUAL(mymset1
.get_termfreq(term3
),
1402 mymset2
.get_termfreq(term3
));
1403 TEST_EQUAL(mymset1
.get_termweight(term3
),
1404 mymset2
.get_termweight(term3
));
1405 // TEST_EQUAL(mymset1, mymset2);
1410 /// Test that elite set doesn't pick terms with 0 frequency
1411 DEFINE_TESTCASE(eliteset4
, backend
) {
1412 Xapian::Database
mydb1(get_database("apitest_simpledata"));
1413 Xapian::Enquire
enquire1(mydb1
);
1415 Xapian::Database
mydb2(get_database("apitest_simpledata"));
1416 Xapian::Enquire
enquire2(mydb2
);
1418 Xapian::Query myquery1
= query("rubbish");
1419 Xapian::Query myquery2
= query(Xapian::Query::OP_ELITE_SET
, 1,
1420 "word", "rubbish", "fibble");
1421 enquire1
.set_query(myquery1
);
1422 enquire2
.set_query(myquery2
);
1424 // retrieve the results
1425 Xapian::MSet mymset1
= enquire1
.get_mset(0, 10);
1426 Xapian::MSet mymset2
= enquire2
.get_mset(0, 10);
1428 TEST_NOT_EQUAL(mymset2
.size(), 0);
1429 TEST_EQUAL(mymset1
, mymset2
);
1430 // TEST_EQUAL(mymset1, mymset2);
1435 /// Regression test for problem with excess precision.
1436 DEFINE_TESTCASE(eliteset5
, backend
) {
1437 Xapian::Database
mydb1(get_database("apitest_simpledata"));
1438 Xapian::Enquire
enquire1(mydb1
);
1441 for (int i
= 0; i
!= 3; ++i
) {
1442 v
.push_back("simpl");
1443 v
.push_back("queri");
1445 v
.push_back("rubbish");
1446 v
.push_back("rubbish");
1447 v
.push_back("rubbish");
1448 v
.push_back("word");
1449 v
.push_back("word");
1450 v
.push_back("word");
1453 Xapian::Query myquery1
= Xapian::Query(Xapian::Query::OP_ELITE_SET
,
1454 v
.begin(), v
.end(), 1);
1455 myquery1
= Xapian::Query(Xapian::Query::OP_SCALE_WEIGHT
,
1459 enquire1
.set_query(myquery1
);
1460 // On architectures with excess precision (or, at least, on x86), the
1461 // following call used to result in a segfault.
1462 enquire1
.get_mset(0, 10);
1467 /// Test that the termfreq returned by termlists is correct.
1468 DEFINE_TESTCASE(termlisttermfreq1
, backend
) {
1469 Xapian::Database
mydb(get_database("apitest_simpledata"));
1470 Xapian::Enquire
enquire(mydb
);
1471 Xapian::Stem
stemmer("english");
1474 rset1
.add_document(5);
1475 rset2
.add_document(6);
1477 Xapian::ESet eset1
= enquire
.get_eset(1000, rset1
);
1478 Xapian::ESet eset2
= enquire
.get_eset(1000, rset2
);
1480 // search for weight of term 'another'
1481 string theterm
= stemmer("another");
1486 Xapian::ESetIterator i
= eset1
.begin();
1487 for ( ; i
!= eset1
.end(); i
++) {
1488 if (*i
== theterm
) {
1489 wt1
= i
.get_weight();
1495 Xapian::ESetIterator i
= eset2
.begin();
1496 for ( ; i
!= eset2
.end(); i
++) {
1497 if (*i
== theterm
) {
1498 wt2
= i
.get_weight();
1504 TEST_NOT_EQUAL(wt1
, 0);
1505 TEST_NOT_EQUAL(wt2
, 0);
1506 TEST_EQUAL(wt1
, wt2
);
1511 /// Test the termfrequency and termweight info returned for query terms
1512 DEFINE_TESTCASE(qterminfo1
, backend
) {
1513 Xapian::Database
mydb1(get_database("apitest_simpledata", "apitest_simpledata2"));
1514 Xapian::Enquire
enquire1(mydb1
);
1516 Xapian::Database
mydb2(get_database("apitest_simpledata"));
1517 mydb2
.add_database(get_database("apitest_simpledata2"));
1518 Xapian::Enquire
enquire2(mydb2
);
1521 Xapian::Stem
stemmer("english");
1523 string term1
= stemmer("word");
1524 string term2
= stemmer("inmemory");
1525 string term3
= stemmer("flibble");
1527 Xapian::Query
myquery(Xapian::Query::OP_OR
,
1528 Xapian::Query(term1
),
1529 Xapian::Query(Xapian::Query::OP_OR
,
1530 Xapian::Query(term2
),
1531 Xapian::Query(term3
)));
1532 enquire1
.set_query(myquery
);
1533 enquire2
.set_query(myquery
);
1535 // retrieve the results
1536 Xapian::MSet mymset1a
= enquire1
.get_mset(0, 0);
1537 Xapian::MSet mymset2a
= enquire2
.get_mset(0, 0);
1539 TEST_EQUAL(mymset1a
.get_termfreq(term1
),
1540 mymset2a
.get_termfreq(term1
));
1541 TEST_EQUAL(mymset1a
.get_termfreq(term2
),
1542 mymset2a
.get_termfreq(term2
));
1543 TEST_EQUAL(mymset1a
.get_termfreq(term3
),
1544 mymset2a
.get_termfreq(term3
));
1546 TEST_EQUAL(mymset1a
.get_termfreq(term1
), 3);
1547 TEST_EQUAL(mymset1a
.get_termfreq(term2
), 1);
1548 TEST_EQUAL(mymset1a
.get_termfreq(term3
), 0);
1550 TEST_NOT_EQUAL(mymset1a
.get_termweight(term1
), 0);
1551 TEST_NOT_EQUAL(mymset1a
.get_termweight(term2
), 0);
1552 // non-existent terms should have 0 weight.
1553 TEST_EQUAL(mymset1a
.get_termweight(term3
), 0);
1555 TEST_EQUAL(mymset1a
.get_termfreq(stemmer("banana")), 1);
1556 TEST_EXCEPTION(Xapian::InvalidArgumentError
,
1557 mymset1a
.get_termweight(stemmer("banana")));
1559 TEST_EQUAL(mymset1a
.get_termfreq("sponge"), 0);
1560 TEST_EXCEPTION(Xapian::InvalidArgumentError
,
1561 mymset1a
.get_termweight("sponge"));
1566 /// Regression test for bug #37.
1567 DEFINE_TESTCASE(qterminfo2
, backend
) {
1568 Xapian::Database
db(get_database("apitest_simpledata"));
1569 Xapian::Enquire
enquire(db
);
1572 Xapian::Stem
stemmer("english");
1574 string term1
= stemmer("paragraph");
1575 string term2
= stemmer("another");
1577 Xapian::Query
query(Xapian::Query::OP_AND_NOT
, term1
,
1578 Xapian::Query(Xapian::Query::OP_AND
, term1
, term2
));
1579 enquire
.set_query(query
);
1581 // retrieve the results
1582 // Note: get_mset() used to throw "AssertionError" in debug builds
1583 Xapian::MSet mset
= enquire
.get_mset(0, 10);
1585 TEST_NOT_EQUAL(mset
.get_termweight("paragraph"), 0);
1590 // tests that when specifying that no items are to be returned, those
1591 // statistics which should be the same are.
1592 DEFINE_TESTCASE(msetzeroitems1
, backend
) {
1593 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1594 enquire
.set_query(query("this"));
1595 Xapian::MSet mymset1
= enquire
.get_mset(0, 0);
1597 Xapian::MSet mymset2
= enquire
.get_mset(0, 1);
1599 TEST_EQUAL(mymset1
.get_max_possible(), mymset2
.get_max_possible());
1604 // test that the matches_* of a simple query are as expected
1605 DEFINE_TESTCASE(matches1
, backend
) {
1606 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1607 Xapian::Query myquery
;
1608 Xapian::MSet mymset
;
1610 myquery
= query("word");
1611 enquire
.set_query(myquery
);
1612 mymset
= enquire
.get_mset(0, 10);
1613 TEST_EQUAL(mymset
.get_matches_lower_bound(), 2);
1614 TEST_EQUAL(mymset
.get_matches_estimated(), 2);
1615 TEST_EQUAL(mymset
.get_matches_upper_bound(), 2);
1616 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 2);
1617 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 2);
1618 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 2);
1620 myquery
= query(Xapian::Query::OP_OR
, "inmemory", "word");
1621 enquire
.set_query(myquery
);
1622 mymset
= enquire
.get_mset(0, 10);
1623 TEST_EQUAL(mymset
.get_matches_lower_bound(), 2);
1624 TEST_EQUAL(mymset
.get_matches_estimated(), 2);
1625 TEST_EQUAL(mymset
.get_matches_upper_bound(), 2);
1626 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 2);
1627 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 2);
1628 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 2);
1630 myquery
= query(Xapian::Query::OP_AND
, "inmemory", "word");
1631 enquire
.set_query(myquery
);
1632 mymset
= enquire
.get_mset(0, 10);
1633 TEST_EQUAL(mymset
.get_matches_lower_bound(), 0);
1634 TEST_EQUAL(mymset
.get_matches_estimated(), 0);
1635 TEST_EQUAL(mymset
.get_matches_upper_bound(), 0);
1636 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 0);
1637 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 0);
1638 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 0);
1640 myquery
= query(Xapian::Query::OP_AND
, "simple", "word");
1641 enquire
.set_query(myquery
);
1642 mymset
= enquire
.get_mset(0, 10);
1643 TEST_EQUAL(mymset
.get_matches_lower_bound(), 2);
1644 TEST_EQUAL(mymset
.get_matches_estimated(), 2);
1645 TEST_EQUAL(mymset
.get_matches_upper_bound(), 2);
1646 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 2);
1647 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 2);
1648 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 2);
1650 myquery
= query(Xapian::Query::OP_AND
, "simple", "word");
1651 enquire
.set_query(myquery
);
1652 mymset
= enquire
.get_mset(0, 0);
1653 // For a single database, this is true, but not for "multi" (since there
1654 // one sub-database has 3 documents and simple and word both have termfreq
1655 // of 2, so the matcher can tell at least one document must match!)
1656 // TEST_EQUAL(mymset.get_matches_lower_bound(), 0);
1657 TEST_REL(mymset
.get_matches_lower_bound(),<=,mymset
.get_matches_estimated());
1658 TEST_EQUAL(mymset
.get_matches_estimated(), 1);
1659 TEST_EQUAL(mymset
.get_matches_upper_bound(), 2);
1660 TEST_REL(mymset
.get_uncollapsed_matches_lower_bound(),<=,mymset
.get_uncollapsed_matches_estimated());
1661 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 1);
1662 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 2);
1664 mymset
= enquire
.get_mset(0, 1);
1665 TEST_EQUAL(mymset
.get_matches_lower_bound(), 2);
1666 TEST_EQUAL(mymset
.get_matches_estimated(), 2);
1667 TEST_EQUAL(mymset
.get_matches_upper_bound(), 2);
1668 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 2);
1669 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 2);
1670 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 2);
1672 mymset
= enquire
.get_mset(0, 2);
1673 TEST_EQUAL(mymset
.get_matches_lower_bound(), 2);
1674 TEST_EQUAL(mymset
.get_matches_estimated(), 2);
1675 TEST_EQUAL(mymset
.get_matches_upper_bound(), 2);
1676 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 2);
1677 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 2);
1678 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 2);
1680 myquery
= query(Xapian::Query::OP_AND
, "paragraph", "another");
1681 enquire
.set_query(myquery
);
1682 mymset
= enquire
.get_mset(0, 0);
1683 TEST_EQUAL(mymset
.get_matches_lower_bound(), 1);
1684 TEST_EQUAL(mymset
.get_matches_estimated(), 2);
1685 TEST_EQUAL(mymset
.get_matches_upper_bound(), 2);
1686 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 1);
1687 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 2);
1688 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 2);
1690 mymset
= enquire
.get_mset(0, 1);
1691 TEST_EQUAL(mymset
.get_matches_lower_bound(), 1);
1692 TEST_EQUAL(mymset
.get_matches_estimated(), 2);
1693 TEST_EQUAL(mymset
.get_matches_upper_bound(), 2);
1694 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 1);
1695 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 2);
1696 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 2);
1698 mymset
= enquire
.get_mset(0, 2);
1699 TEST_EQUAL(mymset
.get_matches_lower_bound(), 1);
1700 TEST_EQUAL(mymset
.get_matches_estimated(), 1);
1701 TEST_EQUAL(mymset
.get_matches_upper_bound(), 1);
1702 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 1);
1703 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 1);
1704 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 1);
1706 mymset
= enquire
.get_mset(1, 20);
1707 TEST_EQUAL(mymset
.get_matches_lower_bound(), 1);
1708 TEST_EQUAL(mymset
.get_matches_estimated(), 1);
1709 TEST_EQUAL(mymset
.get_matches_upper_bound(), 1);
1710 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 1);
1711 TEST_EQUAL(mymset
.get_uncollapsed_matches_estimated(), 1);
1712 TEST_EQUAL(mymset
.get_uncollapsed_matches_upper_bound(), 1);
1717 // tests that wqf affects the document weights
1718 DEFINE_TESTCASE(wqf1
, backend
) {
1719 // Both queries have length 2; in q1 word has wqf=2, in q2 word has wqf=1
1720 Xapian::Query
q1("word", 2);
1721 Xapian::Query
q2("word");
1722 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1723 enquire
.set_query(q1
);
1724 Xapian::MSet mset1
= enquire
.get_mset(0, 10);
1725 enquire
.set_query(q2
);
1726 Xapian::MSet mset2
= enquire
.get_mset(0, 2);
1727 // Check the weights
1728 TEST(mset1
.begin().get_weight() > mset2
.begin().get_weight());
1732 // tests that query length affects the document weights
1733 DEFINE_TESTCASE(qlen1
, backend
) {
1734 Xapian::Query
q1("word");
1735 Xapian::Query
q2("word");
1736 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1737 enquire
.set_query(q1
);
1738 Xapian::MSet mset1
= enquire
.get_mset(0, 10);
1739 enquire
.set_query(q2
);
1740 Xapian::MSet mset2
= enquire
.get_mset(0, 2);
1741 // Check the weights
1742 //TEST(mset1.begin().get_weight() < mset2.begin().get_weight());
1743 TEST(mset1
.begin().get_weight() == mset2
.begin().get_weight());
1747 // tests that opening a non-existent termlist throws the correct exception
1748 DEFINE_TESTCASE(termlist1
, backend
) {
1749 Xapian::Database
db(get_database("apitest_onedoc"));
1750 TEST_EXCEPTION(Xapian::InvalidArgumentError
,
1751 Xapian::TermIterator t
= db
.termlist_begin(0));
1752 TEST_EXCEPTION(Xapian::DocNotFoundError
,
1753 Xapian::TermIterator t
= db
.termlist_begin(2));
1754 /* Cause the database to be used properly, showing up problems
1755 * with the link being in a bad state. CME */
1756 Xapian::TermIterator temp
= db
.termlist_begin(1);
1757 TEST_EXCEPTION(Xapian::DocNotFoundError
,
1758 Xapian::TermIterator t
= db
.termlist_begin(999999999));
1762 // tests that a Xapian::TermIterator works as an STL iterator
1763 DEFINE_TESTCASE(termlist2
, backend
) {
1764 Xapian::Database
db(get_database("apitest_onedoc"));
1765 Xapian::TermIterator t
= db
.termlist_begin(1);
1766 Xapian::TermIterator tend
= db
.termlist_end(1);
1768 // test operator= creates a copy which compares equal
1769 Xapian::TermIterator t_copy
= t
;
1770 TEST_EQUAL(t
, t_copy
);
1772 // test copy constructor creates a copy which compares equal
1773 Xapian::TermIterator
t_clone(t
);
1774 TEST_EQUAL(t
, t_clone
);
1776 vector
<string
> v(t
, tend
);
1778 t
= db
.termlist_begin(1);
1779 tend
= db
.termlist_end(1);
1780 vector
<string
>::const_iterator i
;
1781 for (i
= v
.begin(); i
!= v
.end(); ++i
) {
1782 TEST_NOT_EQUAL(t
, tend
);
1786 TEST_EQUAL(t
, tend
);
1790 static Xapian::TermIterator
1791 test_termlist3_helper()
1793 Xapian::Database
db(get_database("apitest_onedoc"));
1794 return db
.termlist_begin(1);
1797 // tests that a Xapian::TermIterator still works when the DB is deleted
1798 DEFINE_TESTCASE(termlist3
, backend
) {
1799 Xapian::TermIterator u
= test_termlist3_helper();
1800 Xapian::Database
db(get_database("apitest_onedoc"));
1801 Xapian::TermIterator t
= db
.termlist_begin(1);
1802 Xapian::TermIterator tend
= db
.termlist_end(1);
1813 DEFINE_TESTCASE(termlist4
, backend
) {
1814 Xapian::Database
db(get_database("apitest_onedoc"));
1815 Xapian::TermIterator i
= db
.termlist_begin(1);
1821 // tests punctuation is OK in terms (particularly in remote queries)
1822 DEFINE_TESTCASE(puncterms1
, backend
) {
1823 Xapian::Database
db(get_database("apitest_punc"));
1824 Xapian::Enquire
enquire(db
);
1826 Xapian::Query
q1("semi;colon");
1827 enquire
.set_query(q1
);
1828 Xapian::MSet m1
= enquire
.get_mset(0, 10);
1830 Xapian::Query
q2("col:on");
1831 enquire
.set_query(q2
);
1832 Xapian::MSet m2
= enquire
.get_mset(0, 10);
1834 Xapian::Query
q3("com,ma");
1835 enquire
.set_query(q3
);
1836 Xapian::MSet m3
= enquire
.get_mset(0, 10);
1841 // test that searching for a term with a space or backslash in it works
1842 DEFINE_TESTCASE(spaceterms1
, backend
) {
1843 Xapian::Enquire
enquire(get_database("apitest_space"));
1844 Xapian::MSet mymset
;
1845 Xapian::doccount count
;
1846 Xapian::MSetIterator m
;
1847 Xapian::Stem
stemmer("english");
1849 enquire
.set_query(stemmer("space man"));
1850 mymset
= enquire
.get_mset(0, 10);
1851 TEST_MSET_SIZE(mymset
, 1);
1853 for (m
= mymset
.begin(); m
!= mymset
.end(); ++m
) ++count
;
1854 TEST_EQUAL(count
, 1);
1856 for (Xapian::valueno value_no
= 1; value_no
< 7; ++value_no
) {
1857 TEST_NOT_EQUAL(mymset
.begin().get_document().get_data(), "");
1858 TEST_NOT_EQUAL(mymset
.begin().get_document().get_value(value_no
), "");
1861 enquire
.set_query(stemmer("tab\tby"));
1862 mymset
= enquire
.get_mset(0, 10);
1863 TEST_MSET_SIZE(mymset
, 1);
1865 for (m
= mymset
.begin(); m
!= mymset
.end(); ++m
) ++count
;
1866 TEST_EQUAL(count
, 1);
1868 for (Xapian::valueno value_no
= 0; value_no
< 7; ++value_no
) {
1869 string value
= mymset
.begin().get_document().get_value(value_no
);
1870 TEST_NOT_EQUAL(value
, "");
1871 if (value_no
== 0) {
1872 TEST(value
.size() > 262);
1873 TEST_EQUAL(static_cast<unsigned char>(value
[262]), 255);
1877 enquire
.set_query(stemmer("back\\slash"));
1878 mymset
= enquire
.get_mset(0, 10);
1879 TEST_MSET_SIZE(mymset
, 1);
1881 for (m
= mymset
.begin(); m
!= mymset
.end(); ++m
) ++count
;
1882 TEST_EQUAL(count
, 1);
1887 // test that XOR queries work
1888 DEFINE_TESTCASE(xor1
, backend
) {
1889 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1890 Xapian::Stem
stemmer("english");
1892 vector
<string
> terms
;
1893 terms
.push_back(stemmer("this"));
1894 terms
.push_back(stemmer("word"));
1895 terms
.push_back(stemmer("of"));
1897 Xapian::Query
query(Xapian::Query::OP_XOR
, terms
.begin(), terms
.end());
1898 enquire
.set_weighting_scheme(Xapian::BoolWeight());
1899 enquire
.set_query(query
);
1901 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
1902 // Docid this word of Match?
1909 mset_expect_order(mymset
, 1, 2, 5, 6);
1914 /// Test that weighted XOR queries work (bug fixed in 1.2.1 and 1.0.21).
1915 DEFINE_TESTCASE(xor2
, backend
) {
1916 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1917 Xapian::Stem
stemmer("english");
1919 vector
<string
> terms
;
1920 terms
.push_back(stemmer("this"));
1921 terms
.push_back(stemmer("word"));
1922 terms
.push_back(stemmer("of"));
1924 Xapian::Query
query(Xapian::Query::OP_XOR
, terms
.begin(), terms
.end());
1925 enquire
.set_query(query
);
1927 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
1928 // Docid LEN this word of Match?
1935 mset_expect_order(mymset
, 2, 1, 5, 6);
1940 // test Xapian::Database::get_document()
1941 DEFINE_TESTCASE(getdoc1
, backend
) {
1942 Xapian::Database
db(get_database("apitest_onedoc"));
1943 Xapian::Document
doc(db
.get_document(1));
1944 TEST_EXCEPTION(Xapian::InvalidArgumentError
, db
.get_document(0));
1945 TEST_EXCEPTION(Xapian::DocNotFoundError
, db
.get_document(999999999));
1946 TEST_EXCEPTION(Xapian::DocNotFoundError
, db
.get_document(123456789));
1947 TEST_EXCEPTION(Xapian::DocNotFoundError
, db
.get_document(3));
1948 TEST_EXCEPTION(Xapian::DocNotFoundError
, db
.get_document(2));
1949 // Check that Document works as a handle on modification
1950 // (this was broken for the first try at Xapian::Document prior to 0.7).
1951 Xapian::Document doc2
= doc
;
1952 doc
.set_data("modified!");
1953 TEST_EQUAL(doc
.get_data(), "modified!");
1954 TEST_EQUAL(doc
.get_data(), doc2
.get_data());
1958 // test whether operators with no elements work as a null query
1959 DEFINE_TESTCASE(emptyop1
, backend
) {
1960 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1961 vector
<Xapian::Query
> nullvec
;
1963 Xapian::Query
query1(Xapian::Query::OP_XOR
, nullvec
.begin(), nullvec
.end());
1965 enquire
.set_query(query1
);
1966 Xapian::MSet mymset
= enquire
.get_mset(0, 10);
1967 TEST_MSET_SIZE(mymset
, 0);
1968 // In Xapian < 1.3.0, this gave InvalidArgumentError (because
1969 // query1.empty()) but elsewhere we treat an empty query as just not
1970 // matching any documents, so we now do the same here too.
1971 TEST_EQUAL(enquire
.get_matching_terms_begin(1),
1972 enquire
.get_matching_terms_end(1));
1977 // Regression test for check_at_least SEGV when there are no matches.
1978 DEFINE_TESTCASE(checkatleast1
, backend
) {
1979 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1980 enquire
.set_query(Xapian::Query("thom"));
1981 Xapian::MSet mymset
= enquire
.get_mset(0, 10, 11);
1982 TEST_EQUAL(0, mymset
.size());
1987 // Regression test - if check_at_least was set we returned (check_at_least - 1)
1988 // results, rather than the requested msize. Fixed in 1.0.2.
1989 DEFINE_TESTCASE(checkatleast2
, backend
) {
1990 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
1991 enquire
.set_query(Xapian::Query("paragraph"));
1993 Xapian::MSet mymset
= enquire
.get_mset(0, 3, 10);
1994 TEST_MSET_SIZE(mymset
, 3);
1995 TEST_EQUAL(mymset
.get_matches_lower_bound(), 5);
1996 TEST_EQUAL(mymset
.get_uncollapsed_matches_lower_bound(), 5);
1998 mymset
= enquire
.get_mset(0, 2, 4);
1999 TEST_MSET_SIZE(mymset
, 2);
2000 TEST_REL(mymset
.get_matches_lower_bound(),>=,4);
2001 TEST_REL(mymset
.get_matches_lower_bound(),>=,4);
2002 TEST_REL(mymset
.get_uncollapsed_matches_lower_bound(),>=,4);
2003 TEST_REL(mymset
.get_uncollapsed_matches_lower_bound(),>=,4);
2008 // Feature tests - check_at_least with various sorting options.
2009 DEFINE_TESTCASE(checkatleast3
, backend
) {
2010 Xapian::Enquire
enquire(get_database("etext"));
2011 enquire
.set_query(Xapian::Query("prussian")); // 60 matches.
2013 for (int order
= 0; order
< 3; ++order
) {
2016 enquire
.set_docid_order(Xapian::Enquire::ASCENDING
);
2019 enquire
.set_docid_order(Xapian::Enquire::DESCENDING
);
2022 enquire
.set_docid_order(Xapian::Enquire::DONT_CARE
);
2026 for (int sort
= 0; sort
< 7; ++sort
) {
2027 bool reverse
= (sort
& 1);
2030 enquire
.set_sort_by_relevance();
2033 enquire
.set_sort_by_value(0, reverse
);
2036 enquire
.set_sort_by_value_then_relevance(0, reverse
);
2039 enquire
.set_sort_by_relevance_then_value(0, reverse
);
2043 Xapian::MSet mset
= enquire
.get_mset(0, 100, 500);
2044 TEST_MSET_SIZE(mset
, 60);
2045 TEST_EQUAL(mset
.get_matches_lower_bound(), 60);
2046 TEST_EQUAL(mset
.get_matches_estimated(), 60);
2047 TEST_EQUAL(mset
.get_matches_upper_bound(), 60);
2048 TEST_EQUAL(mset
.get_uncollapsed_matches_lower_bound(), 60);
2049 TEST_EQUAL(mset
.get_uncollapsed_matches_estimated(), 60);
2050 TEST_EQUAL(mset
.get_uncollapsed_matches_upper_bound(), 60);
2052 mset
= enquire
.get_mset(0, 50, 100);
2053 TEST_MSET_SIZE(mset
, 50);
2054 TEST_EQUAL(mset
.get_matches_lower_bound(), 60);
2055 TEST_EQUAL(mset
.get_matches_estimated(), 60);
2056 TEST_EQUAL(mset
.get_matches_upper_bound(), 60);
2057 TEST_EQUAL(mset
.get_uncollapsed_matches_lower_bound(), 60);
2058 TEST_EQUAL(mset
.get_uncollapsed_matches_estimated(), 60);
2059 TEST_EQUAL(mset
.get_uncollapsed_matches_upper_bound(), 60);
2061 mset
= enquire
.get_mset(0, 10, 50);
2062 TEST_MSET_SIZE(mset
, 10);
2063 TEST_REL(mset
.get_matches_lower_bound(),>=,50);
2064 TEST_REL(mset
.get_uncollapsed_matches_lower_bound(),>=,50);
2071 // tests all document postlists
2072 DEFINE_TESTCASE(allpostlist1
, backend
) {
2073 Xapian::Database
db(get_database("apitest_manydocs"));
2074 Xapian::PostingIterator i
= db
.postlist_begin("");
2076 while (i
!= db
.postlist_end("")) {
2083 i
= db
.postlist_begin("");
2085 while (i
!= db
.postlist_end("")) {
2099 static void test_emptyterm1_helper(Xapian::Database
& db
)
2101 // Don't bother with postlist_begin() because allpostlist tests cover that.
2102 TEST_EXCEPTION(Xapian::InvalidArgumentError
, db
.positionlist_begin(1, ""));
2103 TEST_EQUAL(db
.get_doccount(), db
.get_termfreq(""));
2104 TEST_EQUAL(db
.get_doccount() != 0, db
.term_exists(""));
2105 TEST_EQUAL(db
.get_doccount(), db
.get_collection_freq(""));
2108 // tests results of passing an empty term to various methods
2109 DEFINE_TESTCASE(emptyterm1
, backend
) {
2110 Xapian::Database
db(get_database("apitest_manydocs"));
2111 TEST_EQUAL(db
.get_doccount(), 512);
2112 test_emptyterm1_helper(db
);
2114 db
= get_database("apitest_onedoc");
2115 TEST_EQUAL(db
.get_doccount(), 1);
2116 test_emptyterm1_helper(db
);
2118 db
= get_database("");
2119 TEST_EQUAL(db
.get_doccount(), 0);
2120 test_emptyterm1_helper(db
);
2125 // Test for alldocs postlist with a sparse database.
2126 DEFINE_TESTCASE(alldocspl1
, writable
) {
2127 Xapian::WritableDatabase db
= get_writable_database();
2128 Xapian::Document doc
;
2130 doc
.add_value(0, "5");
2131 db
.replace_document(5, doc
);
2133 Xapian::PostingIterator i
= db
.postlist_begin("");
2134 TEST(i
!= db
.postlist_end(""));
2136 TEST_EQUAL(i
.get_doclength(), 0);
2137 TEST_EQUAL(i
.get_unique_terms(), 0);
2138 TEST_EQUAL(i
.get_wdf(), 1);
2140 TEST(i
== db
.postlist_end(""));
2145 // Test reading and writing a modified alldocspostlist.
2146 DEFINE_TESTCASE(alldocspl2
, writable
) {
2147 Xapian::PostingIterator i
, end
;
2149 Xapian::WritableDatabase db
= get_writable_database();
2150 Xapian::Document doc
;
2152 doc
.add_value(0, "5");
2153 db
.replace_document(5, doc
);
2155 // Test iterating before committing the changes.
2156 i
= db
.postlist_begin("");
2157 end
= db
.postlist_end("");
2160 TEST_EQUAL(i
.get_doclength(), 0);
2161 TEST_EQUAL(i
.get_unique_terms(), 0);
2162 TEST_EQUAL(i
.get_wdf(), 1);
2168 // Test iterating after committing the changes.
2169 i
= db
.postlist_begin("");
2170 end
= db
.postlist_end("");
2173 TEST_EQUAL(i
.get_doclength(), 0);
2174 TEST_EQUAL(i
.get_unique_terms(), 0);
2175 TEST_EQUAL(i
.get_wdf(), 1);
2179 // Add another document.
2180 doc
= Xapian::Document();
2182 doc
.add_value(0, "7");
2183 db
.replace_document(7, doc
);
2185 // Test iterating through before committing the changes.
2186 i
= db
.postlist_begin("");
2187 end
= db
.postlist_end("");
2190 TEST_EQUAL(i
.get_doclength(), 0);
2191 TEST_EQUAL(i
.get_unique_terms(), 0);
2192 TEST_EQUAL(i
.get_wdf(), 1);
2196 TEST_EQUAL(i
.get_doclength(), 0);
2197 TEST_EQUAL(i
.get_unique_terms(), 0);
2198 TEST_EQUAL(i
.get_wdf(), 1);
2202 // Delete the first document.
2203 db
.delete_document(5);
2205 // Test iterating through before committing the changes.
2206 i
= db
.postlist_begin("");
2207 end
= db
.postlist_end("");
2210 TEST_EQUAL(i
.get_doclength(), 0);
2211 TEST_EQUAL(i
.get_unique_terms(), 0);
2212 TEST_EQUAL(i
.get_wdf(), 1);
2216 // Test iterating through after committing the changes, and dropping the
2217 // reference to the main DB.
2219 i
= db
.postlist_begin("");
2220 end
= db
.postlist_end("");
2225 TEST_EQUAL(i
.get_doclength(), 0);
2226 TEST_EQUAL(i
.get_unique_terms(), 0);
2227 TEST_EQUAL(i
.get_wdf(), 1);
2234 // Feature test for Query::OP_SCALE_WEIGHT.
2235 DEFINE_TESTCASE(scaleweight1
, backend
) {
2236 Xapian::Database
db(get_database("apitest_phrase"));
2237 Xapian::Enquire
enq(db
);
2238 Xapian::QueryParser qp
;
2240 static const char * queries
[] = {
2243 "leave milk on fridge",
2244 "ordered milk operator",
2245 "ordered phrase operator",
2246 "leave \"milk on fridge\"",
2248 "leave \"milk notpresent\"",
2251 static const double multipliers
[] = {
2252 -1000000, -2.5, -1, -0.5, 0, 0.5, 1, 2.5, 1000000,
2256 for (const char **qstr
= queries
; *qstr
; ++qstr
) {
2258 Xapian::Query query1
= qp
.parse_query(*qstr
);
2259 tout
<< "query1: " << query1
.get_description() << endl
;
2260 for (const double *multp
= multipliers
; multp
[0] != multp
[1]; ++multp
) {
2261 double mult
= *multp
;
2263 TEST_EXCEPTION(Xapian::InvalidArgumentError
,
2264 Xapian::Query(Xapian::Query::OP_SCALE_WEIGHT
,
2268 Xapian::Query
query2(Xapian::Query::OP_SCALE_WEIGHT
, query1
, mult
);
2269 tout
<< "query2: " << query2
.get_description() << endl
;
2271 enq
.set_query(query1
);
2272 Xapian::MSet mset1
= enq
.get_mset(0, 20);
2273 enq
.set_query(query2
);
2274 Xapian::MSet mset2
= enq
.get_mset(0, 20);
2276 TEST_EQUAL(mset1
.size(), mset2
.size());
2278 Xapian::MSetIterator i1
, i2
;
2280 for (i1
= mset1
.begin(), i2
= mset2
.begin();
2281 i1
!= mset1
.end() && i2
!= mset2
.end(); ++i1
, ++i2
) {
2282 TEST_EQUAL_DOUBLE(i1
.get_weight() * mult
, i2
.get_weight());
2283 TEST_EQUAL(*i1
, *i2
);
2286 // Weights in mset2 are 0; so it should be sorted by docid.
2287 vector
<Xapian::docid
> ids1
;
2288 vector
<Xapian::docid
> ids2
;
2289 for (i1
= mset1
.begin(), i2
= mset2
.begin();
2290 i1
!= mset1
.end() && i2
!= mset2
.end(); ++i1
, ++i2
) {
2291 TEST_NOT_EQUAL_DOUBLE(i1
.get_weight(), 0);
2292 TEST_EQUAL_DOUBLE(i2
.get_weight(), 0);
2293 ids1
.push_back(*i1
);
2294 ids2
.push_back(*i2
);
2296 sort(ids1
.begin(), ids1
.end());
2297 TEST_EQUAL(ids1
, ids2
);
2304 // Test Query::OP_SCALE_WEIGHT being used to multiply some of the weights of a
2306 DEFINE_TESTCASE(scaleweight2
, backend
) {
2307 Xapian::Database
db(get_database("apitest_phrase"));
2308 Xapian::Enquire
enq(db
);
2309 Xapian::MSetIterator i
;
2311 Xapian::Query
query1("fridg");
2312 Xapian::Query
query2(Xapian::Query::OP_SCALE_WEIGHT
, query1
, 2.5);
2313 Xapian::Query
query3("milk");
2314 Xapian::Query
query4(Xapian::Query::OP_SCALE_WEIGHT
, query3
, 0);
2315 Xapian::Query
query5(Xapian::Query::OP_OR
, query2
, query4
);
2317 // query5 should first return the same results as query1, in the same
2318 // order, and then return the results of query3 which aren't also results
2319 // of query1, in ascending docid order. We test that this happens.
2321 // First, build a vector of docids matching the first part of the query,
2322 // and append the non-duplicate docids matching the second part of the
2324 vector
<Xapian::docid
> ids1
;
2325 set
<Xapian::docid
> idsin1
;
2326 vector
<Xapian::docid
> ids3
;
2328 enq
.set_query(query1
);
2329 Xapian::MSet mset1
= enq
.get_mset(0, 20);
2330 enq
.set_query(query3
);
2331 Xapian::MSet mset3
= enq
.get_mset(0, 20);
2332 TEST_NOT_EQUAL(mset1
.size(), 0);
2333 for (i
= mset1
.begin(); i
!= mset1
.end(); ++i
) {
2337 TEST_NOT_EQUAL(mset3
.size(), 0);
2338 for (i
= mset3
.begin(); i
!= mset3
.end(); ++i
) {
2339 if (idsin1
.find(*i
) != idsin1
.end())
2343 sort(ids3
.begin(), ids3
.end());
2344 ids1
.insert(ids1
.end(), ids3
.begin(), ids3
.end());
2346 // Now, run the combined query and build a vector of the matching docids.
2347 vector
<Xapian::docid
> ids5
;
2348 enq
.set_query(query5
);
2349 Xapian::MSet mset5
= enq
.get_mset(0, 20);
2350 for (i
= mset5
.begin(); i
!= mset5
.end(); ++i
) {
2354 TEST_EQUAL(ids1
, ids5
);
2358 // Regression test for bug fixed in 1.0.5 - this test would failed under
2359 // valgrind because it used an uninitialised value.
2360 DEFINE_TESTCASE(bm25weight1
, backend
) {
2361 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
2362 enquire
.set_weighting_scheme(Xapian::BM25Weight(1, 25, 1, 0.01, 0.5));
2363 enquire
.set_query(Xapian::Query("word") );
2365 Xapian::MSet mset
= enquire
.get_mset(0, 25);
2370 // Feature test for TradWeight.
2371 DEFINE_TESTCASE(tradweight1
, backend
) {
2372 Xapian::Enquire
enquire(get_database("apitest_simpledata"));
2373 enquire
.set_weighting_scheme(Xapian::TradWeight());
2374 enquire
.set_query(Xapian::Query("word") );
2376 Xapian::MSet mset
= enquire
.get_mset(0, 25);
2377 TEST_EQUAL(mset
.size(), 2);
2379 enquire
.set_weighting_scheme(Xapian::TradWeight(0));
2380 enquire
.set_query(Xapian::Query("this") );
2382 mset
= enquire
.get_mset(0, 25);
2383 TEST_EQUAL(mset
.size(), 6);
2385 // Check that TradWeight(0) means wdf and doc length really don't affect
2386 // the weights as stated in the documentation.
2387 TEST_EQUAL(mset
[0].get_weight(), mset
[5].get_weight());
2392 // Test TradWeight when weighting documents using an RSet.
2393 // Simply changed the weighting scheme used by rset2 testcase.
2394 DEFINE_TESTCASE(tradweight4
, backend
) {
2395 Xapian::Database
mydb(get_database("apitest_rset"));
2396 Xapian::Enquire
enquire(mydb
);
2397 Xapian::Query myquery
= query(Xapian::Query::OP_OR
, "cuddly", "people");
2399 enquire
.set_query(myquery
);
2400 enquire
.set_weighting_scheme(Xapian::TradWeight());
2402 Xapian::MSet mymset1
= enquire
.get_mset(0, 10);
2404 Xapian::RSet myrset
;
2405 myrset
.add_document(2);
2407 Xapian::MSet mymset2
= enquire
.get_mset(0, 10, &myrset
);
2409 mset_expect_order(mymset1
, 1, 2);
2410 // Document 2 should have higher weight than document 1 despite the wdf of
2411 // "people" being 1 because "people" indexes a document in the RSet whereas
2412 // "cuddly" (wdf=2) does not.
2413 mset_expect_order(mymset2
, 2, 1);
2418 // Feature test for Database::get_uuid().
2419 DEFINE_TESTCASE(uuid1
, backend
&& !multi
) {
2420 SKIP_TEST_FOR_BACKEND("inmemory");
2421 Xapian::Database db
= get_database("apitest_simpledata");
2422 string uuid1
= db
.get_uuid();
2423 TEST_EQUAL(uuid1
.size(), 36);
2425 // A database with no sub-databases has an empty UUID.
2426 Xapian::Database db2
;
2427 TEST(db2
.get_uuid().empty());
2429 db2
.add_database(db
);
2430 TEST_EQUAL(uuid1
, db2
.get_uuid());
2432 // Multi-database has multiple UUIDs (we don't define the format exactly
2433 // so this assumes something about the implementation).
2434 db2
.add_database(db
);
2435 TEST_EQUAL(uuid1
+ ":" + uuid1
, db2
.get_uuid());
2437 #ifdef XAPIAN_HAS_INMEMORY_BACKEND
2438 // This relies on InMemory databases not supporting uuids.
2439 // A multi-database containing a database with no uuid has no uuid.
2440 db2
.add_database(Xapian::InMemory::open());
2441 TEST(db2
.get_uuid().empty());