From 7e694406d3a5befc6c7c864fec98f122131902b9 Mon Sep 17 00:00:00 2001 From: Leif Walsh <leif@tokutek.com> Date: Tue, 16 Apr 2013 23:59:41 -0400 Subject: [PATCH] [t:3638] merging stress-test to mainline, it passes git-svn-id: file:///svn/toku/tokudb@32643 c7de825b-a66e-492c-adef-691d508d4ae1 --- src/tests/stress-test.c | 217 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 src/tests/stress-test.c diff --git a/src/tests/stress-test.c b/src/tests/stress-test.c new file mode 100644 index 0000000000..96c25102e0 --- /dev/null +++ b/src/tests/stress-test.c @@ -0,0 +1,217 @@ +/* -*- mode: C; c-basic-offset: 4 -*- */ +#ident "Copyright (c) 2011 Tokutek Inc. All rights reserved." +#ident "$Id$" + +#include "test.h" + +enum state { + UNTOUCHED = 0, + INSERTED, + DELETED +}; +struct pair { + DBT key, val; + enum state state; +}; + +#define NKEYS (1<<20) +#define NDELS (1<<17) + +int keys[NKEYS]; +struct pair pairs[NKEYS]; +struct pair sorted[NKEYS]; +int dels[NDELS]; + +char some_data[200] = ("abetefocebbrk3894d,h" + "tebe73t90htb349i83d4" + "h3498bk4onhaosnetkb0" + "bk934bkgpbk0,8kh4c.r" + "bk9,438k4bkr,09k8hkb" + "bk9,gr,gkhb,k9,.bkg," + "b4kg4,39k,3k890,.bkr" + "bugk349kc,b.rk,.0k8," + "bkreb,0k8.p,k,r,bkhr" + "kb.rpgxbeu0xcehu te"); + +static int +pair_cmp(const void *a, const void *b) +{ + const struct pair *p1 = a, *p2 = b; + if (p1->key.size < p2->key.size) { + return memcmp(p1->key.data, p2->key.data, p1->key.size) || -1; + } else if (p1->key.size > p2->key.size) { + return memcmp(p1->key.data, p2->key.data, p2->key.size) || 1; + } else { + return memcmp(p1->key.data, p2->key.data, p1->key.size); + } +} + +static void +gen_data(void) +{ + srandom(0); + for (int i = 0; i < NKEYS; ++i) { + keys[i] = htonl(i); + } + for (int e = NKEYS-1; e > 0; --e) { + int r = random() % e; + int t = keys[r]; + keys[r] = keys[e]; + keys[e] = t; + } + for (int i = 0; i < NKEYS; ++i) { + int vallen = random() % 150; + int idx = random() % (200 - vallen); + dbt_init(&pairs[i].key, &keys[i], sizeof keys[i]); + dbt_init(&pairs[i].val, &some_data[idx], vallen); + pairs[i].state = UNTOUCHED; + } + + for (int i = 0; i < NDELS; ) { + int idx = random() % NKEYS; + if (pairs[idx].state != DELETED) { + dels[i++] = idx; + pairs[idx].state = DELETED; + } + } + for (int i = 0; i < NDELS; ++i) { + pairs[dels[i]].state = UNTOUCHED; + } +} + +static void +run_test(DB *db) +{ + DB_TXN * const null_txn = 0; + int p = 0, d = 0; + for (int cursz = NKEYS / 10; cursz <= NKEYS; cursz += NKEYS / 10) { + // insert a chunk + for (; p < cursz; ++p) { + // put an element in + invariant(pairs[p].state == UNTOUCHED); + CHK(db->put(db, null_txn, &pairs[p].key, &pairs[p].val, 0)); + pairs[p].state = INSERTED; + // delete everything we can so far, in the given order + for (; d < NDELS && dels[d] <= p; ++d) { + invariant(pairs[dels[d]].state == INSERTED); + CHK(db->del(db, null_txn, &pairs[dels[d]].key, 0)); + pairs[dels[d]].state = DELETED; + } + } + + // get what the data should be + memcpy(sorted, pairs, cursz * (sizeof pairs[0])); + qsort(sorted, cursz, sizeof sorted[0], pair_cmp); + + // verify the data + + // with point queries + if ((random() % 10) < 5) { + for (int i = 0; i < cursz; ++i) { + DBT val; dbt_init(&val, NULL, 0); + invariant(sorted[i].state != UNTOUCHED); + int r = db->get(db, null_txn, &sorted[i].key, &val, 0); + if (sorted[i].state == INSERTED) { + CKERR(r); + assert(val.size == sorted[i].val.size); + assert(memcmp(val.data, sorted[i].val.data, val.size) == 0); + } else { + CKERR2(r, DB_NOTFOUND); + } + } + } + + // with a forward traversal + if ((random() % 10) < 5) { + DBC *cur; + CHK(db->cursor(db, null_txn, &cur, 0)); + DBT ck, cv; dbt_init(&ck, NULL, 0); dbt_init(&cv, NULL, 0); + int i, r; + for (r = CHK(cur->c_get(cur, &ck, &cv, DB_FIRST)), i = 0; + r == 0 && i < cursz; + r = cur->c_get(cur, &ck, &cv, DB_NEXT), ++i) { + invariant(sorted[i].state != UNTOUCHED); + while (i < cursz && sorted[i].state == DELETED) { + i++; + invariant(sorted[i].state != UNTOUCHED); + } + invariant(i < cursz); + assert(ck.size == sorted[i].key.size); + assert(memcmp(ck.data, sorted[i].key.data, ck.size) == 0); + assert(cv.size == sorted[i].val.size); + assert(memcmp(cv.data, sorted[i].val.data, cv.size) == 0); + } + while (i < cursz && sorted[i].state == DELETED) { + i++; + invariant(sorted[i].state != UNTOUCHED); + } + assert(i == cursz); + assert(r == DB_NOTFOUND); + } + + // with a backward traversal + if ((random() % 10) < 5) { + DBC *cur; + CHK(db->cursor(db, null_txn, &cur, 0)); + DBT ck, cv; dbt_init(&ck, NULL, 0); dbt_init(&cv, NULL, 0); + int i, r; + for (r = CHK(cur->c_get(cur, &ck, &cv, DB_LAST)), i = cursz - 1; + r == 0 && i >= 0; + r = cur->c_get(cur, &ck, &cv, DB_PREV), --i) { + invariant(sorted[i].state != UNTOUCHED); + while (i >= 0 && sorted[i].state == DELETED) { + i--; + invariant(sorted[i].state != UNTOUCHED); + } + invariant(i >= 0); + assert(ck.size == sorted[i].key.size); + assert(memcmp(ck.data, sorted[i].key.data, ck.size) == 0); + assert(cv.size == sorted[i].val.size); + assert(memcmp(cv.data, sorted[i].val.data, cv.size) == 0); + } + while (i >= 0 && sorted[i].state == DELETED) { + i--; + invariant(sorted[i].state != UNTOUCHED); + } + assert(i == -1); + assert(r == DB_NOTFOUND); + } + } +} + +static void +init_db(DB_ENV **env, DB **db) +{ + DB_TXN * const null_txn = 0; + + CHK(system("rm -rf " ENVDIR)); + CHK(toku_os_mkdir(ENVDIR, S_IRWXU+S_IRWXG+S_IRWXO)); + CHK(db_env_create(env, 0)); + (*env)->set_errfile(*env, stderr); + CHK((*env)->open(*env, ENVDIR, DB_CREATE+DB_PRIVATE+DB_INIT_MPOOL, 0)); + CHK(db_create(db, *env, 0)); + CHK((*db)->open(*db, null_txn, "test.stress.brt", "main", + DB_BTREE, DB_CREATE, 0666)); +} + +static void +destroy_db(DB_ENV *env, DB *db) +{ + CHK(db->close(db, 0)); + CHK(env->close(env, 0)); +} + +int +test_main(int argc, char * const argv[]) +{ + DB_ENV *env; + DB *db; + + parse_args(argc, argv); + gen_data(); + init_db(&env, &db); + run_test(db); + destroy_db(env, db); + + return 0; +} -- 2.30.9