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
00026 #define XAPIAN_DEPRECATED(D) D
00027
00028 #include "safeerrno.h"
00029
00030 #include "unixcmds.h"
00031 #include "testsuite.h"
00032 #include "testutils.h"
00033 #include <xapian/error.h>
00034
00035 #include "quartz_database.h"
00036 #include "quartz_postlist.h"
00037 #include "bcursor.h"
00038 #include "quartz_utils.h"
00039 #include "utils.h"
00040
00041 #include <vector>
00042 #include <algorithm>
00043 using namespace std;
00044
00045 #include <sys/types.h>
00046 #include "safesysstat.h"
00047
00048 static string tmpdir;
00049
00050 static void makedir(const string &filename)
00051 {
00052 if (mkdir(filename, 0700) == -1 && errno != EEXIST) {
00053 FAIL_TEST("Couldn't create directory `" << filename << "' (" <<
00054 strerror(errno) << ")");
00055 }
00056 }
00057
00058 static void removedir(const string &filename)
00059 {
00060 rm_rf(filename);
00061 struct stat buf;
00062 if (stat(filename, &buf) == 0 || errno != ENOENT) {
00063 FAIL_TEST("Failed to remove directory `" << filename << "' (" <<
00064 strerror(errno) << ")");
00065 }
00066 }
00067
00069 static bool test_create1()
00070 {
00071 const string dbdir = tmpdir + "testdb_create1";
00072 removedir(dbdir);
00073
00074 Xapian::Internal::RefCntPtr<Xapian::Database::Internal> db;
00075 db = new QuartzWritableDatabase(dbdir, Xapian::DB_CREATE, 2048);
00076
00077
00078 db = new QuartzDatabase(dbdir);
00079 TEST_EQUAL(db->get_doccount(), 0);
00080 db = 0;
00081 db = new QuartzWritableDatabase(dbdir, Xapian::DB_CREATE_OR_OVERWRITE, 2048);
00082 TEST_EQUAL(db->get_doccount(), 0);
00083 Xapian::Document document_in;
00084 document_in.set_data("Foobar rising");
00085 document_in.add_value(7, "Value7");
00086 document_in.add_value(13, "Value13");
00087 document_in.add_posting("foobar", 1);
00088 document_in.add_posting("rising", 2);
00089 document_in.add_posting("foobar", 3);
00090 db->add_document(document_in);
00091 TEST_EQUAL(db->get_doccount(), 1);
00092 db->add_document(document_in);
00093 TEST_EQUAL(db->get_doccount(), 2);
00094
00095
00096 db = new QuartzDatabase(dbdir);
00097 db = 0;
00098 db = new QuartzWritableDatabase(dbdir, Xapian::DB_CREATE_OR_OVERWRITE, 2048);
00099 db->add_document(document_in);
00100 TEST_EQUAL(db->get_doccount(), 1);
00101
00102 return true;
00103 }
00104
00108 static bool test_adddoc1()
00109 {
00110 const string dbdir = tmpdir + "testdb_adddoc1";
00111 removedir(dbdir);
00112
00113 Xapian::Internal::RefCntPtr<Xapian::Database::Internal> db = new QuartzWritableDatabase(dbdir, Xapian::DB_CREATE, 2048);
00114
00115 TEST_EQUAL(db->get_doccount(), 0);
00116 TEST_EQUAL(db->get_avlength(), 0);
00117 Xapian::Document document;
00118 Xapian::docid did;
00119
00120 did = db->add_document(document);
00121 TEST_EQUAL(db->get_doccount(), 1);
00122 TEST_EQUAL(did, 1);
00123 TEST_EQUAL(db->get_avlength(), 0);
00124 #if 0
00125
00126 {
00127 Xapian::Internal::RefCntPtr<Xapian::Database::Internal> db_readonly = new QuartzDatabase(dbdir);
00128 TEST_EQUAL(db_readonly->get_doccount(), 0);
00129 TEST_EQUAL(db_readonly->get_avlength(), 0);
00130 }
00131 #endif
00132 db->flush();
00133 {
00134 Xapian::Internal::RefCntPtr<Xapian::Database::Internal> db_readonly = new QuartzDatabase(dbdir);
00135 TEST_EQUAL(db_readonly->get_doccount(), 1);
00136 TEST_EQUAL(db_readonly->get_avlength(), 0);
00137 }
00138
00139 db->delete_document(did);
00140 TEST_EQUAL(db->get_doccount(), 0);
00141 TEST_EQUAL(db->get_avlength(), 0);
00142 #if 0
00143
00144 {
00145 Xapian::Internal::RefCntPtr<Xapian::Database::Internal> db_readonly = new QuartzDatabase(dbdir);
00146 TEST_EQUAL(db_readonly->get_doccount(), 1);
00147 TEST_EQUAL(db_readonly->get_avlength(), 0);
00148 }
00149 #endif
00150 db->flush();
00151 {
00152 Xapian::Internal::RefCntPtr<Xapian::Database::Internal> db_readonly = new QuartzDatabase(dbdir);
00153 TEST_EQUAL(db_readonly->get_doccount(), 0);
00154 TEST_EQUAL(db_readonly->get_avlength(), 0);
00155 }
00156
00157 did = db->add_document(document);
00158 TEST_EQUAL(db->get_doccount(), 1);
00159 TEST_EQUAL(did, 2);
00160 TEST_EQUAL(db->get_avlength(), 0);
00161
00162 db->flush();
00163
00164 return true;
00165 }
00166
00168 static bool test_packint1()
00169 {
00170 TEST_EQUAL(pack_uint(0u), string("\0", 1));
00171 TEST_EQUAL(pack_uint(1u), string("\001", 1));
00172 TEST_EQUAL(pack_uint(127u), string("\177", 1));
00173 TEST_EQUAL(pack_uint(128u), string("\200\001", 2));
00174 TEST_EQUAL(pack_uint(0xffffu), string("\377\377\003", 3));
00175 TEST_EQUAL(pack_uint(0xffffffffu), string("\377\377\377\377\017", 5));
00176
00177 return true;
00178 }
00179
00181 static bool test_packint2()
00182 {
00183 string foo;
00184
00185 foo += pack_uint(3u);
00186 foo += pack_uint(12475123u);
00187 foo += pack_uint(128u);
00188 foo += pack_uint(0xffffffffu);
00189 foo += pack_uint(127u);
00190 foo += pack_uint(0u);
00191 foo += pack_uint(0xffffffffu);
00192 foo += pack_uint(0u);
00193 foo += pack_uint(82134u);
00194
00195 const char * p = foo.data();
00196 om_uint32 result;
00197
00198 TEST(unpack_uint(&p, foo.data() + foo.size(), &result));
00199 TEST_EQUAL(result, 3u);
00200 TEST(unpack_uint(&p, foo.data() + foo.size(), &result));
00201 TEST_EQUAL(result, 12475123u);
00202 TEST(unpack_uint(&p, foo.data() + foo.size(), &result));
00203 TEST_EQUAL(result, 128u);
00204 TEST(unpack_uint(&p, foo.data() + foo.size(), &result));
00205 TEST_EQUAL(result, 0xffffffffu);
00206 TEST(unpack_uint(&p, foo.data() + foo.size(), &result));
00207 TEST_EQUAL(result, 127u);
00208 TEST(unpack_uint(&p, foo.data() + foo.size(), &result));
00209 TEST_EQUAL(result, 0u);
00210 TEST(unpack_uint(&p, foo.data() + foo.size(), &result));
00211 TEST_EQUAL(result, 0xffffffffu);
00212 TEST(unpack_uint(&p, foo.data() + foo.size(), &result));
00213 TEST_EQUAL(result, 0u);
00214 TEST(unpack_uint(&p, foo.data() + foo.size(), &result));
00215 TEST_EQUAL(result, 82134u);
00216
00217 return true;
00218 }
00219
00221 static bool test_packint3()
00222 {
00223 string foo;
00224
00225 vector<unsigned int> ints;
00226 vector<string> strings;
00227
00228 ints.push_back(3u);
00229 ints.push_back(12475123u);
00230 ints.push_back(128u);
00231 ints.push_back(0xffffffffu);
00232 ints.push_back(127u);
00233 ints.push_back(256u);
00234 ints.push_back(254u);
00235 ints.push_back(255u);
00236 ints.push_back(0u);
00237 ints.push_back(0xffffffffu);
00238 ints.push_back(0u);
00239 ints.push_back(82134u);
00240
00241 vector<unsigned int>::const_iterator i;
00242 vector<string>::const_iterator j;
00243 for (i = ints.begin(); i != ints.end(); i++) {
00244 foo += pack_uint_preserving_sort(*i);
00245 strings.push_back(pack_uint_preserving_sort(*i));
00246 }
00247
00248 const char * p = foo.data();
00249 om_uint32 result;
00250 i = ints.begin();
00251 while (p != foo.data() + foo.size()) {
00252 TEST(i != ints.end());
00253 TEST(p != 0);
00254 TEST(unpack_uint_preserving_sort(&p, foo.data() + foo.size(), &result));
00255 TEST_EQUAL(result, *i);
00256 i++;
00257 }
00258 TEST(p != 0);
00259 TEST(i == ints.end());
00260
00261 sort(ints.begin(), ints.end());
00262 sort(strings.begin(), strings.end());
00263
00264 for (i = ints.begin(), j = strings.begin();
00265 i != ints.end() && j != strings.end();
00266 i++, j++) {
00267 TEST(pack_uint_preserving_sort(*i) == *j);
00268 }
00269
00270 return true;
00271 }
00272
00274 static bool test_unpackint1()
00275 {
00276 string foo;
00277 const char *p;
00278 om_uint32 result;
00279 bool success;
00280
00281 p = foo.data();
00282 success = unpack_uint(&p, foo.data() + foo.size(), &result);
00283 TEST(!success);
00284 TEST_EQUAL(p, 0);
00285
00286 foo = string("\000\002\301\001", 4);
00287 result = 1;
00288 p = foo.data();
00289
00290 success = unpack_uint(&p, foo.data() + foo.size(), &result);
00291 TEST(success);
00292 TEST_EQUAL(result, 0);
00293 TEST_EQUAL(p, reinterpret_cast<const char *>(foo.data() + 1));
00294
00295 success = unpack_uint(&p, foo.data() + foo.size(), &result);
00296 TEST(success);
00297 TEST_EQUAL(result, 2);
00298 TEST_EQUAL(p, foo.data() + 2);
00299
00300 success = unpack_uint(&p, foo.data() + foo.size(), &result);
00301 TEST(success);
00302 TEST_EQUAL(result, 65 + 128);
00303 TEST_EQUAL(p, foo.data() + 4);
00304
00305 success = unpack_uint(&p, foo.data() + foo.size(), &result);
00306 TEST(!success);
00307 TEST_EQUAL(p, 0);
00308
00309 foo = string("\377\377\377\377\017\377\377\377\377\020\007\200\200\200\200\200\200\200\000\200\200\200\200\200\200\001\200\200\200\200\200\200", 32);
00310 result = 1;
00311 p = foo.data();
00312
00313 success = unpack_uint(&p, foo.data() + foo.size(), &result);
00314 TEST(success);
00315 TEST_EQUAL(result, 0xffffffff);
00316 TEST_EQUAL(p, foo.data() + 5);
00317
00318 success = unpack_uint(&p, foo.data() + foo.size(), &result);
00319 TEST(!success);
00320 TEST_EQUAL(p, foo.data() + 10);
00321
00322 success = unpack_uint(&p, foo.data() + foo.size(), &result);
00323 TEST(success);
00324 TEST_EQUAL(result, 7);
00325 TEST_EQUAL(p, foo.data() + 11);
00326
00327 success = unpack_uint(&p, foo.data() + foo.size(), &result);
00328 TEST(!success);
00329 TEST_EQUAL(p, foo.data() + 19);
00330
00331 success = unpack_uint(&p, foo.data() + foo.size(), &result);
00332 TEST(!success);
00333 TEST_EQUAL(p, foo.data() + 26);
00334
00335 success = unpack_uint(&p, foo.data() + foo.size(), &result);
00336 TEST(!success);
00337 TEST_EQUAL(p, 0);
00338
00339 return true;
00340 }
00341
00343 static bool test_writelock1()
00344 {
00345 const string dbname = tmpdir + "writelock1";
00346 removedir(dbname);
00347
00348 Xapian::WritableDatabase writer = Xapian::Quartz::open(dbname, Xapian::DB_CREATE);
00349 TEST_EXCEPTION(Xapian::DatabaseLockError,
00350 Xapian::WritableDatabase writer2 = Xapian::Quartz::open(dbname, Xapian::DB_OPEN));
00351 TEST_EXCEPTION(Xapian::DatabaseLockError,
00352 Xapian::WritableDatabase writer2 = Xapian::Quartz::open(dbname, Xapian::DB_CREATE_OR_OVERWRITE));
00353
00354 TEST_EXCEPTION(Xapian::DatabaseLockError,
00355 Xapian::WritableDatabase writer2 = Xapian::Quartz::open(dbname, Xapian::DB_CREATE_OR_OPEN));
00356 return true;
00357 }
00358
00360 static bool test_packstring1()
00361 {
00362 string before;
00363 string after;
00364 string packed;
00365 const char *src;
00366 const char *src_end;
00367
00368 before = "foo";
00369 packed = pack_string_preserving_sort(before);
00370 if (verbose) { tout << "packed = `" << packed << "'\n"; }
00371 src = packed.data();
00372 src_end = src + packed.length();
00373 TEST(unpack_string_preserving_sort(&src, src_end, after));
00374 TEST(src == src_end);
00375 TEST(before == after);
00376
00377 before = "";
00378 packed = pack_string_preserving_sort(before);
00379 if (verbose) { tout << "packed = `" << packed << "'\n"; }
00380 src = packed.data();
00381 src_end = src + packed.length();
00382 TEST(unpack_string_preserving_sort(&src, src_end, after));
00383 TEST(src == src_end);
00384 TEST(before == after);
00385
00386 before = "length_8";
00387 packed = pack_string_preserving_sort(before);
00388 if (verbose) { tout << "packed = `" << packed << "'\n"; }
00389 src = packed.data();
00390 src_end = src + packed.length();
00391 TEST(unpack_string_preserving_sort(&src, src_end, after));
00392 TEST(src == src_end);
00393 TEST(before == after);
00394
00395 before = "Quite a long string, really";
00396 packed = pack_string_preserving_sort(before);
00397 if (verbose) { tout << "packed = `" << packed << "'\n"; }
00398 src = packed.data();
00399 src_end = src + packed.length();
00400 TEST(unpack_string_preserving_sort(&src, src_end, after));
00401 TEST(src == src_end);
00402 TEST(before == after);
00403
00404
00405 before = "Quite a long string - multiple of eight.";
00406 packed = pack_string_preserving_sort(before);
00407 if (verbose) { tout << "packed = `" << packed << "'\n"; }
00408 src = packed.data();
00409 src_end = src + packed.length();
00410 TEST(unpack_string_preserving_sort(&src, src_end, after));
00411 TEST(src == src_end);
00412 TEST(before == after);
00413
00414 return true;
00415 }
00416
00417
00418
00419
00420
00422 test_desc tests[] = {
00423 {"create1", test_create1},
00424 {"adddoc1", test_adddoc1},
00425 {"packint1", test_packint1},
00426 {"packint2", test_packint2},
00427 {"packint3", test_packint3},
00428 {"unpackint1", test_unpackint1},
00429 {"writelock1", test_writelock1},
00430 {"packstring1", test_packstring1},
00431 {0, 0}
00432 };
00433
00434 int main(int argc, char **argv)
00435 {
00436 tmpdir = ".quartztmp";
00437 removedir(tmpdir);
00438 makedir(tmpdir);
00439 tmpdir += '/';
00440 test_driver::parse_command_line(argc, argv);
00441 return test_driver::run(tests);
00442 }