00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include "api_serialise.h"
00025
00026 #include <xapian.h>
00027
00028 #include <exception>
00029 #include <stdexcept>
00030
00031 #include "apitest.h"
00032 #include "testutils.h"
00033
00034 using namespace std;
00035
00036
00037 DEFINE_TESTCASE(serialise_document1, !backend) {
00038 Xapian::Document doc;
00039 doc.add_term("foo", 2);
00040 doc.add_posting("foo", 10);
00041 doc.add_value(1, "bar");
00042 doc.set_data("baz");
00043
00044 Xapian::Document doc2 = Xapian::Document::unserialise(doc.serialise());
00045
00046 TEST_EQUAL(doc.termlist_count(), doc2.termlist_count());
00047 TEST_EQUAL(doc.termlist_count(), 1);
00048 Xapian::TermIterator i;
00049 Xapian::PositionIterator j;
00050 Xapian::ValueIterator k;
00051
00052 i = doc.termlist_begin();
00053 TEST_NOT_EQUAL(i, doc.termlist_end());
00054 TEST_EQUAL(i.get_wdf(), 3);
00055 TEST_EQUAL(*i, "foo");
00056 TEST_EQUAL(i.positionlist_count(), 1);
00057 j = i.positionlist_begin();
00058 TEST_NOT_EQUAL(j, i.positionlist_end());
00059 TEST_EQUAL(*j, 10);
00060 ++j;
00061 TEST_EQUAL(j, i.positionlist_end());
00062 ++i;
00063 TEST_EQUAL(i, doc.termlist_end());
00064
00065 TEST_EQUAL(doc.values_count(), 1);
00066 k = doc.values_begin();
00067 TEST_NOT_EQUAL(k, doc.values_end());
00068 TEST_EQUAL(k.get_valueno(), 1);
00069 TEST_EQUAL(*k, "bar");
00070 ++k;
00071 TEST_EQUAL(k, doc.values_end());
00072
00073 TEST_EQUAL(doc.get_data(), "baz");
00074
00075 i = doc2.termlist_begin();
00076 TEST_NOT_EQUAL(i, doc2.termlist_end());
00077 TEST_EQUAL(i.get_wdf(), 3);
00078 TEST_EQUAL(*i, "foo");
00079 TEST_EQUAL(i.positionlist_count(), 1);
00080 j = i.positionlist_begin();
00081 TEST_NOT_EQUAL(j, i.positionlist_end());
00082 TEST_EQUAL(*j, 10);
00083 ++j;
00084 TEST_EQUAL(j, i.positionlist_end());
00085 ++i;
00086 TEST_EQUAL(i, doc2.termlist_end());
00087
00088 TEST_EQUAL(doc2.values_count(), 1);
00089 k = doc2.values_begin();
00090 TEST_NOT_EQUAL(k, doc2.values_end());
00091 TEST_EQUAL(k.get_valueno(), 1);
00092 TEST_EQUAL(*k, "bar");
00093 ++k;
00094 TEST_EQUAL(k, doc2.values_end());
00095
00096 TEST_EQUAL(doc2.get_data(), "baz");
00097
00098 return true;
00099 }
00100
00101
00102 DEFINE_TESTCASE(serialise_document2, writable) {
00103 Xapian::Document origdoc;
00104 origdoc.add_term("foo", 2);
00105 origdoc.add_posting("foo", 10);
00106 origdoc.add_value(1, "bar");
00107 origdoc.set_data("baz");
00108 Xapian::WritableDatabase db = get_writable_database();
00109 db.add_document(origdoc);
00110
00111 Xapian::Document doc = db.get_document(1);
00112
00113 Xapian::Document doc2 = Xapian::Document::unserialise(doc.serialise());
00114
00115 TEST_EQUAL(doc.termlist_count(), doc2.termlist_count());
00116 TEST_EQUAL(doc.termlist_count(), 1);
00117 Xapian::TermIterator i;
00118 Xapian::PositionIterator j;
00119 Xapian::ValueIterator k;
00120
00121 i = doc.termlist_begin();
00122 TEST_NOT_EQUAL(i, doc.termlist_end());
00123 TEST_EQUAL(i.get_wdf(), 3);
00124 TEST_EQUAL(*i, "foo");
00125 TEST_EQUAL(i.positionlist_count(), 1);
00126 j = i.positionlist_begin();
00127 TEST_NOT_EQUAL(j, i.positionlist_end());
00128 TEST_EQUAL(*j, 10);
00129 ++j;
00130 TEST_EQUAL(j, i.positionlist_end());
00131 ++i;
00132 TEST_EQUAL(i, doc.termlist_end());
00133
00134 TEST_EQUAL(doc.values_count(), 1);
00135 k = doc.values_begin();
00136 TEST_NOT_EQUAL(k, doc.values_end());
00137 TEST_EQUAL(k.get_valueno(), 1);
00138 TEST_EQUAL(*k, "bar");
00139 ++k;
00140 TEST_EQUAL(k, doc.values_end());
00141
00142 TEST_EQUAL(doc.get_data(), "baz");
00143
00144 i = doc2.termlist_begin();
00145 TEST_NOT_EQUAL(i, doc2.termlist_end());
00146 TEST_EQUAL(i.get_wdf(), 3);
00147 TEST_EQUAL(*i, "foo");
00148 TEST_EQUAL(i.positionlist_count(), 1);
00149 j = i.positionlist_begin();
00150 TEST_NOT_EQUAL(j, i.positionlist_end());
00151 TEST_EQUAL(*j, 10);
00152 ++j;
00153 TEST_EQUAL(j, i.positionlist_end());
00154 ++i;
00155 TEST_EQUAL(i, doc2.termlist_end());
00156
00157 TEST_EQUAL(doc2.values_count(), 1);
00158 k = doc2.values_begin();
00159 TEST_NOT_EQUAL(k, doc2.values_end());
00160 TEST_EQUAL(k.get_valueno(), 1);
00161 TEST_EQUAL(*k, "bar");
00162 ++k;
00163 TEST_EQUAL(k, doc2.values_end());
00164
00165 TEST_EQUAL(doc2.get_data(), "baz");
00166
00167 return true;
00168 }
00169
00170
00171 DEFINE_TESTCASE(serialise_query1, !backend) {
00172 Xapian::Query q;
00173 Xapian::Query q2 = Xapian::Query::unserialise(q.serialise());
00174 TEST_EQUAL(q.get_description(), q2.get_description());
00175 TEST_EQUAL(q.get_description(), "Xapian::Query()");
00176
00177 q = Xapian::Query("hello");
00178 q2 = Xapian::Query::unserialise(q.serialise());
00179 TEST_EQUAL(q.get_description(), q2.get_description());
00180 TEST_EQUAL(q.get_description(), "Xapian::Query(hello)");
00181
00182 q = Xapian::Query(Xapian::Query::OP_OR, Xapian::Query("hello"), Xapian::Query("world"));
00183 q2 = Xapian::Query::unserialise(q.serialise());
00184 TEST_EQUAL(q.get_description(), q2.get_description());
00185 TEST_EQUAL(q.get_description(), "Xapian::Query((hello OR world))");
00186
00187 return true;
00188 }
00189
00190
00191 DEFINE_TESTCASE(serialise_query2, !backend) {
00192 Xapian::ValueWeightPostingSource s1(10);
00193 Xapian::Query q(&s1);
00194 Xapian::Query q2 = Xapian::Query::unserialise(q.serialise());
00195 TEST_EQUAL(q.get_description(), q2.get_description());
00196 TEST_EQUAL(q.get_description(), "Xapian::Query(PostingSource(Xapian::ValueWeightPostingSource(slot=10)))");
00197
00198 Xapian::ValueMapPostingSource s2(11);
00199 s2.set_default_weight(5.0);
00200 q = Xapian::Query(&s2);
00201 q2 = Xapian::Query::unserialise(q.serialise());
00202 TEST_EQUAL(q.get_description(), q2.get_description());
00203 TEST_EQUAL(q.get_description(), "Xapian::Query(PostingSource(Xapian::ValueMapPostingSource(slot=11)))");
00204
00205 Xapian::FixedWeightPostingSource s3(5.5);
00206 q = Xapian::Query(&s3);
00207 q2 = Xapian::Query::unserialise(q.serialise());
00208 TEST_EQUAL(q.get_description(), q2.get_description());
00209 TEST_EQUAL(q.get_description(), "Xapian::Query(PostingSource(Xapian::FixedWeightPostingSource(wt=5.5)))");
00210
00211 return true;
00212 }
00213
00214
00215 DEFINE_TESTCASE(serialise_query3, !backend) {
00216 Xapian::ValueWeightPostingSource s1(10);
00217 Xapian::Query q(&s1);
00218 Xapian::Registry reg;
00219 Xapian::Query q2 = Xapian::Query::unserialise(q.serialise(), reg);
00220 TEST_EQUAL(q.get_description(), q2.get_description());
00221 TEST_EQUAL(q.get_description(), "Xapian::Query(PostingSource(Xapian::ValueWeightPostingSource(slot=10)))");
00222
00223 Xapian::ValueMapPostingSource s2(11);
00224 s2.set_default_weight(5.0);
00225 q = Xapian::Query(&s2);
00226 q2 = Xapian::Query::unserialise(q.serialise(), reg);
00227 TEST_EQUAL(q.get_description(), q2.get_description());
00228 TEST_EQUAL(q.get_description(), "Xapian::Query(PostingSource(Xapian::ValueMapPostingSource(slot=11)))");
00229
00230 Xapian::FixedWeightPostingSource s3(5.5);
00231 q = Xapian::Query(&s3);
00232 q2 = Xapian::Query::unserialise(q.serialise(), reg);
00233 TEST_EQUAL(q.get_description(), q2.get_description());
00234 TEST_EQUAL(q.get_description(), "Xapian::Query(PostingSource(Xapian::FixedWeightPostingSource(wt=5.5)))");
00235
00236 return true;
00237 }
00238
00239 class MyPostingSource2 : public Xapian::ValuePostingSource {
00240 std::string desc;
00241 public:
00242 MyPostingSource2(const std::string & desc_)
00243 : Xapian::ValuePostingSource(0), desc(desc_)
00244 {
00245 }
00246
00247 MyPostingSource2 * clone() const
00248 {
00249 return new MyPostingSource2(desc);
00250 }
00251
00252 std::string name() const {
00253 return "MyPostingSource2";
00254 }
00255
00256 std::string serialise() const {
00257 return desc;
00258 }
00259
00260 MyPostingSource2 * unserialise(const std::string & s) const {
00261 return new MyPostingSource2(s);
00262 }
00263
00264 Xapian::weight get_weight() const { return 1.0; }
00265
00266 std::string get_description() const {
00267 return "MyPostingSource2(" + desc + ")";
00268 }
00269 };
00270
00271
00272 DEFINE_TESTCASE(serialise_query4, !backend) {
00273 MyPostingSource2 s1("foo");
00274 Xapian::Query q(&s1);
00275 TEST_EQUAL(q.get_description(), "Xapian::Query(PostingSource(MyPostingSource2(foo)))");
00276 std::string serialised = q.serialise();
00277
00278 TEST_EXCEPTION(Xapian::InvalidArgumentError, Xapian::Query::unserialise(serialised));
00279 Xapian::Registry reg;
00280 TEST_EXCEPTION(Xapian::InvalidArgumentError, Xapian::Query::unserialise(serialised, reg));
00281
00282 reg.register_posting_source(s1);
00283 Xapian::Query q2 = Xapian::Query::unserialise(serialised, reg);
00284 TEST_EQUAL(q.get_description(), q2.get_description());
00285
00286 return true;
00287 }
00288
00290 DEFINE_TESTCASE(double_register_leak, !backend) {
00291 MyPostingSource2 s1("foo");
00292 Xapian::BM25Weight w1;
00293
00294 Xapian::Registry reg;
00295 reg.register_posting_source(s1);
00296 reg.register_posting_source(s1);
00297 reg.register_posting_source(s1);
00298
00299 reg.register_weighting_scheme(w1);
00300 reg.register_weighting_scheme(w1);
00301 reg.register_weighting_scheme(w1);
00302
00303 return true;
00304 }
00305
00306 class ExceptionalPostingSource : public Xapian::PostingSource {
00307 public:
00308 typedef enum { NONE, CLONE, DTOR } failmode;
00309
00310 failmode fail;
00311
00312 PostingSource * & allocated;
00313
00314 ExceptionalPostingSource(failmode fail_, PostingSource * & allocated_)
00315 : fail(fail_), allocated(allocated_) { }
00316
00317 ~ExceptionalPostingSource() {
00318 if (fail == DTOR) {
00319 throw runtime_error(string("arfle barfle gloop?"));
00320 }
00321 }
00322
00323 string name() const {
00324 return "ExceptionalPostingSource";
00325 }
00326
00327 PostingSource * clone() const {
00328 if (fail == CLONE)
00329 throw bad_alloc();
00330 allocated = new ExceptionalPostingSource(fail, allocated);
00331 return allocated;
00332 }
00333
00334 void init(const Xapian::Database &) { }
00335
00336 Xapian::doccount get_termfreq_min() const { return 0; }
00337 Xapian::doccount get_termfreq_est() const { return 1; }
00338 Xapian::doccount get_termfreq_max() const { return 2; }
00339
00340 void next(Xapian::weight) { }
00341
00342 void skip_to(Xapian::docid, Xapian::weight) { }
00343
00344 bool at_end() const { return true; }
00345 Xapian::docid get_docid() const { return 0; }
00346 };
00347
00349 DEFINE_TESTCASE(registry1, !backend) {
00350
00351 {
00352 Xapian::Registry reg;
00353
00354 Xapian::PostingSource * ptr = NULL;
00355 ExceptionalPostingSource eps(ExceptionalPostingSource::NONE, ptr);
00356 TEST_EXCEPTION(Xapian::UnimplementedError, eps.serialise());
00357 TEST_EXCEPTION(Xapian::UnimplementedError, eps.unserialise(string()));
00358 reg.register_posting_source(eps);
00359 try {
00360 Xapian::PostingSource * ptr_clone = NULL;
00361 ExceptionalPostingSource eps_clone(ExceptionalPostingSource::CLONE,
00362 ptr_clone);
00363 reg.register_posting_source(eps_clone);
00364 return false;
00365 } catch (const bad_alloc &) {
00366 }
00367
00368
00369 const Xapian::PostingSource * p;
00370 p = reg.get_posting_source("ExceptionalPostingSource");
00371 if (p) {
00372 TEST_EQUAL(p->name(), "ExceptionalPostingSource");
00373 }
00374 }
00375
00376
00377 {
00378 Xapian::Registry reg;
00379
00380 Xapian::PostingSource * ptr_dtor = NULL;
00381 ExceptionalPostingSource eps_dtor(ExceptionalPostingSource::DTOR,
00382 ptr_dtor);
00383 reg.register_posting_source(eps_dtor);
00384
00385 eps_dtor.fail = ExceptionalPostingSource::NONE;
00386
00387 try {
00388 Xapian::PostingSource * ptr = NULL;
00389 ExceptionalPostingSource eps(ExceptionalPostingSource::NONE, ptr);
00390 reg.register_posting_source(eps);
00391 return false;
00392 } catch (const runtime_error &) {
00393 }
00394
00395
00396 const Xapian::PostingSource * p;
00397 p = reg.get_posting_source("ExceptionalPostingSource");
00398 if (p) {
00399 TEST_EQUAL(p->name(), "ExceptionalPostingSource");
00400 }
00401
00402
00403
00404 operator delete(ptr_dtor);
00405 }
00406
00407 return true;
00408 }
00409
00410 class ExceptionalWeight : public Xapian::Weight {
00411 public:
00412 typedef enum { NONE, CLONE, DTOR } failmode;
00413
00414 failmode fail;
00415
00416 Weight * & allocated;
00417
00418 ExceptionalWeight(failmode fail_, Weight * & allocated_)
00419 : fail(fail_), allocated(allocated_) { }
00420
00421 ~ExceptionalWeight() {
00422 if (fail == DTOR) {
00423 throw runtime_error(string("arfle barfle gloop?"));
00424 }
00425 }
00426
00427 string name() const {
00428 return "ExceptionalWeight";
00429 }
00430
00431 Weight * clone() const {
00432 if (fail == CLONE)
00433 throw bad_alloc();
00434 allocated = new ExceptionalWeight(fail, allocated);
00435 return allocated;
00436 }
00437
00438 void init(double) { }
00439
00440 Xapian::weight get_sumpart(Xapian::termcount, Xapian::termcount) const {
00441 return 0;
00442 }
00443 Xapian::weight get_maxpart() const { return 0; }
00444
00445 Xapian::weight get_sumextra(Xapian::termcount) const { return 0; }
00446 Xapian::weight get_maxextra() const { return 0; }
00447 };
00448
00450 DEFINE_TESTCASE(registry2, !backend) {
00451
00452 {
00453 Xapian::Registry reg;
00454
00455 Xapian::Weight * ptr = NULL;
00456 ExceptionalWeight ewt(ExceptionalWeight::NONE, ptr);
00457 reg.register_weighting_scheme(ewt);
00458 try {
00459 Xapian::Weight * ptr_clone = NULL;
00460 ExceptionalWeight ewt_clone(ExceptionalWeight::CLONE,
00461 ptr_clone);
00462 reg.register_weighting_scheme(ewt_clone);
00463 return false;
00464 } catch (const bad_alloc &) {
00465 }
00466
00467
00468 const Xapian::Weight * p;
00469 p = reg.get_weighting_scheme("ExceptionalWeight");
00470 if (p) {
00471 TEST_EQUAL(p->name(), "ExceptionalWeight");
00472 }
00473 }
00474
00475
00476 {
00477 Xapian::Registry reg;
00478
00479 Xapian::Weight * ptr_dtor = NULL;
00480 ExceptionalWeight ewt_dtor(ExceptionalWeight::DTOR,
00481 ptr_dtor);
00482 reg.register_weighting_scheme(ewt_dtor);
00483
00484 ewt_dtor.fail = ExceptionalWeight::NONE;
00485
00486 try {
00487 Xapian::Weight * ptr = NULL;
00488 ExceptionalWeight ewt(ExceptionalWeight::NONE, ptr);
00489 reg.register_weighting_scheme(ewt);
00490 return false;
00491 } catch (const runtime_error &) {
00492 }
00493
00494
00495 const Xapian::Weight * p;
00496 p = reg.get_weighting_scheme("ExceptionalWeight");
00497 if (p) {
00498 TEST_EQUAL(p->name(), "ExceptionalWeight");
00499 }
00500
00501
00502
00503 operator delete(ptr_dtor);
00504 }
00505
00506 return true;
00507 }
00508
00509 class ExceptionalMatchSpy : public Xapian::MatchSpy {
00510 public:
00511 typedef enum { NONE, CLONE, DTOR } failmode;
00512
00513 failmode fail;
00514
00515 MatchSpy * & allocated;
00516
00517 ExceptionalMatchSpy(failmode fail_, MatchSpy * & allocated_)
00518 : fail(fail_), allocated(allocated_) { }
00519
00520 ~ExceptionalMatchSpy() {
00521 if (fail == DTOR) {
00522 throw runtime_error(string("arfle barfle gloop?"));
00523 }
00524 }
00525
00526 string name() const {
00527 return "ExceptionalMatchSpy";
00528 }
00529
00530 MatchSpy * clone() const {
00531 if (fail == CLONE)
00532 throw bad_alloc();
00533 allocated = new ExceptionalMatchSpy(fail, allocated);
00534 return allocated;
00535 }
00536
00537 void operator()(const Xapian::Document &, Xapian::weight) {
00538 }
00539 };
00540
00542 DEFINE_TESTCASE(registry3, !backend) {
00543
00544 {
00545 Xapian::Registry reg;
00546
00547 Xapian::MatchSpy * ptr = NULL;
00548 ExceptionalMatchSpy ems(ExceptionalMatchSpy::NONE, ptr);
00549 reg.register_match_spy(ems);
00550 try {
00551 Xapian::MatchSpy * ptr_clone = NULL;
00552 ExceptionalMatchSpy ems_clone(ExceptionalMatchSpy::CLONE,
00553 ptr_clone);
00554 reg.register_match_spy(ems_clone);
00555 return false;
00556 } catch (const bad_alloc &) {
00557 }
00558
00559
00560 const Xapian::MatchSpy * p;
00561 p = reg.get_match_spy("ExceptionalMatchSpy");
00562 if (p) {
00563 TEST_EQUAL(p->name(), "ExceptionalMatchSpy");
00564 }
00565 }
00566
00567
00568 {
00569 Xapian::Registry reg;
00570
00571 Xapian::MatchSpy * ptr_dtor = NULL;
00572 ExceptionalMatchSpy ems_dtor(ExceptionalMatchSpy::DTOR, ptr_dtor);
00573 reg.register_match_spy(ems_dtor);
00574
00575 ems_dtor.fail = ExceptionalMatchSpy::NONE;
00576
00577 try {
00578 Xapian::MatchSpy * ptr = NULL;
00579 ExceptionalMatchSpy ems(ExceptionalMatchSpy::NONE, ptr);
00580 reg.register_match_spy(ems);
00581 return false;
00582 } catch (const runtime_error &) {
00583 }
00584
00585
00586 const Xapian::MatchSpy * p;
00587 p = reg.get_match_spy("ExceptionalMatchSpy");
00588 if (p) {
00589 TEST_EQUAL(p->name(), "ExceptionalMatchSpy");
00590 }
00591
00592
00593
00594 operator delete(ptr_dtor);
00595 }
00596
00597 return true;
00598 }