| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | |
|---|
| 21 | |
|---|
| 22 | |
|---|
| 23 | |
|---|
| 24 | #include <config.h> |
|---|
| 25 | |
|---|
| 26 | #include "api_nodb.h" |
|---|
| 27 | |
|---|
| 28 | #include <string> |
|---|
| 29 | #include <vector> |
|---|
| 30 | #include "autoptr.h" |
|---|
| 31 | |
|---|
| 32 | #include <xapian.h> |
|---|
| 33 | |
|---|
| 34 | #include "apitest.h" |
|---|
| 35 | #include "testsuite.h" |
|---|
| 36 | #include "testutils.h" |
|---|
| 37 | #include "utils.h" |
|---|
| 38 | |
|---|
| 39 | #include <list> |
|---|
| 40 | |
|---|
| 41 | using namespace std; |
|---|
| 42 | |
|---|
| 43 | |
|---|
| 44 | DEFINE_TESTCASE(trivial1, !backend) { |
|---|
| 45 | return true; |
|---|
| 46 | } |
|---|
| 47 | |
|---|
| 48 | |
|---|
| 49 | DEFINE_TESTCASE(getqterms1, !backend) { |
|---|
| 50 | list<string> answers_list; |
|---|
| 51 | answers_list.push_back("one"); |
|---|
| 52 | answers_list.push_back("two"); |
|---|
| 53 | answers_list.push_back("three"); |
|---|
| 54 | answers_list.push_back("four"); |
|---|
| 55 | |
|---|
| 56 | Xapian::Query myquery(Xapian::Query::OP_OR, |
|---|
| 57 | Xapian::Query(Xapian::Query::OP_AND, |
|---|
| 58 | Xapian::Query("one", 1, 1), |
|---|
| 59 | Xapian::Query("three", 1, 3)), |
|---|
| 60 | Xapian::Query(Xapian::Query::OP_OR, |
|---|
| 61 | Xapian::Query("four", 1, 4), |
|---|
| 62 | Xapian::Query("two", 1, 2))); |
|---|
| 63 | |
|---|
| 64 | list<string> list1; |
|---|
| 65 | { |
|---|
| 66 | Xapian::TermIterator t; |
|---|
| 67 | for (t = myquery.get_terms_begin(); t != myquery.get_terms_end(); ++t) |
|---|
| 68 | list1.push_back(*t); |
|---|
| 69 | } |
|---|
| 70 | TEST(list1 == answers_list); |
|---|
| 71 | list<string> list2(myquery.get_terms_begin(), myquery.get_terms_end()); |
|---|
| 72 | TEST(list2 == answers_list); |
|---|
| 73 | return true; |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | |
|---|
| 77 | |
|---|
| 78 | DEFINE_TESTCASE(getqterms2, !backend) { |
|---|
| 79 | Xapian::Query empty_query; |
|---|
| 80 | TEST_EQUAL(empty_query.get_terms_begin(), empty_query.get_terms_end()); |
|---|
| 81 | return true; |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | |
|---|
| 85 | DEFINE_TESTCASE(emptyquery2, !backend) { |
|---|
| 86 | |
|---|
| 87 | TEST(Xapian::Query().empty()); |
|---|
| 88 | |
|---|
| 89 | TEST(Xapian::Query().get_length() == 0); |
|---|
| 90 | vector<Xapian::Query> v; |
|---|
| 91 | TEST(Xapian::Query(Xapian::Query::OP_OR, v.begin(), v.end()).empty()); |
|---|
| 92 | TEST(Xapian::Query(Xapian::Query::OP_OR, v.begin(), v.end()).get_length() == 0); |
|---|
| 93 | return true; |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | |
|---|
| 97 | DEFINE_TESTCASE(emptyquery3, !backend) { |
|---|
| 98 | static const Xapian::Query::op ops[] = { |
|---|
| 99 | Xapian::Query::OP_AND, |
|---|
| 100 | Xapian::Query::OP_OR, |
|---|
| 101 | Xapian::Query::OP_XOR, |
|---|
| 102 | Xapian::Query::OP_AND_MAYBE, |
|---|
| 103 | Xapian::Query::OP_AND_NOT |
|---|
| 104 | }; |
|---|
| 105 | |
|---|
| 106 | for (size_t i = 0; i < sizeof(ops) / sizeof(ops[0]); ++i) { |
|---|
| 107 | tout << "Testing op #" << i << endl; |
|---|
| 108 | Xapian::Query empty; |
|---|
| 109 | Xapian::Query q("test"); |
|---|
| 110 | Xapian::Query qcombine(ops[i], empty, q); |
|---|
| 111 | tout << qcombine.get_description() << endl; |
|---|
| 112 | Xapian::Query qcombine2(ops[i], q, empty); |
|---|
| 113 | tout << qcombine2.get_description() << endl; |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | return true; |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | |
|---|
| 120 | DEFINE_TESTCASE(querylen1, !backend) { |
|---|
| 121 | |
|---|
| 122 | Xapian::Query myquery; |
|---|
| 123 | myquery = Xapian::Query(Xapian::Query::OP_OR, |
|---|
| 124 | Xapian::Query("foo"), |
|---|
| 125 | Xapian::Query("bar")); |
|---|
| 126 | myquery = Xapian::Query(Xapian::Query::OP_AND, |
|---|
| 127 | myquery, |
|---|
| 128 | Xapian::Query(Xapian::Query::OP_OR, |
|---|
| 129 | Xapian::Query("wibble"), |
|---|
| 130 | Xapian::Query("spoon"))); |
|---|
| 131 | |
|---|
| 132 | TEST_EQUAL(myquery.get_length(), 4); |
|---|
| 133 | TEST(!myquery.empty()); |
|---|
| 134 | return true; |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | |
|---|
| 138 | DEFINE_TESTCASE(querylen2, !backend) { |
|---|
| 139 | |
|---|
| 140 | string terms[3] = { |
|---|
| 141 | "foo", |
|---|
| 142 | "bar", |
|---|
| 143 | "baz" |
|---|
| 144 | }; |
|---|
| 145 | Xapian::Query queries[3] = { |
|---|
| 146 | Xapian::Query("wibble"), |
|---|
| 147 | Xapian::Query("wobble"), |
|---|
| 148 | Xapian::Query(Xapian::Query::OP_OR, string("jelly"), string("belly")) |
|---|
| 149 | }; |
|---|
| 150 | |
|---|
| 151 | Xapian::Query myquery; |
|---|
| 152 | vector<string> v1(terms, terms + 3); |
|---|
| 153 | vector<Xapian::Query> v2(queries, queries + 3); |
|---|
| 154 | vector<Xapian::Query *> v3; |
|---|
| 155 | AutoPtr<Xapian::Query> dynquery1(new Xapian::Query(Xapian::Query::OP_AND, |
|---|
| 156 | string("ball"), |
|---|
| 157 | string("club"))); |
|---|
| 158 | AutoPtr<Xapian::Query> dynquery2(new Xapian::Query("ring")); |
|---|
| 159 | v3.push_back(dynquery1.get()); |
|---|
| 160 | v3.push_back(dynquery2.get()); |
|---|
| 161 | |
|---|
| 162 | Xapian::Query myq1 = Xapian::Query(Xapian::Query::OP_AND, v1.begin(), v1.end()); |
|---|
| 163 | tout << "myq1=" << myq1 << "\n"; |
|---|
| 164 | TEST_EQUAL(myq1.get_length(), 3); |
|---|
| 165 | |
|---|
| 166 | Xapian::Query myq2_1 = Xapian::Query(Xapian::Query::OP_OR, v2.begin(), v2.end()); |
|---|
| 167 | tout << "myq2_1=" << myq2_1 << "\n"; |
|---|
| 168 | TEST_EQUAL(myq2_1.get_length(), 4); |
|---|
| 169 | |
|---|
| 170 | Xapian::Query myq2_2 = Xapian::Query(Xapian::Query::OP_AND, v3.begin(), v3.end()); |
|---|
| 171 | tout << "myq2_2=" << myq2_2 << "\n"; |
|---|
| 172 | TEST_EQUAL(myq2_2.get_length(), 3); |
|---|
| 173 | |
|---|
| 174 | Xapian::Query myq2 = Xapian::Query(Xapian::Query::OP_OR, myq2_1, myq2_2); |
|---|
| 175 | tout << "myq2=" << myq2 << "\n"; |
|---|
| 176 | TEST_EQUAL(myq2.get_length(), 7); |
|---|
| 177 | |
|---|
| 178 | myquery = Xapian::Query(Xapian::Query::OP_OR, myq1, myq2); |
|---|
| 179 | tout << "myquery=" << myquery << "\n"; |
|---|
| 180 | TEST_EQUAL(myquery.get_length(), 10); |
|---|
| 181 | |
|---|
| 182 | return true; |
|---|
| 183 | } |
|---|
| 184 | |
|---|
| 185 | |
|---|
| 186 | DEFINE_TESTCASE(queryvalid1, !backend) { |
|---|
| 187 | vector<Xapian::Query> v1; |
|---|
| 188 | |
|---|
| 189 | TEST_EXCEPTION(Xapian::InvalidArgumentError, |
|---|
| 190 | Xapian::Query(Xapian::Query::OP_AND_NOT, v1.begin(), v1.end())); |
|---|
| 191 | tout << "ANDNOT () checked" << endl; |
|---|
| 192 | v1.push_back(Xapian::Query("bad")); |
|---|
| 193 | TEST_EXCEPTION(Xapian::InvalidArgumentError, |
|---|
| 194 | Xapian::Query(Xapian::Query::OP_AND_NOT, v1.begin(), v1.end())); |
|---|
| 195 | tout << "ANDNOT (\"bad\") checked" << endl; |
|---|
| 196 | v1.clear(); |
|---|
| 197 | v1.push_back(Xapian::Query()); |
|---|
| 198 | TEST_EXCEPTION(Xapian::InvalidArgumentError, |
|---|
| 199 | Xapian::Query(Xapian::Query::OP_AND_NOT, v1.begin(), v1.end())); |
|---|
| 200 | tout << "ANDNOT (Xapian::Query()) checked" << endl; |
|---|
| 201 | Xapian::Query q2(Xapian::Query::OP_XOR, Xapian::Query("foo"), Xapian::Query("bar")); |
|---|
| 202 | tout << "XOR (\"foo\", \"bar\") checked" << endl; |
|---|
| 203 | return true; |
|---|
| 204 | } |
|---|
| 205 | |
|---|
| 206 | |
|---|
| 207 | DEFINE_TESTCASE(subqcollapse1, !backend) { |
|---|
| 208 | Xapian::Query queries1[3] = { |
|---|
| 209 | Xapian::Query("wibble"), |
|---|
| 210 | Xapian::Query("wobble"), |
|---|
| 211 | Xapian::Query(Xapian::Query::OP_OR, string("jelly"), string("belly")) |
|---|
| 212 | }; |
|---|
| 213 | |
|---|
| 214 | Xapian::Query queries2[3] = { |
|---|
| 215 | Xapian::Query(Xapian::Query::OP_AND, string("jelly"), string("belly")), |
|---|
| 216 | Xapian::Query("wibble"), |
|---|
| 217 | Xapian::Query("wobble") |
|---|
| 218 | }; |
|---|
| 219 | |
|---|
| 220 | vector<Xapian::Query> vec1(queries1, queries1 + 3); |
|---|
| 221 | Xapian::Query myquery1(Xapian::Query::OP_OR, vec1.begin(), vec1.end()); |
|---|
| 222 | TEST_EQUAL(myquery1.get_description(), |
|---|
| 223 | "Xapian::Query((wibble OR wobble OR jelly OR belly))"); |
|---|
| 224 | |
|---|
| 225 | vector<Xapian::Query> vec2(queries2, queries2 + 3); |
|---|
| 226 | Xapian::Query myquery2(Xapian::Query::OP_AND, vec2.begin(), vec2.end()); |
|---|
| 227 | TEST_EQUAL(myquery2.get_description(), |
|---|
| 228 | "Xapian::Query((jelly AND belly AND wibble AND wobble))"); |
|---|
| 229 | |
|---|
| 230 | return true; |
|---|
| 231 | } |
|---|
| 232 | |
|---|
| 233 | |
|---|
| 234 | DEFINE_TESTCASE(emptyquerypart1, !backend) { |
|---|
| 235 | vector<string> emptyterms; |
|---|
| 236 | Xapian::Query query(Xapian::Query::OP_OR, emptyterms.begin(), emptyterms.end()); |
|---|
| 237 | TEST(Xapian::Query(Xapian::Query::OP_AND, query, Xapian::Query("x")).empty()); |
|---|
| 238 | TEST(Xapian::Query(Xapian::Query::OP_AND, query, Xapian::Query("x")).get_length() == 0); |
|---|
| 239 | TEST(!Xapian::Query(Xapian::Query::OP_OR, query, Xapian::Query("x")).empty()); |
|---|
| 240 | TEST(Xapian::Query(Xapian::Query::OP_OR, query, Xapian::Query("x")).get_length() == 1); |
|---|
| 241 | return true; |
|---|
| 242 | } |
|---|
| 243 | |
|---|
| 244 | DEFINE_TESTCASE(singlesubq1, !backend) { |
|---|
| 245 | vector<string> oneterm; |
|---|
| 246 | oneterm.push_back("solo"); |
|---|
| 247 | Xapian::Query q_eliteset(Xapian::Query::OP_ELITE_SET, oneterm.begin(), oneterm.end(), 1); |
|---|
| 248 | Xapian::Query q_near(Xapian::Query::OP_NEAR, oneterm.begin(), oneterm.end(), 1); |
|---|
| 249 | Xapian::Query q_phrase(Xapian::Query::OP_PHRASE, oneterm.begin(), oneterm.end(), 1); |
|---|
| 250 | return true; |
|---|
| 251 | } |
|---|
| 252 | |
|---|
| 253 | DEFINE_TESTCASE(stemlangs1, !backend) { |
|---|
| 254 | string langs = Xapian::Stem::get_available_languages(); |
|---|
| 255 | tout << "available languages '" << langs << "'" << endl; |
|---|
| 256 | TEST(!langs.empty()); |
|---|
| 257 | |
|---|
| 258 | |
|---|
| 259 | langs += " da nl en fi fr de hu it no pt ro ru es sv tr"; |
|---|
| 260 | |
|---|
| 261 | string::size_type i = 0; |
|---|
| 262 | while (true) { |
|---|
| 263 | string::size_type spc = langs.find(' ', i); |
|---|
| 264 | |
|---|
| 265 | |
|---|
| 266 | TEST_NOT_EQUAL(i, spc); |
|---|
| 267 | |
|---|
| 268 | |
|---|
| 269 | |
|---|
| 270 | string language = langs.substr(i, spc - i); |
|---|
| 271 | tout << "checking language code '" << language << "' works" << endl; |
|---|
| 272 | Xapian::Stem stemmer(language); |
|---|
| 273 | |
|---|
| 274 | if (spc == string::npos) break; |
|---|
| 275 | i = spc + 1; |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | |
|---|
| 279 | TEST_EXCEPTION(Xapian::InvalidArgumentError, Xapian::Stem stemmer("bogus")); |
|---|
| 280 | |
|---|
| 281 | |
|---|
| 282 | Xapian::Stem stem_nothing = Xapian::Stem(""); |
|---|
| 283 | |
|---|
| 284 | return true; |
|---|
| 285 | } |
|---|
| 286 | |
|---|
| 287 | |
|---|
| 288 | DEFINE_TESTCASE(weight1, !backend) { |
|---|
| 289 | Xapian::Weight * wt; |
|---|
| 290 | |
|---|
| 291 | Xapian::BoolWeight boolweight; |
|---|
| 292 | TEST_EQUAL(boolweight.name(), "Bool"); |
|---|
| 293 | wt = Xapian::BoolWeight().unserialise(boolweight.serialise()); |
|---|
| 294 | TEST_EQUAL(boolweight.serialise(), wt->serialise()); |
|---|
| 295 | delete wt; |
|---|
| 296 | |
|---|
| 297 | Xapian::TradWeight tradweight_dflt; |
|---|
| 298 | Xapian::TradWeight tradweight(1.0); |
|---|
| 299 | TEST_EQUAL(tradweight.name(), "Trad"); |
|---|
| 300 | TEST_EQUAL(tradweight_dflt.serialise(), tradweight.serialise()); |
|---|
| 301 | wt = Xapian::TradWeight().unserialise(tradweight.serialise()); |
|---|
| 302 | TEST_EQUAL(tradweight.serialise(), wt->serialise()); |
|---|
| 303 | delete wt; |
|---|
| 304 | |
|---|
| 305 | Xapian::TradWeight tradweight2(2.0); |
|---|
| 306 | TEST_NOT_EQUAL(tradweight.serialise(), tradweight2.serialise()); |
|---|
| 307 | |
|---|
| 308 | Xapian::BM25Weight bm25weight_dflt; |
|---|
| 309 | Xapian::BM25Weight bm25weight(1, 0, 1, 0.5, 0.5); |
|---|
| 310 | TEST_EQUAL(bm25weight.name(), "BM25"); |
|---|
| 311 | TEST_EQUAL(bm25weight_dflt.serialise(), bm25weight.serialise()); |
|---|
| 312 | wt = Xapian::BM25Weight().unserialise(bm25weight.serialise()); |
|---|
| 313 | TEST_EQUAL(bm25weight.serialise(), wt->serialise()); |
|---|
| 314 | delete wt; |
|---|
| 315 | |
|---|
| 316 | Xapian::BM25Weight bm25weight2(1, 0.5, 1, 0.5, 0.5); |
|---|
| 317 | TEST_NOT_EQUAL(bm25weight.serialise(), bm25weight2.serialise()); |
|---|
| 318 | |
|---|
| 319 | return true; |
|---|
| 320 | } |
|---|
| 321 | |
|---|
| 322 | |
|---|
| 323 | DEFINE_TESTCASE(nosuchdb1, !backend) { |
|---|
| 324 | |
|---|
| 325 | TEST_EXCEPTION(Xapian::DatabaseOpeningError, |
|---|
| 326 | Xapian::Database db("NOsuChdaTabASe")); |
|---|
| 327 | return true; |
|---|
| 328 | } |
|---|
| 329 | |
|---|
| 330 | |
|---|
| 331 | DEFINE_TESTCASE(addvalue1, !backend) { |
|---|
| 332 | |
|---|
| 333 | Xapian::Document doc; |
|---|
| 334 | doc.add_value(1, "original"); |
|---|
| 335 | doc.add_value(1, "replacement"); |
|---|
| 336 | TEST_EQUAL(doc.get_value(1), "replacement"); |
|---|
| 337 | |
|---|
| 338 | doc.add_value(2, "too"); |
|---|
| 339 | doc.add_value(3, "free"); |
|---|
| 340 | doc.add_value(4, "for"); |
|---|
| 341 | |
|---|
| 342 | doc.remove_value(2); |
|---|
| 343 | doc.remove_value(4); |
|---|
| 344 | TEST_EQUAL(doc.get_value(0), ""); |
|---|
| 345 | TEST_EQUAL(doc.get_value(1), "replacement"); |
|---|
| 346 | TEST_EQUAL(doc.get_value(2), ""); |
|---|
| 347 | TEST_EQUAL(doc.get_value(3), "free"); |
|---|
| 348 | TEST_EQUAL(doc.get_value(4), ""); |
|---|
| 349 | |
|---|
| 350 | return true; |
|---|
| 351 | } |
|---|
| 352 | |
|---|
| 353 | |
|---|
| 354 | DEFINE_TESTCASE(poscollapse2, !backend) { |
|---|
| 355 | Xapian::Query q(Xapian::Query::OP_OR, Xapian::Query("this", 1, 1), Xapian::Query("this", 1, 1)); |
|---|
| 356 | TEST_EQUAL(q.get_length(), 2); |
|---|
| 357 | return true; |
|---|
| 358 | } |
|---|
| 359 | |
|---|
| 360 | |
|---|
| 361 | |
|---|
| 362 | DEFINE_TESTCASE(uninitdb1, !backend) { |
|---|
| 363 | Xapian::Database db; |
|---|
| 364 | TEST_EXCEPTION(Xapian::InvalidArgumentError, |
|---|
| 365 | Xapian::Enquire enq(db)); |
|---|
| 366 | return true; |
|---|
| 367 | } |
|---|
| 368 | |
|---|
| 369 | |
|---|
| 370 | DEFINE_TESTCASE(scaleweight3, !backend) { |
|---|
| 371 | Xapian::Query matchnothing(Xapian::Query::MatchNothing); |
|---|
| 372 | Xapian::Query query(Xapian::Query::OP_SCALE_WEIGHT, matchnothing, 3.0); |
|---|
| 373 | TEST_EQUAL(query.get_description(), "Xapian::Query()"); |
|---|
| 374 | return true; |
|---|
| 375 | } |
|---|
| 376 | |
|---|
| 377 | |
|---|
| 378 | DEFINE_TESTCASE(scaleweight4, !backend) { |
|---|
| 379 | |
|---|
| 380 | |
|---|
| 381 | double factor = 179.76931348623157e306; |
|---|
| 382 | double nearly1 = factor * (1.0 / factor); |
|---|
| 383 | |
|---|
| 384 | TEST_NOT_EQUAL(nearly1, 1.0); |
|---|
| 385 | Xapian::Query foo("foo"); |
|---|
| 386 | Xapian::Query foo_nearly1(Xapian::Query::OP_SCALE_WEIGHT, foo, nearly1); |
|---|
| 387 | TEST_EQUAL(foo_nearly1.get_description(), "Xapian::Query(foo)"); |
|---|
| 388 | |
|---|
| 389 | return true; |
|---|
| 390 | } |
|---|
| 391 | |
|---|
| 392 | |
|---|
| 393 | DEFINE_TESTCASE(rset4, !backend) { |
|---|
| 394 | Xapian::RSet rset; |
|---|
| 395 | rset.add_document(1); |
|---|
| 396 | |
|---|
| 397 | TEST_STRINGS_EQUAL(rset.get_description(), "RSet(RSet::Internal(1))"); |
|---|
| 398 | return true; |
|---|
| 399 | } |
|---|
| 400 | |
|---|
| 401 | |
|---|
| 402 | DEFINE_TESTCASE(opvaluege1, !backend) { |
|---|
| 403 | Xapian::Query query(Xapian::Query::OP_VALUE_GE, 0, ""); |
|---|
| 404 | TEST_STRINGS_EQUAL(query.get_description(), Xapian::Query::MatchAll.get_description()); |
|---|
| 405 | return true; |
|---|
| 406 | } |
|---|