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 "soaktest/soaktest.h"
00025 #include "soaktest/soaktest_queries.h"
00026
00027 #include <xapian.h>
00028
00029 #include "backendmanager.h"
00030 #include "str.h"
00031 #include "testrunner.h"
00032 #include "testsuite.h"
00033 #include "testutils.h"
00034 #include "utils.h"
00035
00036 #include <list>
00037
00038 using namespace std;
00039
00045 static void
00046 builddb_queries1(Xapian::WritableDatabase &db, const string &arg)
00047 {
00048 unsigned int doccount = 1000;
00049 unsigned int maxtermsperfield = atoi(arg.c_str());
00050 for (unsigned int i = 0; i < doccount; ++i) {
00051 Xapian::Document doc;
00052 for (unsigned int j = randint(maxtermsperfield) + 1; j != 0; --j) {
00053 doc.add_term("N" + str(j));
00054 }
00055 db.add_document(doc);
00056 }
00057 db.commit();
00058 }
00059
00061 struct QueryBuilderEnv {
00063 list<Xapian::Query> pieces;
00064
00065 unsigned int maxtermsperfield;
00066 unsigned int maxchildren;
00067
00068 QueryBuilderEnv(unsigned int maxtermsperfield_,
00069 unsigned int maxchildren_)
00070 : maxtermsperfield(maxtermsperfield_),
00071 maxchildren(maxchildren_)
00072 {}
00073
00075 Xapian::Query pop() {
00076 if (pieces.empty()) return Xapian::Query();
00077 Xapian::Query result = pieces.front();
00078 pieces.pop_front();
00079 return result;
00080 }
00081
00083 list<Xapian::Query>::iterator pick(unsigned int num) {
00084 list<Xapian::Query>::iterator i = pieces.begin();
00085 for (unsigned int c = 0; c != num && i != pieces.end(); ++c, ++i) {}
00086 return i;
00087 }
00088 };
00089
00090 typedef void (*QueryStep)(QueryBuilderEnv &);
00091
00093 static void push_leaf_N(QueryBuilderEnv & env)
00094 {
00095 env.pieces.push_back(Xapian::Query(
00096 "N" + str(randint(env.maxtermsperfield) + 1)));
00097 }
00098
00104 static void combine_OR(QueryBuilderEnv & env)
00105 {
00106 list<Xapian::Query>::iterator i = env.pick(randint(env.maxchildren));
00107 Xapian::Query combined(Xapian::Query::OP_OR, env.pieces.begin(), i);
00108 env.pieces.erase(env.pieces.begin(), i);
00109 env.pieces.push_back(combined);
00110 }
00111
00117 static void combine_AND(QueryBuilderEnv & env)
00118 {
00119 list<Xapian::Query>::iterator i = env.pick(randint(env.maxchildren));
00120 Xapian::Query combined(Xapian::Query::OP_AND, env.pieces.begin(), i);
00121 env.pieces.erase(env.pieces.begin(), i);
00122 env.pieces.push_back(combined);
00123 }
00124
00130 static void combine_XOR(QueryBuilderEnv & env)
00131 {
00132 list<Xapian::Query>::iterator i = env.pick(randint(env.maxchildren));
00133 Xapian::Query combined(Xapian::Query::OP_XOR, env.pieces.begin(), i);
00134 env.pieces.erase(env.pieces.begin(), i);
00135 env.pieces.push_back(combined);
00136 }
00137
00143 static void combine_NOT(QueryBuilderEnv & env)
00144 {
00145 if (env.pieces.size() < 2) return;
00146 list<Xapian::Query>::iterator i = env.pick(2);
00147 Xapian::Query combined(Xapian::Query::OP_AND_NOT, env.pieces.begin(), i);
00148 env.pieces.erase(env.pieces.begin(), i);
00149 env.pieces.push_back(combined);
00150 }
00151
00153 class QueryBuilder {
00155 vector<QueryStep> options;
00156
00158 QueryBuilderEnv env;
00159
00161 unsigned int maxsteps;
00162
00163 public:
00164 QueryBuilder(unsigned int maxtermsperfield_,
00165 unsigned int maxchildren_,
00166 unsigned int maxsteps_)
00167 : env(maxtermsperfield_, maxchildren_),
00168 maxsteps(maxsteps_)
00169 {
00170
00171
00172 options.push_back(push_leaf_N);
00173 options.push_back(push_leaf_N);
00174 options.push_back(push_leaf_N);
00175 options.push_back(push_leaf_N);
00176 options.push_back(combine_OR);
00177 options.push_back(combine_AND);
00178 options.push_back(combine_XOR);
00179 options.push_back(combine_NOT);
00180 }
00181
00190 Xapian::Query make_query() {
00191 unsigned int steps = randint(maxsteps) + 1;
00192 while (steps-- != 0) {
00193 QueryStep & step = options[randint(options.size())];
00194 step(env);
00195 }
00196 return env.pop();
00197 }
00198 };
00199
00200
00201
00202
00203
00204 DEFINE_TESTCASE(queries1, writable && !remote && !inmemory) {
00205 unsigned int seed = initrand();
00206 unsigned int maxtermsperfield = 100;
00207 unsigned int repetitions = 10000;
00208 QueryBuilder builder(maxtermsperfield, 10, 10);
00209
00210 Xapian::Database db;
00211 string arg(str(maxtermsperfield));
00212 db = backendmanager->get_database("queries1_" + str(seed) + "_" + arg,
00213 builddb_queries1, arg);
00214
00215
00216
00217 initrand();
00218
00219 Xapian::Enquire enquire(db);
00220
00221 unsigned int count = 0;
00222 while (++count != repetitions) {
00223 Xapian::Query query(builder.make_query());
00224 tout.str(string());
00225 tout << "query " << count << ": " << query << "\n";
00226
00227 enquire.set_query(query);
00228 Xapian::MSet mset1 = enquire.get_mset(0, 1);
00229 Xapian::MSet mset10 = enquire.get_mset(0, 10);
00230 Xapian::MSet msetall = enquire.get_mset(0, db.get_doccount());
00231 tout << mset1 << "\n";
00232 tout << mset10 << "\n";
00233 tout << msetall << "\n";
00234 if (mset1.empty()) {
00235 TEST(mset10.empty());
00236 TEST(msetall.empty());
00237 continue;
00238 }
00239 TEST(mset_range_is_same(mset1, 0, msetall, 0, mset1.size()));
00240 TEST(mset_range_is_same(mset10, 0, msetall, 0, mset10.size()));
00241 }
00242
00243 return true;
00244 }