00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024
00025 #include "api_postingsource.h"
00026
00027 #include <xapian.h>
00028
00029 #include <string>
00030
00031 #include "testutils.h"
00032 #include "str.h"
00033 #include "apitest.h"
00034
00035 using namespace std;
00036
00037 class MyOddPostingSource : public Xapian::PostingSource {
00038 Xapian::doccount num_docs;
00039
00040 Xapian::doccount last_docid;
00041
00042 Xapian::docid did;
00043
00044 MyOddPostingSource(Xapian::doccount num_docs_,
00045 Xapian::doccount last_docid_)
00046 : num_docs(num_docs_), last_docid(last_docid_), did(0)
00047 { }
00048
00049 public:
00050 MyOddPostingSource(const Xapian::Database &db)
00051 : num_docs(db.get_doccount()), last_docid(db.get_lastdocid()), did(0)
00052 { }
00053
00054 PostingSource * clone() const { return new MyOddPostingSource(num_docs, last_docid); }
00055
00056 void init(const Xapian::Database &) { did = 0; }
00057
00058
00059 Xapian::doccount get_termfreq_min() const { return 0; }
00060
00061 Xapian::doccount get_termfreq_est() const { return num_docs / 2; }
00062
00063 Xapian::doccount get_termfreq_max() const { return num_docs; }
00064
00065 void next(Xapian::weight wt) {
00066 (void)wt;
00067 ++did;
00068 if (did % 2 == 0) ++did;
00069 }
00070
00071 void skip_to(Xapian::docid to_did, Xapian::weight wt) {
00072 (void)wt;
00073 did = to_did;
00074 if (did % 2 == 0) ++did;
00075 }
00076
00077 bool at_end() const {
00078
00079 return did > last_docid;
00080 }
00081
00082 Xapian::docid get_docid() const { return did; }
00083
00084 string get_description() const { return "MyOddPostingSource"; }
00085 };
00086
00087 DEFINE_TESTCASE(externalsource1, backend && !remote && !multi) {
00088
00089
00090
00091 Xapian::Database db(get_database("apitest_phrase"));
00092 Xapian::Enquire enq(db);
00093 MyOddPostingSource src(db);
00094
00095
00096 TEST_EXCEPTION(Xapian::InvalidArgumentError, Xapian::Query bad(NULL));
00097 Xapian::PostingSource * nullsrc = NULL;
00098 TEST_EXCEPTION(Xapian::InvalidArgumentError, Xapian::Query bad(nullsrc));
00099
00100 enq.set_query(Xapian::Query(&src));
00101
00102 Xapian::MSet mset = enq.get_mset(0, 10);
00103 mset_expect_order(mset, 1, 3, 5, 7, 9, 11, 13, 15, 17);
00104
00105 Xapian::Query q(Xapian::Query::OP_FILTER,
00106 Xapian::Query("leav"),
00107 Xapian::Query(&src));
00108 enq.set_query(q);
00109
00110 mset = enq.get_mset(0, 10);
00111 mset_expect_order(mset, 5, 7, 11, 13, 9);
00112
00113 return true;
00114 }
00115
00116
00117
00118
00119 DEFINE_TESTCASE(externalsource2, remote) {
00120 Xapian::Database db(get_database("apitest_phrase"));
00121 Xapian::Enquire enq(db);
00122 MyOddPostingSource src(db);
00123
00124 enq.set_query(Xapian::Query(&src));
00125
00126 TEST_EXCEPTION(Xapian::UnimplementedError,
00127 Xapian::MSet mset = enq.get_mset(0, 10));
00128
00129 Xapian::Query q(Xapian::Query::OP_FILTER,
00130 Xapian::Query("leav"),
00131 Xapian::Query(&src));
00132 enq.set_query(q);
00133
00134 TEST_EXCEPTION(Xapian::UnimplementedError,
00135 Xapian::MSet mset = enq.get_mset(0, 10));
00136
00137 return true;
00138 }
00139
00140 class MyOddWeightingPostingSource : public Xapian::PostingSource {
00141 Xapian::doccount num_docs;
00142
00143 Xapian::doccount last_docid;
00144
00145 Xapian::docid did;
00146
00147 MyOddWeightingPostingSource(Xapian::doccount num_docs_,
00148 Xapian::doccount last_docid_)
00149 : num_docs(num_docs_), last_docid(last_docid_), did(0)
00150 {
00151 set_maxweight(1000);
00152 }
00153
00154 public:
00155 MyOddWeightingPostingSource(const Xapian::Database &db)
00156 : num_docs(db.get_doccount()), last_docid(db.get_lastdocid()), did(0)
00157 { }
00158
00159 PostingSource * clone() const {
00160 return new MyOddWeightingPostingSource(num_docs, last_docid);
00161 }
00162
00163 void init(const Xapian::Database &) { did = 0; }
00164
00165 Xapian::weight get_weight() const {
00166 return (did % 2) ? 1000 : 0.001;
00167 }
00168
00169
00170 Xapian::doccount get_termfreq_min() const { return 0; }
00171
00172 Xapian::doccount get_termfreq_est() const { return num_docs / 2; }
00173
00174 Xapian::doccount get_termfreq_max() const { return num_docs; }
00175
00176 void next(Xapian::weight wt) {
00177 (void)wt;
00178 ++did;
00179 }
00180
00181 void skip_to(Xapian::docid to_did, Xapian::weight wt) {
00182 (void)wt;
00183 did = to_did;
00184 }
00185
00186 bool at_end() const {
00187
00188 return did > last_docid;
00189 }
00190
00191 Xapian::docid get_docid() const { return did; }
00192
00193 string get_description() const {
00194 return "MyOddWeightingPostingSource";
00195 }
00196 };
00197
00198
00199 DEFINE_TESTCASE(externalsource3, backend && !remote && !multi) {
00200
00201
00202
00203 Xapian::Database db(get_database("apitest_phrase"));
00204 Xapian::Enquire enq(db);
00205 MyOddWeightingPostingSource src(db);
00206
00207 enq.set_query(Xapian::Query(&src));
00208
00209 Xapian::MSet mset = enq.get_mset(0, 10);
00210 mset_expect_order(mset, 1, 3, 5, 7, 9, 11, 13, 15, 17, 2);
00211
00212 Xapian::Query q(Xapian::Query::OP_OR,
00213 Xapian::Query("leav"),
00214 Xapian::Query(&src));
00215 enq.set_query(q);
00216
00217 mset = enq.get_mset(0, 5);
00218 mset_expect_order(mset, 5, 7, 11, 13, 9);
00219
00220 tout << "max possible weight = " << mset.get_max_possible() << endl;
00221 TEST(mset.get_max_possible() > 1000);
00222
00223 enq.set_cutoff(0, 1000.001);
00224 mset = enq.get_mset(0, 10);
00225 mset_expect_order(mset, 5, 7, 11, 13, 9);
00226
00227 tout << "max possible weight = " << mset.get_max_possible() << endl;
00228 TEST(mset.get_max_possible() > 1000);
00229
00230 enq.set_query(Xapian::Query(q.OP_SCALE_WEIGHT, Xapian::Query(&src), 0.5));
00231 mset = enq.get_mset(0, 10);
00232 TEST(mset.empty());
00233
00234 TEST_EQUAL(mset.get_max_possible(), 500);
00235
00236 enq.set_query(Xapian::Query(q.OP_SCALE_WEIGHT, Xapian::Query(&src), 2));
00237 mset = enq.get_mset(0, 10);
00238 mset_expect_order(mset, 1, 3, 5, 7, 9, 11, 13, 15, 17);
00239
00240 TEST_EQUAL(mset.get_max_possible(), 2000);
00241
00242 return true;
00243 }
00244
00245 class MyDontAskWeightPostingSource : public Xapian::PostingSource {
00246 Xapian::doccount num_docs;
00247
00248 Xapian::doccount last_docid;
00249
00250 Xapian::docid did;
00251
00252 MyDontAskWeightPostingSource(Xapian::doccount num_docs_,
00253 Xapian::doccount last_docid_)
00254 : num_docs(num_docs_), last_docid(last_docid_), did(0)
00255 { }
00256
00257 public:
00258 MyDontAskWeightPostingSource() : Xapian::PostingSource() {}
00259
00260 PostingSource * clone() const { return new MyDontAskWeightPostingSource(num_docs, last_docid); }
00261
00262 void init(const Xapian::Database &db) {
00263 num_docs = db.get_doccount();
00264 last_docid = db.get_lastdocid();
00265 did = 0;
00266 }
00267
00268 Xapian::weight get_weight() const {
00269 FAIL_TEST("MyDontAskWeightPostingSource::get_weight() called");
00270 }
00271
00272
00273 Xapian::doccount get_termfreq_min() const { return num_docs; }
00274
00275 Xapian::doccount get_termfreq_est() const { return num_docs; }
00276
00277 Xapian::doccount get_termfreq_max() const { return num_docs; }
00278
00279 void next(Xapian::weight wt) {
00280 (void)wt;
00281 ++did;
00282 }
00283
00284 void skip_to(Xapian::docid to_did, Xapian::weight wt) {
00285 (void)wt;
00286 did = to_did;
00287 }
00288
00289 bool at_end() const {
00290
00291 return did > last_docid;
00292 }
00293
00294 Xapian::docid get_docid() const { return did; }
00295
00296 string get_description() const {
00297 return "MyDontAskWeightPostingSource";
00298 }
00299 };
00300
00301
00302 DEFINE_TESTCASE(externalsource4, backend && !remote) {
00303 Xapian::Database db(get_database("apitest_phrase"));
00304 Xapian::Enquire enq(db);
00305 MyDontAskWeightPostingSource src;
00306
00307 tout << "OP_SCALE_WEIGHT 0" << endl;
00308 enq.set_query(Xapian::Query(Xapian::Query::OP_SCALE_WEIGHT, Xapian::Query(&src), 0));
00309
00310 Xapian::MSet mset = enq.get_mset(0, 5);
00311 mset_expect_order(mset, 1, 2, 3, 4, 5);
00312
00313 tout << "OP_FILTER" << endl;
00314 Xapian::Query q(Xapian::Query::OP_FILTER,
00315 Xapian::Query("leav"),
00316 Xapian::Query(&src));
00317 enq.set_query(q);
00318
00319 mset = enq.get_mset(0, 5);
00320 mset_expect_order(mset, 8, 6, 4, 5, 7);
00321
00322 tout << "BoolWeight" << endl;
00323 enq.set_query(Xapian::Query(&src));
00324 enq.set_weighting_scheme(Xapian::BoolWeight());
00325
00326
00327
00328
00329 return true;
00330 }
00331
00332
00333 DEFINE_TESTCASE(valueweightsource1, backend) {
00334 Xapian::Database db(get_database("apitest_phrase"));
00335 Xapian::Enquire enq(db);
00336 Xapian::ValueWeightPostingSource src(11);
00337
00338
00339 tout << "RAW" << endl;
00340 enq.set_query(Xapian::Query(&src));
00341 Xapian::MSet mset = enq.get_mset(0, 5);
00342 mset_expect_order(mset, 3, 1, 2, 8, 14);
00343
00344
00345 tout << "OP_FILTER" << endl;
00346 Xapian::Query q(Xapian::Query::OP_FILTER,
00347 Xapian::Query("leav"),
00348 Xapian::Query(&src));
00349 enq.set_query(q);
00350 mset = enq.get_mset(0, 5);
00351 mset_expect_order(mset, 8, 6, 4, 5, 7);
00352
00353
00354 tout << "OP_FILTER other way" << endl;
00355 q = Xapian::Query(Xapian::Query::OP_FILTER,
00356 Xapian::Query(&src),
00357 Xapian::Query("leav"));
00358 enq.set_query(q);
00359 mset = enq.get_mset(0, 5);
00360 mset_expect_order(mset, 8, 14, 9, 13, 7);
00361
00362 return true;
00363 }
00364
00365
00366
00367 DEFINE_TESTCASE(valueweightsource2, valuestats) {
00368 Xapian::Database db(get_database("apitest_phrase"));
00369 Xapian::ValueWeightPostingSource src(11);
00370 src.init(db);
00371 TEST_EQUAL(src.get_termfreq_min(), 17);
00372 TEST_EQUAL(src.get_termfreq_est(), 17);
00373 TEST_EQUAL(src.get_termfreq_max(), 17);
00374 TEST_EQUAL(src.get_maxweight(), 135);
00375
00376 return true;
00377 }
00378
00379
00380 DEFINE_TESTCASE(valueweightsource3, valuestats && !multi) {
00381
00382 Xapian::Database db(get_database("apitest_phrase"));
00383 Xapian::ValueWeightPostingSource src(11);
00384 src.init(db);
00385 TEST(!src.at_end());
00386 src.skip_to(8, 0.0);
00387 TEST(!src.at_end());
00388 TEST_EQUAL(src.get_docid(), 8);
00389 src.skip_to(8, 0.0);
00390 TEST(!src.at_end());
00391 TEST_EQUAL(src.get_docid(), 8);
00392
00393 return true;
00394 }
00395
00396
00397 DEFINE_TESTCASE(fixedweightsource1, backend) {
00398 Xapian::Database db(get_database("apitest_phrase"));
00399 Xapian::Enquire enq(db);
00400 double wt = 5.6;
00401
00402 {
00403 Xapian::FixedWeightPostingSource src(wt);
00404
00405
00406 enq.set_query(Xapian::Query(&src));
00407 Xapian::MSet mset = enq.get_mset(0, 5);
00408 mset_expect_order(mset, 1, 2, 3, 4, 5);
00409
00410 for (Xapian::MSetIterator i = mset.begin(); i != mset.end(); ++i) {
00411 TEST_EQUAL(i.get_weight(), wt);
00412 }
00413 }
00414
00415
00416 {
00417
00418 Xapian::FixedWeightPostingSource src(wt);
00419 src.init(db);
00420
00421 src.next(1.0);
00422 TEST(!src.at_end());
00423 TEST_EQUAL(src.get_docid(), 1);
00424 src.next(1.0);
00425 TEST(!src.at_end());
00426 TEST_EQUAL(src.get_docid(), 2);
00427 src.skip_to(5, 1.0);
00428 TEST(!src.at_end());
00429 TEST_EQUAL(src.get_docid(), 5);
00430 src.next(wt * 2);
00431 TEST(src.at_end());
00432 }
00433 {
00434
00435 Xapian::FixedWeightPostingSource src(wt);
00436 src.init(db);
00437
00438 TEST_EQUAL(src.check(5, 1.0), true);
00439 TEST(!src.at_end());
00440 TEST_EQUAL(src.get_docid(), 5);
00441 src.next(1.0);
00442 TEST(!src.at_end());
00443 TEST_EQUAL(src.get_docid(), 6);
00444 }
00445 {
00446
00447 Xapian::FixedWeightPostingSource src(wt);
00448 src.init(db);
00449
00450 TEST_EQUAL(src.check(5, 1.0), true);
00451 TEST(!src.at_end());
00452 TEST_EQUAL(src.get_docid(), 5);
00453 src.skip_to(6, 1.0);
00454 TEST(!src.at_end());
00455 TEST_EQUAL(src.get_docid(), 6);
00456 src.skip_to(7, wt * 2);
00457 TEST(src.at_end());
00458 }
00459
00460 return true;
00461 }
00462
00463
00464 class ChangeMaxweightPostingSource : public Xapian::PostingSource {
00465 Xapian::docid did;
00466
00467
00468 Xapian::docid maxid_accessed;
00469
00470 public:
00471 ChangeMaxweightPostingSource(Xapian::docid maxid_accessed_)
00472 : did(0), maxid_accessed(maxid_accessed_) { }
00473
00474 void init(const Xapian::Database &) { did = 0; }
00475
00476 Xapian::weight get_weight() const {
00477 if (did > maxid_accessed) {
00478 FAIL_TEST("ChangeMaxweightPostingSource::get_weight() called "
00479 "for docid " + str(did) + ", max id accessed "
00480 "should be " + str(maxid_accessed));
00481 }
00482 return 5 - did;
00483 }
00484
00485 Xapian::doccount get_termfreq_min() const { return 4; }
00486 Xapian::doccount get_termfreq_est() const { return 4; }
00487 Xapian::doccount get_termfreq_max() const { return 4; }
00488
00489 void next(Xapian::weight) {
00490 ++did;
00491 set_maxweight(5 - did);
00492 }
00493
00494 void skip_to(Xapian::docid to_did, Xapian::weight) {
00495 did = to_did;
00496 set_maxweight(5 - did);
00497 }
00498
00499 bool at_end() const { return did >= 5; }
00500 Xapian::docid get_docid() const { return did; }
00501 string get_description() const { return "ChangeMaxweightPostingSource"; }
00502 };
00503
00504
00505 DEFINE_TESTCASE(changemaxweightsource1, backend && !remote && !multi) {
00506
00507 Xapian::Database db(get_database("apitest_phrase"));
00508 Xapian::Enquire enq(db);
00509
00510 {
00511 ChangeMaxweightPostingSource src1(5);
00512 Xapian::FixedWeightPostingSource src2(2.5);
00513
00514 Xapian::Query q(Xapian::Query::OP_AND,
00515 Xapian::Query(&src1), Xapian::Query(&src2));
00516 enq.set_query(q);
00517
00518
00519 enq.set_docid_order(enq.DESCENDING);
00520
00521 Xapian::MSet mset = enq.get_mset(0, 4);
00522 TEST(src1.at_end());
00523 mset_expect_order(mset, 1, 2, 3, 4);
00524 for (Xapian::MSetIterator i = mset.begin(); i != mset.end(); ++i) {
00525 TEST_EQUAL_DOUBLE(i.get_weight(), 7.5 - *i);
00526 }
00527 }
00528
00529 {
00530 ChangeMaxweightPostingSource src1(3);
00531 Xapian::FixedWeightPostingSource src2(2.5);
00532
00533 Xapian::Query q(Xapian::Query::OP_AND,
00534 Xapian::Query(&src1), Xapian::Query(&src2));
00535 enq.set_query(q);
00536
00537 Xapian::MSet mset = enq.get_mset(0, 2);
00538 TEST(!src1.at_end());
00539 TEST_EQUAL(src1.get_docid(), 3);
00540 TEST_EQUAL_DOUBLE(src1.get_maxweight(), 2.0);
00541 mset_expect_order(mset, 1, 2);
00542 for (Xapian::MSetIterator i = mset.begin(); i != mset.end(); ++i) {
00543 TEST_EQUAL_DOUBLE(i.get_weight(), 7.5 - *i);
00544 }
00545 }
00546
00547 return true;
00548 }
00549
00550
00551 DEFINE_TESTCASE(emptyvalwtsource1, backend && !remote && !multi) {
00552 Xapian::Database db(get_database("apitest_phrase"));
00553 Xapian::Enquire enq(db);
00554
00555 Xapian::ValueWeightPostingSource src2(11);
00556 Xapian::ValueWeightPostingSource src3(100);
00557 Xapian::Query q1("leav");
00558 Xapian::Query q2(&src2);
00559 Xapian::Query q3(&src3);
00560 Xapian::Query q(Xapian::Query::OP_OR, Xapian::Query(Xapian::Query::OP_AND_MAYBE, q1, q2), q3);
00561
00562
00563 Xapian::doccount size1;
00564 {
00565 enq.set_query(q1);
00566 Xapian::MSet mset = enq.get_mset(0, 10);
00567 TEST_REL(mset.get_max_possible(), >, 0.0);
00568 size1 = mset.size();
00569 TEST_REL(size1, >, 0);
00570 }
00571
00572
00573
00574 {
00575 enq.set_query(q2);
00576 Xapian::MSet mset = enq.get_mset(0, 10);
00577 TEST_REL(mset.get_max_possible(), >, 0.0);
00578 TEST_REL(mset.size(), >, 0);
00579 }
00580
00581
00582
00583 {
00584 enq.set_query(q3);
00585 Xapian::MSet mset = enq.get_mset(0, 10);
00586
00587
00588
00589
00590 TEST_REL(mset.get_max_possible(), >=, 0.0);
00591
00592 TEST_EQUAL(mset.size(), 0);
00593 }
00594
00595
00596
00597 {
00598 enq.set_query(q);
00599 Xapian::MSet mset = enq.get_mset(0, 10);
00600 TEST_REL(mset.get_max_possible(), >, 0.0);
00601 TEST_REL(mset.size(), >, 0.0);
00602 TEST_EQUAL(mset.size(), size1);
00603 }
00604
00605 return true;
00606 }