Ticket #108: xapian-loadtest1.patch

File xapian-loadtest1.patch, 5.4 KB (added by Richard Boulton, 17 years ago)

Patch which adds a test for this bug

  • tests/loadtest.cc

     
     1/* loadtest.cc: test of Xapian under load
     2 *
     3 * Copyright 2007 Lemur Consulting Ltd
     4 *
     5 * This program is free software; you can redistribute it and/or
     6 * modify it under the terms of the GNU General Public License as
     7 * published by the Free Software Foundation; either version 2 of the
     8 * License, or (at your option) any later version.
     9 *
     10 * This program is distributed in the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 * GNU General Public License for more details.
     14 *
     15 * You should have received a copy of the GNU General Public License
     16 * along with this program; if not, write to the Free Software
     17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
     18 * USA
     19 */
     20
     21#include <config.h>
     22
     23#include "safeerrno.h"
     24
     25#include <xapian.h>
     26#include "testsuite.h"
     27#include "testutils.h"
     28#include "utils.h"
     29
     30#include <pthread.h>
     31#include <string>
     32
     33using namespace std;
     34
     35struct loadtest1_state
     36{
     37    string dbpath;
     38    int add_count;
     39    bool stop;
     40    Xapian::Error * adder_err;
     41    Xapian::Error * opener_err;
     42};
     43
     44static void * loadtest1_opener(void *state_p)
     45{
     46    struct loadtest1_state * state = (struct loadtest1_state *) state_p;
     47    try {
     48        while(!state->stop) {
     49            try {
     50                Xapian::Database db(state->dbpath);
     51                db.get_doccount();
     52            } catch(Xapian::DatabaseOpeningError & e) {
     53                // Ignore opening error (probably means the database was modified under us by the adder).
     54            } catch(Xapian::DatabaseModifiedError & e) {
     55                // Ignore - the database was modified under us by the adder.
     56            }
     57        }
     58    } catch (Xapian::Error &e) {
     59        state->opener_err = new Xapian::Error(e);
     60        state->stop = 1;
     61    }
     62    return NULL;
     63}
     64
     65static void * loadtest1_adder(void *state_p)
     66{
     67    struct loadtest1_state * state = (struct loadtest1_state *) state_p;
     68    try {
     69        Xapian::WritableDatabase dbw(state->dbpath, Xapian::DB_OPEN);
     70        while (!state->stop && state->add_count > 0) {
     71            Xapian::Document doc;
     72            dbw.add_document(doc);
     73            dbw.flush();
     74            state->add_count -= 1;
     75        }
     76    } catch (Xapian::Error &e) {
     77        state->adder_err = new Xapian::Error(e);
     78        state->stop = 1;
     79    }
     80    return NULL;
     81}
     82
     83static bool test_loadtest1()
     84{
     85    const char * tmpdir = ".loadtmp";
     86    string dbpath = string(tmpdir) + "/db1";
     87
     88    /* Clean up old directory and create an empty database. */
     89    rmdir(tmpdir);
     90    if (mkdir(tmpdir, 0700) == -1 && errno != EEXIST) {
     91        FAIL_TEST("Can't make directory `" << tmpdir << "'");
     92    }
     93    {
     94        Xapian::WritableDatabase(dbpath, Xapian::DB_CREATE_OR_OVERWRITE);
     95    }
     96
     97
     98    struct loadtest1_state state;
     99    state.dbpath = dbpath;
     100    state.add_count = 1000;
     101    state.stop = 0;
     102    state.adder_err = NULL;
     103    state.opener_err = NULL;
     104
     105    pthread_t opener_thread;
     106    int errnum = pthread_create(&opener_thread, NULL, loadtest1_opener, &state);
     107    if (errnum != 0) {
     108        FAIL_TEST("Can't make opener thread: " << errnum);
     109    }
     110
     111    pthread_t adder_thread;
     112    errnum = pthread_create(&adder_thread, NULL, loadtest1_adder, &state);
     113    if (errnum != 0) {
     114        FAIL_TEST("Can't make adder thread: " << errnum);
     115    }
     116
     117    errnum = pthread_join(adder_thread, NULL);
     118    if (errnum != 0) {
     119        FAIL_TEST("Can't join adder thread: " << errnum);
     120    }
     121    state.stop = 1;
     122
     123    errnum = pthread_join(opener_thread, NULL);
     124    if (errnum != 0) {
     125        FAIL_TEST("Can't join opener thread: " << errnum);
     126    }
     127
     128    if (state.adder_err != NULL) {
     129        FAIL_TEST("Error in adder thread: "
     130                  << state.adder_err->get_type()
     131                  << state.adder_err->get_msg());
     132    }
     133    if (state.opener_err != NULL) {
     134        FAIL_TEST("Error in opener thread: "
     135                  << state.opener_err->get_type()
     136                  << state.opener_err->get_msg());
     137    }
     138    TEST_EQUAL(state.add_count, 0);
     139
     140    return true;
     141}
     142
     143// ================================
     144// ========= END OF TESTS =========
     145// ================================
     146//
     147// The lists of tests to perform
     148test_desc tests[] = {
     149    {"loadtest1",       test_loadtest1},
     150    {0, 0}
     151};
     152
     153int main(int argc, char **argv)
     154{
     155    test_driver::parse_command_line(argc, argv);
     156    return test_driver::run(tests);
     157}
  • tests/Makefile.am

     
    4040## Test programs to be run
    4141TESTS = $(quartz_tests) $(remote_tests) \
    4242 apitest$(EXEEXT) internaltest$(EXEEXT) stemtest$(EXEEXT) \
    43  queryparsertest$(EXEEXT)
     43 queryparsertest$(EXEEXT) loadtest$(EXEEXT)
    4444
    4545## Programs to build
    4646check_PROGRAMS = $(quartz_check_programs) $(remote_check_programs) \
    47  apitest internaltest stemtest queryparsertest
     47 apitest internaltest stemtest queryparsertest loadtest
    4848
    4949# Make sure runtest is up to date before running tests
    5050check_SCRIPTS = runtest
     
    6363stemtest_LDFLAGS = @ldflags@
    6464stemtest_LDADD = ../libgetopt.la ../libxapian.la
    6565
     66loadtest_SOURCES = loadtest.cc $(testharness_sources)
     67loadtest_LDFLAGS = @ldflags@ -pthread
     68loadtest_LDADD = ../libgetopt.la ../libxapian.la
     69
    6670internaltest_SOURCES = internaltest.cc $(testharness_sources)
    6771internaltest_LDFLAGS = @ldflags@
    6872internaltest_LDADD = ../libgetopt.la ../libxapian.la