tests/quartztest.cc

Go to the documentation of this file.
00001 /* quartztest.cc: test of the Quartz backend
00002  *
00003  * Copyright 1999,2000,2001 BrightStation PLC
00004  * Copyright 2002 Ananova Ltd
00005  * Copyright 2002,2003,2004,2005,2006,2007 Olly Betts
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License as
00009  * published by the Free Software Foundation; either version 2 of the
00010  * License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
00020  * USA
00021  */
00022 
00023 #include <config.h>
00024 
00025 // We have to use the deprecated Quartz::open() method.
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" // for mkdir for MSVC
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     // (7) db exists (create, overwrite)
00078     db = new QuartzDatabase(dbdir);
00079     TEST_EQUAL(db->get_doccount(), 0);
00080     db = 0; // Close the database - Cygwin can't delete a locked file...
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     // (8) db exists with data (create, overwrite)
00096     db = new QuartzDatabase(dbdir);
00097     db = 0; // Close the database - Cygwin can't delete a locked file...
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     // FIXME: this test is flawed as the database is entitled to autoflush
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     // FIXME: this test is flawed as the database is entitled to autoflush
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     // Xapian::DB_CREATE would fail with DatabaseCreateError
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     //        1234567812345678123456781234567812345678
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 // ========= END OF TESTS =========
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 }

Documentation for Xapian (version 1.0.10).
Generated on 24 Dec 2008 by Doxygen 1.5.2.