00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025
00026 #include "api_matchspy.h"
00027
00028 #include <xapian.h>
00029
00030 #include "str.h"
00031 #include <cmath>
00032 #include <map>
00033 #include <vector>
00034
00035 #include "backendmanager.h"
00036 #include "testsuite.h"
00037 #include "testutils.h"
00038 #include "apitest.h"
00039
00040 using namespace std;
00041
00042
00043
00044
00045 class SimpleMatchSpy : public Xapian::MatchSpy {
00046 public:
00047
00048 std::vector<std::string> seen;
00049
00050 void operator()(const Xapian::Document &doc,
00051 Xapian::weight) {
00052
00053
00054
00055 seen.push_back(doc.get_data());
00056 }
00057 };
00058
00059
00060 DEFINE_TESTCASE(matchspy1, backend && !remote) {
00061 Xapian::Database db(get_database("apitest_simpledata"));
00062 Xapian::Enquire enquire(db);
00063 enquire.set_query(Xapian::Query("this"));
00064
00065 SimpleMatchSpy myspy;
00066
00067 Xapian::MSet nospymset = enquire.get_mset(0, 100);
00068 enquire.add_matchspy(&myspy);
00069 Xapian::MSet spymset = enquire.get_mset(0, 100);
00070
00071
00072 TEST_EQUAL(nospymset, spymset);
00073
00074 vector<bool> docid_checked(db.get_lastdocid());
00075
00076
00077
00078 Xapian::MSetIterator i = spymset.begin();
00079 TEST(i != spymset.end());
00080 TEST_EQUAL(spymset.size(), 6);
00081 TEST_EQUAL(myspy.seen.size(), spymset.size());
00082
00083 std::sort(myspy.seen.begin(), myspy.seen.end());
00084
00085 std::vector<std::string> seen2;
00086 for ( ; i != spymset.end(); ++i) {
00087 const Xapian::Document doc(i.get_document());
00088 seen2.push_back(doc.get_data());
00089 }
00090 std::sort(seen2.begin(), seen2.end());
00091
00092 TEST_EQUAL(myspy.seen.size(), seen2.size());
00093 std::vector<std::string>::const_iterator j = myspy.seen.begin();
00094 std::vector<std::string>::const_iterator j2 = seen2.begin();
00095 for (; j != myspy.seen.end(); ++j, ++j2) {
00096 TEST_EQUAL(*j, *j2);
00097 }
00098
00099 return true;
00100 }
00101
00102 static string values_to_repr(const Xapian::ValueCountMatchSpy & spy) {
00103 string resultrepr("|");
00104 for (Xapian::TermIterator i = spy.values_begin();
00105 i != spy.values_end();
00106 ++i) {
00107 resultrepr += *i;
00108 resultrepr += ':';
00109 resultrepr += str(i.get_termfreq());
00110 resultrepr += '|';
00111 }
00112 return resultrepr;
00113 }
00114
00115 static void
00116 make_matchspy2_db(Xapian::WritableDatabase &db, const string &)
00117 {
00118 for (int c = 1; c <= 25; ++c) {
00119 Xapian::Document doc;
00120 doc.set_data("Document " + str(c));
00121 int factors = 0;
00122 for (int factor = 1; factor <= c; ++factor) {
00123 doc.add_term("all");
00124 if (c % factor == 0) {
00125 doc.add_term("XFACT" + str(factor));
00126 ++factors;
00127 }
00128 }
00129
00130
00131 doc.add_value(0, str(factors));
00132
00133 doc.add_value(1, str(c % 10));
00134
00135 doc.add_value(2, "fish");
00136
00137 doc.add_value(3, str(str(c).size()));
00138
00139 db.add_document(doc);
00140 }
00141 }
00142
00143 DEFINE_TESTCASE(matchspy2, generated)
00144 {
00145 Xapian::Database db = get_database("matchspy2", make_matchspy2_db);
00146
00147 Xapian::ValueCountMatchSpy spy0(0);
00148 Xapian::ValueCountMatchSpy spy1(1);
00149 Xapian::ValueCountMatchSpy spy3(3);
00150
00151 Xapian::Enquire enq(db);
00152
00153 enq.set_query(Xapian::Query("all"));
00154
00155 enq.add_matchspy(&spy0);
00156 enq.add_matchspy(&spy1);
00157 enq.add_matchspy(&spy3);
00158 Xapian::MSet mset = enq.get_mset(0, 10);
00159
00160 TEST_EQUAL(spy0.get_total(), 25);
00161 TEST_EQUAL(spy1.get_total(), 25);
00162 TEST_EQUAL(spy3.get_total(), 25);
00163
00164 static const char * results[] = {
00165 "|1:1|2:9|3:3|4:7|5:1|6:3|8:1|",
00166 "|0:2|1:3|2:3|3:3|4:3|5:3|6:2|7:2|8:2|9:2|",
00167 "|1:9|2:16|",
00168 };
00169 TEST_STRINGS_EQUAL(values_to_repr(spy0), results[0]);
00170 TEST_STRINGS_EQUAL(values_to_repr(spy1), results[1]);
00171 TEST_STRINGS_EQUAL(values_to_repr(spy3), results[2]);
00172
00173 return true;
00174 }
00175
00176 DEFINE_TESTCASE(matchspy4, generated)
00177 {
00178 Xapian::Database db = get_database("matchspy2", make_matchspy2_db);
00179
00180
00181
00182
00183 Xapian::ValueCountMatchSpy spya0(0);
00184 Xapian::ValueCountMatchSpy spya1(1);
00185 Xapian::ValueCountMatchSpy spya3(3);
00186 Xapian::ValueCountMatchSpy spyb0(0);
00187 Xapian::ValueCountMatchSpy spyb1(1);
00188 Xapian::ValueCountMatchSpy spyb3(3);
00189
00190 Xapian::Enquire enqa(db);
00191 Xapian::Enquire enqb(db);
00192
00193 enqa.set_query(Xapian::Query("all"));
00194 enqb.set_query(Xapian::Query("all"));
00195
00196 enqa.add_matchspy(&spya0);
00197 enqa.add_matchspy(&spya1);
00198 enqa.add_matchspy(&spya3);
00199 enqb.add_matchspy(&spyb0);
00200 enqb.add_matchspy(&spyb1);
00201 enqb.add_matchspy(&spyb3);
00202
00203 Xapian::MSet mseta = enqa.get_mset(0, 10);
00204 enqb.set_sort_by_value(0, false);
00205 Xapian::MSet msetb = enqb.get_mset(0, 10, 100);
00206
00207 TEST_EQUAL(spya0.get_total(), 25);
00208 TEST_EQUAL(spya1.get_total(), 25);
00209 TEST_EQUAL(spya3.get_total(), 25);
00210 TEST_EQUAL(spyb0.get_total(), 25);
00211 TEST_EQUAL(spyb1.get_total(), 25);
00212 TEST_EQUAL(spyb3.get_total(), 25);
00213
00214 static const char * results[] = {
00215 "|2:9|4:7|3:3|6:3|1:1|5:1|8:1|",
00216 "|1:3|2:3|3:3|4:3|5:3|0:2|6:2|7:2|8:2|9:2|",
00217 "|",
00218 "|2:16|1:9|",
00219 "|2:9|4:7|3:3|6:3|1:1|5:1|8:1|",
00220 "|1:3|2:3|3:3|4:3|5:3|0:2|6:2|7:2|8:2|9:2|",
00221 "|",
00222 "|2:16|1:9|",
00223 NULL
00224 };
00225 std::vector<Xapian::ValueCountMatchSpy *> spies;
00226 spies.push_back(&spya0);
00227 spies.push_back(&spya1);
00228 spies.push_back(NULL);
00229 spies.push_back(&spya3);
00230 spies.push_back(&spyb0);
00231 spies.push_back(&spyb1);
00232 spies.push_back(NULL);
00233 spies.push_back(&spyb3);
00234 for (Xapian::valueno v = 0; results[v]; ++v) {
00235 tout << "value " << v << endl;
00236 Xapian::ValueCountMatchSpy * spy = spies[v];
00237 string allvals_str("|");
00238 if (spy != NULL) {
00239 size_t allvals_size = 0;
00240 for (Xapian::TermIterator i = spy->top_values_begin(100);
00241 i != spy->top_values_end(100);
00242 ++i, ++allvals_size) {
00243 allvals_str += *i;
00244 allvals_str += ':';
00245 allvals_str += str(i.get_termfreq());
00246 allvals_str += '|';
00247 }
00248 tout << allvals_str << endl;
00249 TEST_STRINGS_EQUAL(allvals_str, results[v]);
00250
00251 for (size_t count = 0; count < allvals_size; ++count) {
00252 tout << "count " << count << endl;
00253 for (Xapian::TermIterator i = spy->top_values_begin(100),
00254 j = spy->top_values_begin(count);
00255 i != spy->top_values_end(100) &&
00256 j != spy->top_values_end(count);
00257 ++i, ++j) {
00258 tout << "j " << j << endl;
00259 TEST_EQUAL(*i, *j);
00260 TEST_EQUAL(i.get_termfreq(), j.get_termfreq());
00261 }
00262 }
00263 }
00264 }
00265
00266 return true;
00267 }
00268
00269
00270 DEFINE_TESTCASE(matchspy5, backend)
00271 {
00272 Xapian::Database db(get_database("apitest_simpledata"));
00273 Xapian::Enquire enquire(db);
00274 enquire.set_query(Xapian::Query("this"));
00275
00276 Xapian::ValueCountMatchSpy myspy1(1);
00277 Xapian::ValueCountMatchSpy myspy2(1);
00278
00279 enquire.add_matchspy(&myspy1);
00280 enquire.add_matchspy(&myspy2);
00281 Xapian::MSet mymset = enquire.get_mset(0, 100);
00282 TEST_EQUAL(mymset.size(), 6);
00283
00284 Xapian::TermIterator i = myspy1.values_begin();
00285 TEST(i != myspy1.values_end());
00286 TEST(*i == "h");
00287 TEST_EQUAL(i.get_termfreq(), 5);
00288 ++i;
00289 TEST(i != myspy1.values_end());
00290 TEST(*i == "n");
00291 TEST_EQUAL(i.get_termfreq(), 1);
00292 ++i;
00293 TEST(i == myspy1.values_end());
00294
00295 i = myspy2.values_begin();
00296 TEST(i != myspy2.values_end());
00297 TEST(*i == "h");
00298 TEST_EQUAL(i.get_termfreq(), 5);
00299 ++i;
00300 TEST(i != myspy2.values_end());
00301 TEST(*i == "n");
00302 TEST_EQUAL(i.get_termfreq(), 1);
00303 ++i;
00304 TEST(i == myspy2.values_end());
00305
00306 return true;
00307 }
00308
00309 class MySpy : public Xapian::MatchSpy {
00310 void operator()(const Xapian::Document &, Xapian::weight) {
00311 }
00312 };
00313
00314
00315 DEFINE_TESTCASE(matchspy6, !backend)
00316 {
00317 MySpy spy;
00318
00319 TEST_EXCEPTION(Xapian::UnimplementedError, spy.clone());
00320 TEST_EXCEPTION(Xapian::UnimplementedError, spy.name());
00321 TEST_EXCEPTION(Xapian::UnimplementedError, spy.serialise());
00322 TEST_EXCEPTION(Xapian::UnimplementedError,
00323 spy.unserialise(std::string(), Xapian::Registry()));
00324 TEST_EXCEPTION(Xapian::UnimplementedError, spy.serialise_results());
00325 TEST_EXCEPTION(Xapian::UnimplementedError,
00326 spy.merge_results(std::string()));
00327 TEST_EQUAL(spy.get_description(), "Xapian::MatchSpy()");
00328
00329 return true;
00330 }