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