tdb2: test: convert (non-invasive) run tests to api tests.
authorRusty Russell <rusty@rustcorp.com.au>
Wed, 31 Aug 2011 06:09:16 +0000 (15:39 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 31 Aug 2011 06:09:16 +0000 (15:39 +0930)
This reduces compilation time, since these are merely linked with the
pre-built module, rather than recompiling it into the test (which
allows for fancy things like failtest).

This reduces the test compile time down from about 62 seconds to 45
seconds.  Since ccanlint compiles tests three times (once normally,
once with coverage, and once with reduced config.h) this makes a
difference: we go from 780 seconds to 729 seconds.

46 files changed:
ccan/tdb2/test/api-12-store.c [new file with mode: 0644]
ccan/tdb2/test/api-13-delete.c [new file with mode: 0644]
ccan/tdb2/test/api-14-exists.c [new file with mode: 0644]
ccan/tdb2/test/api-16-wipe_all.c [new file with mode: 0644]
ccan/tdb2/test/api-21-parse_record.c [new file with mode: 0644]
ccan/tdb2/test/api-55-transaction.c [new file with mode: 0644]
ccan/tdb2/test/api-80-tdb_fd.c [new file with mode: 0644]
ccan/tdb2/test/api-81-seqnum.c [new file with mode: 0644]
ccan/tdb2/test/api-82-lockattr.c [new file with mode: 0644]
ccan/tdb2/test/api-83-openhook.c [new file with mode: 0644]
ccan/tdb2/test/api-91-get-stats.c [new file with mode: 0644]
ccan/tdb2/test/api-92-get-set-readonly.c [new file with mode: 0644]
ccan/tdb2/test/api-93-repack.c [new file with mode: 0644]
ccan/tdb2/test/api-add-remove-flags.c [new file with mode: 0644]
ccan/tdb2/test/api-check-callback.c [new file with mode: 0644]
ccan/tdb2/test/api-firstkey-nextkey.c [new file with mode: 0644]
ccan/tdb2/test/api-fork-test.c [new file with mode: 0644]
ccan/tdb2/test/api-locktimeout.c [new file with mode: 0644]
ccan/tdb2/test/api-missing-entries.c [new file with mode: 0644]
ccan/tdb2/test/api-open-multiple-times.c [new file with mode: 0644]
ccan/tdb2/test/api-record-expand.c [new file with mode: 0644]
ccan/tdb2/test/api-simple-delete.c [new file with mode: 0644]
ccan/tdb2/test/api-summary.c [new file with mode: 0644]
ccan/tdb2/test/run-12-store.c [deleted file]
ccan/tdb2/test/run-13-delete.c [deleted file]
ccan/tdb2/test/run-14-exists.c [deleted file]
ccan/tdb2/test/run-16-wipe_all.c [deleted file]
ccan/tdb2/test/run-21-parse_record.c [deleted file]
ccan/tdb2/test/run-55-transaction.c [deleted file]
ccan/tdb2/test/run-80-tdb_fd.c [deleted file]
ccan/tdb2/test/run-81-seqnum.c [deleted file]
ccan/tdb2/test/run-82-lockattr.c [deleted file]
ccan/tdb2/test/run-83-openhook.c [deleted file]
ccan/tdb2/test/run-91-get-stats.c [deleted file]
ccan/tdb2/test/run-92-get-set-readonly.c [deleted file]
ccan/tdb2/test/run-93-repack.c [deleted file]
ccan/tdb2/test/run-add-remove-flags.c [deleted file]
ccan/tdb2/test/run-check-callback.c [deleted file]
ccan/tdb2/test/run-firstkey-nextkey.c [deleted file]
ccan/tdb2/test/run-fork-test.c [deleted file]
ccan/tdb2/test/run-locktimeout.c [deleted file]
ccan/tdb2/test/run-missing-entries.c [deleted file]
ccan/tdb2/test/run-open-multiple-times.c [deleted file]
ccan/tdb2/test/run-record-expand.c [deleted file]
ccan/tdb2/test/run-simple-delete.c [deleted file]
ccan/tdb2/test/run-summary.c [deleted file]

diff --git a/ccan/tdb2/test/api-12-store.c b/ccan/tdb2/test/api-12-store.c
new file mode 100644 (file)
index 0000000..ccec53e
--- /dev/null
@@ -0,0 +1,56 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <ccan/hash/hash.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "logging.h"
+
+/* We use the same seed which we saw a failure on. */
+static uint64_t fixedhash(const void *key, size_t len, uint64_t seed, void *p)
+{
+       return hash64_stable((const unsigned char *)key, len,
+                            *(uint64_t *)p);
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i, j;
+       struct tdb_context *tdb;
+       uint64_t seed = 16014841315512641303ULL;
+       union tdb_attribute fixed_hattr
+               = { .hash = { .base = { TDB_ATTRIBUTE_HASH },
+                             .fn = fixedhash,
+                             .data = &seed } };
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT };
+       struct tdb_data key = { (unsigned char *)&j, sizeof(j) };
+       struct tdb_data data = { (unsigned char *)&j, sizeof(j) };
+
+       fixed_hattr.base.next = &tap_log_attr;
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * (1 + 500 * 3) + 1);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-12-store.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &fixed_hattr);
+               ok1(tdb);
+               if (!tdb)
+                       continue;
+
+               /* We seemed to lose some keys.
+                * Insert and check they're in there! */
+               for (j = 0; j < 500; j++) {
+                       struct tdb_data d = { NULL, 0 }; /* Bogus GCC warning */
+                       ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
+                       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
+                       ok1(tdb_deq(d, data));
+                       free(d.dptr);
+               }
+               tdb_close(tdb);
+       }
+
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-13-delete.c b/ccan/tdb2/test/api-13-delete.c
new file mode 100644 (file)
index 0000000..0287a6a
--- /dev/null
@@ -0,0 +1,210 @@
+#include <ccan/tdb2/private.h> // For TDB_TOPLEVEL_HASH_BITS
+#include <ccan/hash/hash.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include "logging.h"
+
+/* We rig the hash so adjacent-numbered records always clash. */
+static uint64_t clash(const void *key, size_t len, uint64_t seed, void *priv)
+{
+       return ((uint64_t)*(const unsigned int *)key)
+               << (64 - TDB_TOPLEVEL_HASH_BITS - 1);
+}
+
+/* We use the same seed which we saw a failure on. */
+static uint64_t fixedhash(const void *key, size_t len, uint64_t seed, void *p)
+{
+       return hash64_stable((const unsigned char *)key, len,
+                            *(uint64_t *)p);
+}
+
+static bool store_records(struct tdb_context *tdb)
+{
+       int i;
+       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
+       struct tdb_data d, data = { (unsigned char *)&i, sizeof(i) };
+
+       for (i = 0; i < 1000; i++) {
+               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
+                       return false;
+               tdb_fetch(tdb, key, &d);
+               if (!tdb_deq(d, data))
+                       return false;
+               free(d.dptr);
+       }
+       return true;
+}
+
+static void test_val(struct tdb_context *tdb, uint64_t val)
+{
+       uint64_t v;
+       struct tdb_data key = { (unsigned char *)&v, sizeof(v) };
+       struct tdb_data d, data = { (unsigned char *)&v, sizeof(v) };
+
+       /* Insert an entry, then delete it. */
+       v = val;
+       /* Delete should fail. */
+       ok1(tdb_delete(tdb, key) == TDB_ERR_NOEXIST);
+       ok1(tdb_check(tdb, NULL, NULL) == 0);
+
+       /* Insert should succeed. */
+       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+       ok1(tdb_check(tdb, NULL, NULL) == 0);
+
+       /* Delete should succeed. */
+       ok1(tdb_delete(tdb, key) == 0);
+       ok1(tdb_check(tdb, NULL, NULL) == 0);
+
+       /* Re-add it, then add collision. */
+       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+       v = val + 1;
+       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+       ok1(tdb_check(tdb, NULL, NULL) == 0);
+
+       /* Can find both? */
+       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
+       ok1(d.dsize == data.dsize);
+       free(d.dptr);
+       v = val;
+       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
+       ok1(d.dsize == data.dsize);
+       free(d.dptr);
+
+       /* Delete second one. */
+       v = val + 1;
+       ok1(tdb_delete(tdb, key) == 0);
+       ok1(tdb_check(tdb, NULL, NULL) == 0);
+
+       /* Re-add */
+       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+       ok1(tdb_check(tdb, NULL, NULL) == 0);
+
+       /* Now, try deleting first one. */
+       v = val;
+       ok1(tdb_delete(tdb, key) == 0);
+       ok1(tdb_check(tdb, NULL, NULL) == 0);
+
+       /* Can still find second? */
+       v = val + 1;
+       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
+       ok1(d.dsize == data.dsize);
+       free(d.dptr);
+
+       /* Now, this will be ideally placed. */
+       v = val + 2;
+       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+       ok1(tdb_check(tdb, NULL, NULL) == 0);
+
+       /* This will collide with both. */
+       v = val;
+       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+
+       /* We can still find them all, right? */
+       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
+       ok1(d.dsize == data.dsize);
+       free(d.dptr);
+       v = val + 1;
+       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
+       ok1(d.dsize == data.dsize);
+       free(d.dptr);
+       v = val + 2;
+       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
+       ok1(d.dsize == data.dsize);
+       free(d.dptr);
+
+       /* And if we delete val + 1, that val + 2 should not move! */
+       v = val + 1;
+       ok1(tdb_delete(tdb, key) == 0);
+       ok1(tdb_check(tdb, NULL, NULL) == 0);
+
+       v = val;
+       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
+       ok1(d.dsize == data.dsize);
+       free(d.dptr);
+       v = val + 2;
+       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
+       ok1(d.dsize == data.dsize);
+       free(d.dptr);
+
+       /* Delete those two, so we are empty. */
+       ok1(tdb_delete(tdb, key) == 0);
+       v = val;
+       ok1(tdb_delete(tdb, key) == 0);
+
+       ok1(tdb_check(tdb, NULL, NULL) == 0);
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i, j;
+       struct tdb_context *tdb;
+       uint64_t seed = 16014841315512641303ULL;
+       union tdb_attribute clash_hattr
+               = { .hash = { .base = { TDB_ATTRIBUTE_HASH },
+                             .fn = clash } };
+       union tdb_attribute fixed_hattr
+               = { .hash = { .base = { TDB_ATTRIBUTE_HASH },
+                             .fn = fixedhash,
+                             .data = &seed } };
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+       /* These two values gave trouble before. */
+       int vals[] = { 755, 837 };
+
+       clash_hattr.base.next = &tap_log_attr;
+       fixed_hattr.base.next = &tap_log_attr;
+
+       plan_tests(sizeof(flags) / sizeof(flags[0])
+                  * (39 * 3 + 5 + sizeof(vals)/sizeof(vals[0])*2) + 1);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-13-delete.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &clash_hattr);
+               ok1(tdb);
+               if (!tdb)
+                       continue;
+
+               /* Check start of hash table. */
+               test_val(tdb, 0);
+
+               /* Check end of hash table. */
+               test_val(tdb, -1ULL);
+
+               /* Check mixed bitpattern. */
+               test_val(tdb, 0x123456789ABCDEF0ULL);
+
+               ok1(!tdb->file || (tdb->file->allrecord_lock.count == 0
+                                  && tdb->file->num_lockrecs == 0));
+               tdb_close(tdb);
+
+               /* Deleting these entries in the db gave problems. */
+               tdb = tdb_open("run-13-delete.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &fixed_hattr);
+               ok1(tdb);
+               if (!tdb)
+                       continue;
+
+               ok1(store_records(tdb));
+               ok1(tdb_check(tdb, NULL, NULL) == 0);
+               for (j = 0; j < sizeof(vals)/sizeof(vals[0]); j++) {
+                       struct tdb_data key;
+
+                       key.dptr = (unsigned char *)&vals[j];
+                       key.dsize = sizeof(vals[j]);
+                       ok1(tdb_delete(tdb, key) == 0);
+                       ok1(tdb_check(tdb, NULL, NULL) == 0);
+               }
+               tdb_close(tdb);
+       }
+
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-14-exists.c b/ccan/tdb2/test/api-14-exists.c
new file mode 100644 (file)
index 0000000..698006f
--- /dev/null
@@ -0,0 +1,58 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "logging.h"
+
+static bool test_records(struct tdb_context *tdb)
+{
+       int i;
+       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
+       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
+
+       for (i = 0; i < 1000; i++) {
+               if (tdb_exists(tdb, key))
+                       return false;
+               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
+                       return false;
+               if (!tdb_exists(tdb, key))
+                       return false;
+       }
+
+       for (i = 0; i < 1000; i++) {
+               if (!tdb_exists(tdb, key))
+                       return false;
+               if (tdb_delete(tdb, key) != 0)
+                       return false;
+               if (tdb_exists(tdb, key))
+                       return false;
+       }
+       return true;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 2 + 1);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-14-exists.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               if (ok1(tdb))
+                       ok1(test_records(tdb));
+               tdb_close(tdb);
+       }
+
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-16-wipe_all.c b/ccan/tdb2/test/api-16-wipe_all.c
new file mode 100644 (file)
index 0000000..d17eff8
--- /dev/null
@@ -0,0 +1,50 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "logging.h"
+
+static bool add_records(struct tdb_context *tdb)
+{
+       int i;
+       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
+       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
+
+       for (i = 0; i < 1000; i++) {
+               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
+                       return false;
+       }
+       return true;
+}
+
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 4 + 1);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-16-wipe_all.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               if (ok1(tdb)) {
+                       struct tdb_data key;
+                       ok1(add_records(tdb));
+                       ok1(tdb_wipe_all(tdb) == TDB_SUCCESS);
+                       ok1(tdb_firstkey(tdb, &key) == TDB_ERR_NOEXIST);
+                       tdb_close(tdb);
+               }
+       }
+
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-21-parse_record.c b/ccan/tdb2/test/api-21-parse_record.c
new file mode 100644 (file)
index 0000000..4a9cf05
--- /dev/null
@@ -0,0 +1,71 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "logging.h"
+
+static enum TDB_ERROR parse(TDB_DATA key, TDB_DATA data, TDB_DATA *expected)
+{
+       if (!tdb_deq(data, *expected))
+               return TDB_ERR_EINVAL;
+       return TDB_SUCCESS;
+}
+
+static enum TDB_ERROR parse_err(TDB_DATA key, TDB_DATA data, void *unused)
+{
+       return 100;
+}
+
+static bool test_records(struct tdb_context *tdb)
+{
+       int i;
+       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
+       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
+
+       for (i = 0; i < 1000; i++) {
+               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
+                       return false;
+       }
+
+       for (i = 0; i < 1000; i++) {
+               if (tdb_parse_record(tdb, key, parse, &data) != TDB_SUCCESS)
+                       return false;
+       }
+
+       if (tdb_parse_record(tdb, key, parse, &data) != TDB_ERR_NOEXIST)
+               return false;
+
+       /* Test error return from parse function. */
+       i = 0;
+       if (tdb_parse_record(tdb, key, parse_err, NULL) != 100)
+               return false;
+
+       return true;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 2 + 1);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-14-exists.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               if (ok1(tdb))
+                       ok1(test_records(tdb));
+               tdb_close(tdb);
+       }
+
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-55-transaction.c b/ccan/tdb2/test/api-55-transaction.c
new file mode 100644 (file)
index 0000000..9c1044b
--- /dev/null
@@ -0,0 +1,76 @@
+#include <ccan/tdb2/private.h> // struct tdb_context
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       unsigned char *buffer;
+       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
+                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+       struct tdb_data key = tdb_mkdata("key", 3);
+       struct tdb_data data;
+
+       buffer = malloc(1000);
+       for (i = 0; i < 1000; i++)
+               buffer[i] = i;
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 20 + 1);
+
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-55-transaction.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               ok1(tdb);
+               if (!tdb)
+                       continue;
+
+               ok1(tdb_transaction_start(tdb) == 0);
+               data.dptr = buffer;
+               data.dsize = 1000;
+               ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+               ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
+               ok1(data.dsize == 1000);
+               ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
+               free(data.dptr);
+
+               /* Cancelling a transaction means no store */
+               tdb_transaction_cancel(tdb);
+               ok1(tdb->file->allrecord_lock.count == 0
+                   && tdb->file->num_lockrecs == 0);
+               ok1(tdb_check(tdb, NULL, NULL) == 0);
+               ok1(tdb_fetch(tdb, key, &data) == TDB_ERR_NOEXIST);
+
+               /* Commit the transaction. */
+               ok1(tdb_transaction_start(tdb) == 0);
+               data.dptr = buffer;
+               data.dsize = 1000;
+               ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+               ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
+               ok1(data.dsize == 1000);
+               ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
+               free(data.dptr);
+               ok1(tdb_transaction_commit(tdb) == 0);
+               ok1(tdb->file->allrecord_lock.count == 0
+                   && tdb->file->num_lockrecs == 0);
+               ok1(tdb_check(tdb, NULL, NULL) == 0);
+               ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
+               ok1(data.dsize == 1000);
+               ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
+               free(data.dptr);
+
+               tdb_close(tdb);
+       }
+
+       ok1(tap_log_messages == 0);
+       free(buffer);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-80-tdb_fd.c b/ccan/tdb2/test/api-80-tdb_fd.c
new file mode 100644 (file)
index 0000000..b321f59
--- /dev/null
@@ -0,0 +1,36 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 3);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-new_database.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               if (!ok1(tdb))
+                       continue;
+
+               if (flags[i] & TDB_INTERNAL)
+                       ok1(tdb_fd(tdb) == -1);
+               else
+                       ok1(tdb_fd(tdb) > 2);
+               tdb_close(tdb);
+               ok1(tap_log_messages == 0);
+       }
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-81-seqnum.c b/ccan/tdb2/test/api-81-seqnum.c
new file mode 100644 (file)
index 0000000..c41b9ce
--- /dev/null
@@ -0,0 +1,79 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+       unsigned int i, seq;
+       struct tdb_context *tdb;
+       struct tdb_data d = { NULL, 0 }; /* Bogus GCC warning */
+       struct tdb_data key = tdb_mkdata("key", 3);
+       struct tdb_data data = tdb_mkdata("data", 4);
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 15 + 8 * 13);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-new_database.tdb", flags[i]|TDB_SEQNUM,
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               if (!ok1(tdb))
+                       continue;
+
+               seq = 0;
+               ok1(tdb_get_seqnum(tdb) == seq);
+               ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+               ok1(tdb_get_seqnum(tdb) == ++seq);
+               /* Fetch doesn't change seqnum */
+               if (ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS))
+                       free(d.dptr);
+               ok1(tdb_get_seqnum(tdb) == seq);
+               ok1(tdb_append(tdb, key, data) == TDB_SUCCESS);
+               /* Append in tdb1 (or store over value) bumps twice! */
+               if (flags[i] & TDB_VERSION1)
+                       seq++;
+               ok1(tdb_get_seqnum(tdb) == ++seq);
+
+               ok1(tdb_delete(tdb, key) == TDB_SUCCESS);
+               ok1(tdb_get_seqnum(tdb) == ++seq);
+               /* Empty append works */
+               ok1(tdb_append(tdb, key, data) == TDB_SUCCESS);
+               ok1(tdb_get_seqnum(tdb) == ++seq);
+
+               ok1(tdb_wipe_all(tdb) == TDB_SUCCESS);
+               ok1(tdb_get_seqnum(tdb) == ++seq);
+
+               if (!(flags[i] & TDB_INTERNAL)) {
+                       ok1(tdb_transaction_start(tdb) == TDB_SUCCESS);
+                       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+                       ok1(tdb_get_seqnum(tdb) == ++seq);
+                       /* Append in tdb1 (or store over value) bumps twice! */
+                       if (flags[i] & TDB_VERSION1)
+                               seq++;
+                       ok1(tdb_append(tdb, key, data) == TDB_SUCCESS);
+                       ok1(tdb_get_seqnum(tdb) == ++seq);
+                       ok1(tdb_delete(tdb, key) == TDB_SUCCESS);
+                       ok1(tdb_get_seqnum(tdb) == ++seq);
+                       ok1(tdb_transaction_commit(tdb) == TDB_SUCCESS);
+                       ok1(tdb_get_seqnum(tdb) == seq);
+
+                       ok1(tdb_transaction_start(tdb) == TDB_SUCCESS);
+                       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+                       ok1(tdb_get_seqnum(tdb) == seq + 1);
+                       tdb_transaction_cancel(tdb);
+                       ok1(tdb_get_seqnum(tdb) == seq);
+               }
+               tdb_close(tdb);
+               ok1(tap_log_messages == 0);
+       }
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-82-lockattr.c b/ccan/tdb2/test/api-82-lockattr.c
new file mode 100644 (file)
index 0000000..048feac
--- /dev/null
@@ -0,0 +1,248 @@
+#include <ccan/tdb2/private.h> // for tdb_fcntl_unlock
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "logging.h"
+
+static int mylock(int fd, int rw, off_t off, off_t len, bool waitflag,
+                 void *_err)
+{
+       int *lock_err = _err;
+       struct flock fl;
+       int ret;
+
+       if (*lock_err) {
+               errno = *lock_err;
+               return -1;
+       }
+
+       do {
+               fl.l_type = rw;
+               fl.l_whence = SEEK_SET;
+               fl.l_start = off;
+               fl.l_len = len;
+
+               if (waitflag)
+                       ret = fcntl(fd, F_SETLKW, &fl);
+               else
+                       ret = fcntl(fd, F_SETLK, &fl);
+       } while (ret != 0 && errno == EINTR);
+
+       return ret;
+}
+
+static int trav_err;
+static int trav(struct tdb_context *tdb, TDB_DATA k, TDB_DATA d, int *err)
+{
+       *err = trav_err;
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
+                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+       union tdb_attribute lock_attr;
+       struct tdb_data key = tdb_mkdata("key", 3);
+       struct tdb_data data = tdb_mkdata("data", 4);
+       int lock_err;
+
+       lock_attr.base.attr = TDB_ATTRIBUTE_FLOCK;
+       lock_attr.base.next = &tap_log_attr;
+       lock_attr.flock.lock = mylock;
+       lock_attr.flock.unlock = tdb_fcntl_unlock;
+       lock_attr.flock.data = &lock_err;
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 80);
+
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               struct tdb_data d;
+               unsigned int num_oom_messages;
+
+               /* TDB1 double logs here. */
+               if (flags[i] & TDB_VERSION1) {
+                       num_oom_messages = 2;
+               } else {
+                       num_oom_messages = 1;
+               }
+
+               /* Nonblocking open; expect no error message. */
+               lock_err = EAGAIN;
+               tdb = tdb_open("run-82-lockattr.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
+               ok(errno == lock_err, "Errno is %u", errno);
+               ok1(!tdb);
+               ok1(tap_log_messages == 0);
+
+               lock_err = EINTR;
+               tdb = tdb_open("run-82-lockattr.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
+               ok(errno == lock_err, "Errno is %u", errno);
+               ok1(!tdb);
+               ok1(tap_log_messages == 0);
+
+               /* Forced fail open. */
+               lock_err = ENOMEM;
+               tdb = tdb_open("run-82-lockattr.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
+               ok1(errno == lock_err);
+               ok1(!tdb);
+               ok1(tap_log_messages == 1);
+               tap_log_messages = 0;
+
+               lock_err = 0;
+               tdb = tdb_open("run-82-lockattr.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
+               if (!ok1(tdb))
+                       continue;
+               ok1(tap_log_messages == 0);
+
+               /* Nonblocking store. */
+               lock_err = EAGAIN;
+               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = EINTR;
+               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = ENOMEM;
+               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == num_oom_messages);
+               tap_log_messages = 0;
+
+               /* Nonblocking fetch. */
+               lock_err = EAGAIN;
+               ok1(!tdb_exists(tdb, key));
+               ok1(tap_log_messages == 0);
+               lock_err = EINTR;
+               ok1(!tdb_exists(tdb, key));
+               ok1(tap_log_messages == 0);
+               lock_err = ENOMEM;
+               ok1(!tdb_exists(tdb, key));
+               ok1(tap_log_messages == num_oom_messages);
+               tap_log_messages = 0;
+
+               lock_err = EAGAIN;
+               ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = EINTR;
+               ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = ENOMEM;
+               ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == num_oom_messages);
+               tap_log_messages = 0;
+
+               /* Nonblocking delete. */
+               lock_err = EAGAIN;
+               ok1(tdb_delete(tdb, key) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = EINTR;
+               ok1(tdb_delete(tdb, key) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = ENOMEM;
+               ok1(tdb_delete(tdb, key) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == num_oom_messages);
+               tap_log_messages = 0;
+
+               /* Nonblocking locks. */
+               lock_err = EAGAIN;
+               ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = EINTR;
+               ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = ENOMEM;
+               ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == num_oom_messages);
+               tap_log_messages = 0;
+
+               lock_err = EAGAIN;
+               ok1(tdb_chainlock_read(tdb, key) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = EINTR;
+               ok1(tdb_chainlock_read(tdb, key) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = ENOMEM;
+               ok1(tdb_chainlock_read(tdb, key) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == num_oom_messages);
+               tap_log_messages = 0;
+
+               lock_err = EAGAIN;
+               ok1(tdb_lockall(tdb) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = EINTR;
+               ok1(tdb_lockall(tdb) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = ENOMEM;
+               ok1(tdb_lockall(tdb) == TDB_ERR_LOCK);
+               /* This actually does divide and conquer. */
+               ok1(tap_log_messages > 0);
+               tap_log_messages = 0;
+
+               lock_err = EAGAIN;
+               ok1(tdb_lockall_read(tdb) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = EINTR;
+               ok1(tdb_lockall_read(tdb) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = ENOMEM;
+               ok1(tdb_lockall_read(tdb) == TDB_ERR_LOCK);
+               ok1(tap_log_messages > 0);
+               tap_log_messages = 0;
+
+               /* Nonblocking traverse; go nonblock partway through. */
+               lock_err = 0;
+               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
+               trav_err = EAGAIN;
+               ok1(tdb_traverse(tdb, trav, &lock_err) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               trav_err = EINTR;
+               lock_err = 0;
+               ok1(tdb_traverse(tdb, trav, &lock_err) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               trav_err = ENOMEM;
+               lock_err = 0;
+               ok1(tdb_traverse(tdb, trav, &lock_err) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == num_oom_messages);
+               tap_log_messages = 0;
+
+               /* Nonblocking transactions. */
+               lock_err = EAGAIN;
+               ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = EINTR;
+               ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+               lock_err = ENOMEM;
+               ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 1);
+               tap_log_messages = 0;
+
+               /* Nonblocking transaction prepare. */
+               lock_err = 0;
+               ok1(tdb_transaction_start(tdb) == 0);
+               ok1(tdb_delete(tdb, key) == 0);
+
+               lock_err = EAGAIN;
+               ok1(tdb_transaction_prepare_commit(tdb) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+
+               lock_err = 0;
+               ok1(tdb_transaction_prepare_commit(tdb) == 0);
+               ok1(tdb_transaction_commit(tdb) == 0);
+
+               /* And the transaction was committed, right? */
+               ok1(!tdb_exists(tdb, key));
+               tdb_close(tdb);
+               ok1(tap_log_messages == 0);
+       }
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-83-openhook.c b/ccan/tdb2/test/api-83-openhook.c
new file mode 100644 (file)
index 0000000..e7e9473
--- /dev/null
@@ -0,0 +1,99 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <err.h>
+#include <unistd.h>
+#include "external-agent.h"
+#include "logging.h"
+
+static enum TDB_ERROR clear_if_first(int fd, void *arg)
+{
+/* We hold a lock offset 4 always, so we can tell if anyone is holding it.
+ * (This is compatible with tdb1's TDB_CLEAR_IF_FIRST flag).  */
+       struct flock fl;
+
+       if (arg != clear_if_first)
+               return TDB_ERR_CORRUPT;
+
+       fl.l_type = F_WRLCK;
+       fl.l_whence = SEEK_SET;
+       fl.l_start = 4;
+       fl.l_len = 1;
+
+       if (fcntl(fd, F_SETLK, &fl) == 0) {
+               /* We must be first ones to open it! */
+               diag("truncating file!");
+               if (ftruncate(fd, 0) != 0) {
+                       return TDB_ERR_IO;
+               }
+       }
+       fl.l_type = F_RDLCK;
+       if (fcntl(fd, F_SETLKW, &fl) != 0) {
+               return TDB_ERR_IO;
+       }
+       return TDB_SUCCESS;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       struct agent *agent;
+       union tdb_attribute cif;
+       struct tdb_data key = tdb_mkdata("key", 3);
+       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
+                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       cif.openhook.base.attr = TDB_ATTRIBUTE_OPENHOOK;
+       cif.openhook.base.next = &tap_log_attr;
+       cif.openhook.fn = clear_if_first;
+       cif.openhook.data = clear_if_first;
+
+       agent = prepare_external_agent();
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 13);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               /* Create it */
+               tdb = tdb_open("run-83-openhook.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, NULL);
+               ok1(tdb);
+               ok1(tdb_store(tdb, key, key, TDB_REPLACE) == 0);
+               tdb_close(tdb);
+
+               /* Now, open with CIF, should clear it. */
+               tdb = tdb_open("run-83-openhook.tdb", flags[i],
+                              O_RDWR, 0, &cif);
+               ok1(tdb);
+               ok1(!tdb_exists(tdb, key));
+               ok1(tdb_store(tdb, key, key, TDB_REPLACE) == 0);
+
+               /* Agent should not clear it, since it's still open. */
+               ok1(external_agent_operation(agent, OPEN_WITH_HOOK,
+                                            "run-83-openhook.tdb") == SUCCESS);
+               ok1(external_agent_operation(agent, FETCH, "key") == SUCCESS);
+               ok1(external_agent_operation(agent, CLOSE, "") == SUCCESS);
+
+               /* Still exists for us too. */
+               ok1(tdb_exists(tdb, key));
+
+               /* Close it, now agent should clear it. */
+               tdb_close(tdb);
+
+               ok1(external_agent_operation(agent, OPEN_WITH_HOOK,
+                                            "run-83-openhook.tdb") == SUCCESS);
+               ok1(external_agent_operation(agent, FETCH, "key") == FAILED);
+               ok1(external_agent_operation(agent, CLOSE, "") == SUCCESS);
+
+               ok1(tap_log_messages == 0);
+       }
+
+       free_external_agent(agent);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-91-get-stats.c b/ccan/tdb2/test/api-91-get-stats.c
new file mode 100644 (file)
index 0000000..d9a22ca
--- /dev/null
@@ -0,0 +1,59 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
+                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 11);
+
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               union tdb_attribute *attr;
+               struct tdb_data key = tdb_mkdata("key", 3);
+
+               tdb = tdb_open("run-91-get-stats.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               ok1(tdb);
+               ok1(tdb_store(tdb, key, key, TDB_REPLACE) == 0);
+
+               /* Use malloc so valgrind will catch overruns. */
+               attr = malloc(sizeof *attr);
+               attr->stats.base.attr = TDB_ATTRIBUTE_STATS;
+               attr->stats.size = sizeof(*attr);
+
+               ok1(tdb_get_attribute(tdb, attr) == 0);
+               ok1(attr->stats.size == sizeof(*attr));
+               ok1(attr->stats.allocs > 0);
+               ok1(attr->stats.expands > 0);
+               ok1(attr->stats.locks > 0);
+               free(attr);
+
+               /* Try short one. */
+               attr = malloc(offsetof(struct tdb_attribute_stats, allocs)
+                             + sizeof(attr->stats.allocs));
+               attr->stats.base.attr = TDB_ATTRIBUTE_STATS;
+               attr->stats.size = offsetof(struct tdb_attribute_stats, allocs)
+                       + sizeof(attr->stats.allocs);
+               ok1(tdb_get_attribute(tdb, attr) == 0);
+               ok1(attr->stats.size == sizeof(*attr));
+               ok1(attr->stats.allocs > 0);
+               free(attr);
+               ok1(tap_log_messages == 0);
+
+               tdb_close(tdb);
+
+       }
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-92-get-set-readonly.c b/ccan/tdb2/test/api-92-get-set-readonly.c
new file mode 100644 (file)
index 0000000..483b50d
--- /dev/null
@@ -0,0 +1,120 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+       unsigned int i, extra_msgs;
+       struct tdb_context *tdb;
+       struct tdb_data key = tdb_mkdata("key", 3);
+       struct tdb_data data = tdb_mkdata("data", 4);
+       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
+                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 48);
+
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               /* RW -> R0 */
+               tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               ok1(tdb);
+               ok1(!(tdb_get_flags(tdb) & TDB_RDONLY));
+
+               /* TDB1 complains multiple times. */
+               if (flags[i] & TDB_VERSION1) {
+                       extra_msgs = 1;
+               } else {
+                       extra_msgs = 0;
+               }
+
+               ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS);
+
+               tdb_add_flag(tdb, TDB_RDONLY);
+               ok1(tdb_get_flags(tdb) & TDB_RDONLY);
+
+               /* Can't store, append, delete. */
+               ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_ERR_RDONLY);
+               ok1(tap_log_messages == 1);
+               ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY);
+               tap_log_messages -= extra_msgs;
+               ok1(tap_log_messages == 2);
+               ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY);
+               tap_log_messages -= extra_msgs;
+               ok1(tap_log_messages == 3);
+
+               /* Can't start a transaction, or any write lock. */
+               ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY);
+               ok1(tap_log_messages == 4);
+               ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY);
+               tap_log_messages -= extra_msgs;
+               ok1(tap_log_messages == 5);
+               ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY);
+               ok1(tap_log_messages == 6);
+               ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY);
+               ok1(tap_log_messages == 7);
+
+               /* Back to RW. */
+               tdb_remove_flag(tdb, TDB_RDONLY);
+               ok1(!(tdb_get_flags(tdb) & TDB_RDONLY));
+
+               ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_SUCCESS);
+               ok1(tdb_append(tdb, key, data) == TDB_SUCCESS);
+               ok1(tdb_delete(tdb, key) == TDB_SUCCESS);
+
+               ok1(tdb_transaction_start(tdb) == TDB_SUCCESS);
+               ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS);
+               ok1(tdb_transaction_commit(tdb) == TDB_SUCCESS);
+
+               ok1(tdb_chainlock(tdb, key) == TDB_SUCCESS);
+               tdb_chainunlock(tdb, key);
+               ok1(tdb_lockall(tdb) == TDB_SUCCESS);
+               tdb_unlockall(tdb);
+               ok1(tdb_wipe_all(tdb) == TDB_SUCCESS);
+               ok1(tap_log_messages == 7);
+
+               tdb_close(tdb);
+
+               /* R0 -> RW */
+               tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i],
+                              O_RDONLY, 0600, &tap_log_attr);
+               ok1(tdb);
+               ok1(tdb_get_flags(tdb) & TDB_RDONLY);
+
+               /* Can't store, append, delete. */
+               ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_ERR_RDONLY);
+               ok1(tap_log_messages == 8);
+               ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY);
+               tap_log_messages -= extra_msgs;
+               ok1(tap_log_messages == 9);
+               ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY);
+               tap_log_messages -= extra_msgs;
+               ok1(tap_log_messages == 10);
+
+               /* Can't start a transaction, or any write lock. */
+               ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY);
+               ok1(tap_log_messages == 11);
+               ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY);
+               tap_log_messages -= extra_msgs;
+               ok1(tap_log_messages == 12);
+               ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY);
+               ok1(tap_log_messages == 13);
+               ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY);
+               ok1(tap_log_messages == 14);
+
+               /* Can't remove TDB_RDONLY since we opened with O_RDONLY */
+               tdb_remove_flag(tdb, TDB_RDONLY);
+               ok1(tap_log_messages == 15);
+               ok1(tdb_get_flags(tdb) & TDB_RDONLY);
+               tdb_close(tdb);
+
+               ok1(tap_log_messages == 15);
+               tap_log_messages = 0;
+       }
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-93-repack.c b/ccan/tdb2/test/api-93-repack.c
new file mode 100644 (file)
index 0000000..0a2e6d5
--- /dev/null
@@ -0,0 +1,79 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "logging.h"
+
+#define NUM_TESTS 50000
+
+static bool store_all(struct tdb_context *tdb)
+{
+       unsigned int i;
+       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
+       struct tdb_data dbuf = { (unsigned char *)&i, sizeof(i) };
+
+       for (i = 0; i < NUM_TESTS; i++) {
+               if (tdb_store(tdb, key, dbuf, TDB_INSERT) != TDB_SUCCESS)
+                       return false;
+       }
+       return true;
+}
+
+static int mark_entry(struct tdb_context *tdb,
+                     TDB_DATA key, TDB_DATA data, bool found[])
+{
+       unsigned int num;
+
+       if (key.dsize != sizeof(num))
+               return -1;
+       memcpy(&num, key.dptr, key.dsize);
+       if (num >= NUM_TESTS)
+               return -1;
+       if (found[num])
+               return -1;
+       found[num] = true;
+       return 0;
+}
+
+static bool is_all_set(bool found[], unsigned int num)
+{
+       unsigned int i;
+
+       for (i = 0; i < num; i++)
+               if (!found[i])
+                       return false;
+       return true;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       bool found[NUM_TESTS];
+       struct tdb_context *tdb;
+       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
+       };
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 6 + 1);
+
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-93-repack.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               ok1(tdb);
+               if (!tdb)
+                       break;
+
+               ok1(store_all(tdb));
+
+               ok1(tdb_repack(tdb) == TDB_SUCCESS);
+               memset(found, 0, sizeof(found));
+               ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
+               ok1(tdb_traverse(tdb, mark_entry, found) == NUM_TESTS);
+               ok1(is_all_set(found, NUM_TESTS));
+               tdb_close(tdb);
+       }
+
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-add-remove-flags.c b/ccan/tdb2/test/api-add-remove-flags.c
new file mode 100644 (file)
index 0000000..231b9f6
--- /dev/null
@@ -0,0 +1,94 @@
+#include <ccan/tdb2/private.h> // for tdb_context
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       plan_tests(173);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-add-remove-flags.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               ok1(tdb);
+               if (!tdb)
+                       continue;
+
+               ok1(tdb_get_flags(tdb) == tdb->flags);
+               tap_log_messages = 0;
+               tdb_add_flag(tdb, TDB_NOLOCK);
+               if (flags[i] & TDB_INTERNAL)
+                       ok1(tap_log_messages == 1);
+               else {
+                       ok1(tap_log_messages == 0);
+                       ok1(tdb_get_flags(tdb) & TDB_NOLOCK);
+               }
+
+               tap_log_messages = 0;
+               tdb_add_flag(tdb, TDB_NOMMAP);
+               if (flags[i] & TDB_INTERNAL)
+                       ok1(tap_log_messages == 1);
+               else {
+                       ok1(tap_log_messages == 0);
+                       ok1(tdb_get_flags(tdb) & TDB_NOMMAP);
+                       ok1(tdb->file->map_ptr == NULL);
+               }
+
+               tap_log_messages = 0;
+               tdb_add_flag(tdb, TDB_NOSYNC);
+               if (flags[i] & TDB_INTERNAL)
+                       ok1(tap_log_messages == 1);
+               else {
+                       ok1(tap_log_messages == 0);
+                       ok1(tdb_get_flags(tdb) & TDB_NOSYNC);
+               }
+
+               ok1(tdb_get_flags(tdb) == tdb->flags);
+
+               tap_log_messages = 0;
+               tdb_remove_flag(tdb, TDB_NOLOCK);
+               if (flags[i] & TDB_INTERNAL)
+                       ok1(tap_log_messages == 1);
+               else {
+                       ok1(tap_log_messages == 0);
+                       ok1(!(tdb_get_flags(tdb) & TDB_NOLOCK));
+               }
+
+               tap_log_messages = 0;
+               tdb_remove_flag(tdb, TDB_NOMMAP);
+               if (flags[i] & TDB_INTERNAL)
+                       ok1(tap_log_messages == 1);
+               else {
+                       ok1(tap_log_messages == 0);
+                       ok1(!(tdb_get_flags(tdb) & TDB_NOMMAP));
+                       ok1(tdb->file->map_ptr != NULL);
+               }
+
+               tap_log_messages = 0;
+               tdb_remove_flag(tdb, TDB_NOSYNC);
+               if (flags[i] & TDB_INTERNAL)
+                       ok1(tap_log_messages == 1);
+               else {
+                       ok1(tap_log_messages == 0);
+                       ok1(!(tdb_get_flags(tdb) & TDB_NOSYNC));
+               }
+
+               tdb_close(tdb);
+       }
+
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-check-callback.c b/ccan/tdb2/test/api-check-callback.c
new file mode 100644 (file)
index 0000000..fb980f2
--- /dev/null
@@ -0,0 +1,90 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "logging.h"
+
+#define NUM_RECORDS 1000
+
+static bool store_records(struct tdb_context *tdb)
+{
+       int i;
+       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
+       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
+
+       for (i = 0; i < NUM_RECORDS; i++)
+               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
+                       return false;
+       return true;
+}
+
+static enum TDB_ERROR check(struct tdb_data key,
+                           struct tdb_data data,
+                           bool *array)
+{
+       int val;
+
+       if (key.dsize != sizeof(val)) {
+               diag("Wrong key size: %u\n", key.dsize);
+               return TDB_ERR_CORRUPT;
+       }
+
+       if (key.dsize != data.dsize
+           || memcmp(key.dptr, data.dptr, sizeof(val)) != 0) {
+               diag("Key and data differ\n");
+               return TDB_ERR_CORRUPT;
+       }
+
+       memcpy(&val, key.dptr, sizeof(val));
+       if (val >= NUM_RECORDS || val < 0) {
+               diag("check value %i\n", val);
+               return TDB_ERR_CORRUPT;
+       }
+
+       if (array[val]) {
+               diag("Value %i already seen\n", val);
+               return TDB_ERR_CORRUPT;
+       }
+
+       array[val] = true;
+       return TDB_SUCCESS;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i, j;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 4 + 1);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               bool array[NUM_RECORDS];
+
+               tdb = tdb_open("run-check-callback.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               ok1(tdb);
+               if (!tdb)
+                       continue;
+
+               ok1(store_records(tdb));
+               for (j = 0; j < NUM_RECORDS; j++)
+                       array[j] = false;
+               ok1(tdb_check(tdb, check, array) == TDB_SUCCESS);
+               for (j = 0; j < NUM_RECORDS; j++)
+                       if (!array[j])
+                               break;
+               ok1(j == NUM_RECORDS);
+               tdb_close(tdb);
+       }
+
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-firstkey-nextkey.c b/ccan/tdb2/test/api-firstkey-nextkey.c
new file mode 100644 (file)
index 0000000..0c09514
--- /dev/null
@@ -0,0 +1,163 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "logging.h"
+
+#define NUM_RECORDS 1000
+
+static bool store_records(struct tdb_context *tdb)
+{
+       int i;
+       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
+       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
+
+       for (i = 0; i < NUM_RECORDS; i++)
+               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
+                       return false;
+       return true;
+}
+
+struct trav_data {
+       unsigned int records[NUM_RECORDS];
+       unsigned int calls;
+};
+
+static int trav(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, void *p)
+{
+       struct trav_data *td = p;
+       int val;
+
+       memcpy(&val, dbuf.dptr, dbuf.dsize);
+       td->records[td->calls++] = val;
+       return 0;
+}
+
+/* Since tdb_nextkey frees dptr, we need to clone it. */
+static TDB_DATA dup_key(TDB_DATA key)
+{
+       void *p = malloc(key.dsize);
+       memcpy(p, key.dptr, key.dsize);
+       key.dptr = p;
+       return key;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i, j;
+       int num;
+       struct trav_data td;
+       TDB_DATA k;
+       struct tdb_context *tdb;
+       union tdb_attribute seed_attr;
+       enum TDB_ERROR ecode;
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       seed_attr.base.attr = TDB_ATTRIBUTE_SEED;
+       seed_attr.base.next = &tap_log_attr;
+       seed_attr.seed.seed = 6334326220117065685ULL;
+
+       plan_tests(sizeof(flags) / sizeof(flags[0])
+                  * (NUM_RECORDS*6 + (NUM_RECORDS-1)*3 + 22) + 1);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-traverse.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600,
+                              flags[i] & TDB_VERSION1 ? NULL : &seed_attr);
+               ok1(tdb);
+               if (!tdb)
+                       continue;
+
+               ok1(tdb_firstkey(tdb, &k) == TDB_ERR_NOEXIST);
+
+               /* One entry... */
+               k.dptr = (unsigned char *)&num;
+               k.dsize = sizeof(num);
+               num = 0;
+               ok1(tdb_store(tdb, k, k, TDB_INSERT) == 0);
+               ok1(tdb_firstkey(tdb, &k) == TDB_SUCCESS);
+               ok1(k.dsize == sizeof(num));
+               ok1(memcmp(k.dptr, &num, sizeof(num)) == 0);
+               ok1(tdb_nextkey(tdb, &k) == TDB_ERR_NOEXIST);
+
+               /* Two entries. */
+               k.dptr = (unsigned char *)&num;
+               k.dsize = sizeof(num);
+               num = 1;
+               ok1(tdb_store(tdb, k, k, TDB_INSERT) == 0);
+               ok1(tdb_firstkey(tdb, &k) == TDB_SUCCESS);
+               ok1(k.dsize == sizeof(num));
+               memcpy(&num, k.dptr, sizeof(num));
+               ok1(num == 0 || num == 1);
+               ok1(tdb_nextkey(tdb, &k) == TDB_SUCCESS);
+               ok1(k.dsize == sizeof(j));
+               memcpy(&j, k.dptr, sizeof(j));
+               ok1(j == 0 || j == 1);
+               ok1(j != num);
+               ok1(tdb_nextkey(tdb, &k) == TDB_ERR_NOEXIST);
+
+               /* Clean up. */
+               k.dptr = (unsigned char *)&num;
+               k.dsize = sizeof(num);
+               num = 0;
+               ok1(tdb_delete(tdb, k) == 0);
+               num = 1;
+               ok1(tdb_delete(tdb, k) == 0);
+
+               /* Now lots of records. */
+               ok1(store_records(tdb));
+               td.calls = 0;
+
+               num = tdb_traverse(tdb, trav, &td);
+               ok1(num == NUM_RECORDS);
+               ok1(td.calls == NUM_RECORDS);
+
+               /* Simple loop should match tdb_traverse */
+               for (j = 0, ecode = tdb_firstkey(tdb, &k); j < td.calls; j++) {
+                       int val;
+
+                       ok1(ecode == TDB_SUCCESS);
+                       ok1(k.dsize == sizeof(val));
+                       memcpy(&val, k.dptr, k.dsize);
+                       ok1(td.records[j] == val);
+                       ecode = tdb_nextkey(tdb, &k);
+               }
+
+               /* But arbitrary orderings should work too. */
+               for (j = td.calls-1; j > 0; j--) {
+                       k.dptr = (unsigned char *)&td.records[j-1];
+                       k.dsize = sizeof(td.records[j-1]);
+                       k = dup_key(k);
+                       ok1(tdb_nextkey(tdb, &k) == TDB_SUCCESS);
+                       ok1(k.dsize == sizeof(td.records[j]));
+                       ok1(memcmp(k.dptr, &td.records[j], k.dsize) == 0);
+                       free(k.dptr);
+               }
+
+               /* Even delete should work. */
+               for (j = 0, ecode = tdb_firstkey(tdb, &k);
+                    ecode != TDB_ERR_NOEXIST;
+                    j++) {
+                       ok1(ecode == TDB_SUCCESS);
+                       ok1(k.dsize == 4);
+                       ok1(tdb_delete(tdb, k) == 0);
+                       ecode = tdb_nextkey(tdb, &k);
+               }
+
+               diag("delete using first/nextkey gave %u of %u records",
+                    j, NUM_RECORDS);
+               ok1(j == NUM_RECORDS);
+               tdb_close(tdb);
+       }
+
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-fork-test.c b/ccan/tdb2/test/api-fork-test.c
new file mode 100644 (file)
index 0000000..6feb618
--- /dev/null
@@ -0,0 +1,204 @@
+/* Test forking while holding lock.
+ *
+ * There are only five ways to do this currently:
+ * (1) grab a tdb_chainlock, then fork.
+ * (2) grab a tdb_lockall, then fork.
+ * (3) grab a tdb_lockall_read, then fork.
+ * (4) start a transaction, then fork.
+ * (5) fork from inside a tdb_parse() callback.
+ *
+ * Note that we don't hold a lock across tdb_traverse callbacks, so
+ * that doesn't matter.
+ */
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "logging.h"
+
+static enum TDB_ERROR fork_in_parse(TDB_DATA key, TDB_DATA data,
+                                   struct tdb_context *tdb)
+{
+       int status, extra_messages;
+
+       if (tdb_get_flags(tdb) & TDB_VERSION1) {
+               extra_messages = 1;
+       } else {
+               extra_messages = 0;
+       }
+
+       if (fork() == 0) {
+               /* We expect this to fail. */
+               if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
+                       exit(1);
+               tap_log_messages -= extra_messages;
+
+               if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
+                       exit(1);
+
+               tap_log_messages -= extra_messages;
+               if (tap_log_messages != 2)
+                       exit(2);
+
+               tdb_close(tdb);
+               if (tap_log_messages != 2)
+                       exit(3);
+               exit(0);
+       }
+       wait(&status);
+       ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+       return TDB_SUCCESS;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
+                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+       struct tdb_data key = tdb_mkdata("key", 3);
+       struct tdb_data data = tdb_mkdata("data", 4);
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 14);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               int status, extra_messages;
+
+               if (flags[i] & TDB_VERSION1) {
+                       extra_messages = 1;
+               } else {
+                       extra_messages = 0;
+               }
+
+               tap_log_messages = 0;
+
+               tdb = tdb_open("run-fork-test.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               if (!ok1(tdb))
+                       continue;
+
+               /* Put a record in here. */
+               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_SUCCESS);
+
+               ok1(tdb_chainlock(tdb, key) == TDB_SUCCESS);
+               if (fork() == 0) {
+                       /* We expect this to fail. */
+                       if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
+                               return 1;
+                       tap_log_messages -= extra_messages;
+
+                       if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
+                               return 1;
+                       tap_log_messages -= extra_messages;
+
+                       if (tap_log_messages != 2)
+                               return 2;
+
+                       tdb_chainunlock(tdb, key);
+                       if (tap_log_messages != 3)
+                               return 3;
+                       tdb_close(tdb);
+                       if (tap_log_messages != 3)
+                               return 4;
+                       return 0;
+               }
+               wait(&status);
+               ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+               tdb_chainunlock(tdb, key);
+
+               ok1(tdb_lockall(tdb) == TDB_SUCCESS);
+               if (fork() == 0) {
+                       /* We expect this to fail. */
+                       if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
+                               return 1;
+                       tap_log_messages -= extra_messages;
+
+                       if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
+                               return 1;
+                       tap_log_messages -= extra_messages;
+
+                       if (tap_log_messages != 2)
+                               return 2;
+
+                       tdb_unlockall(tdb);
+                       if (tap_log_messages != 2)
+                               return 3;
+                       tdb_close(tdb);
+                       if (tap_log_messages != 2)
+                               return 4;
+                       return 0;
+               }
+               wait(&status);
+               ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+               tdb_unlockall(tdb);
+
+               ok1(tdb_lockall_read(tdb) == TDB_SUCCESS);
+               if (fork() == 0) {
+                       /* We expect this to fail. */
+                       /* This would always fail anyway... */
+                       if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
+                               return 1;
+                       tap_log_messages -= extra_messages;
+
+                       if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
+                               return 1;
+                       tap_log_messages -= extra_messages;
+
+                       if (tap_log_messages != 2)
+                               return 2;
+
+                       tdb_unlockall_read(tdb);
+                       if (tap_log_messages != 2)
+                               return 3;
+                       tdb_close(tdb);
+                       if (tap_log_messages != 2)
+                               return 4;
+                       return 0;
+               }
+               wait(&status);
+               ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+               tdb_unlockall_read(tdb);
+
+               ok1(tdb_transaction_start(tdb) == TDB_SUCCESS);
+               /* If transactions is empty, noop "commit" succeeds. */
+               ok1(tdb_delete(tdb, key) == TDB_SUCCESS);
+               if (fork() == 0) {
+                       /* We expect this to fail. */
+                       if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
+                               return 1;
+                       tap_log_messages -= extra_messages;
+
+                       if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
+                               return 1;
+                       tap_log_messages -= extra_messages;
+
+                       if (tap_log_messages != 2)
+                               return 2;
+
+                       if (tdb_transaction_commit(tdb) != TDB_ERR_LOCK)
+                               return 3;
+                       tap_log_messages -= extra_messages;
+
+                       tdb_close(tdb);
+                       if (tap_log_messages < 3)
+                               return 4;
+                       return 0;
+               }
+               wait(&status);
+               ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+               tdb_transaction_cancel(tdb);
+
+               ok1(tdb_parse_record(tdb, key, fork_in_parse, tdb)
+                   == TDB_SUCCESS);
+               tdb_close(tdb);
+               ok1(tap_log_messages == 0);
+       }
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-locktimeout.c b/ccan/tdb2/test/api-locktimeout.c
new file mode 100644 (file)
index 0000000..21a26c4
--- /dev/null
@@ -0,0 +1,194 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include "logging.h"
+#include "external-agent.h"
+
+#undef alarm
+#define alarm fast_alarm
+
+/* Speed things up by doing things in milliseconds. */
+static unsigned int fast_alarm(unsigned int milli_seconds)
+{
+       struct itimerval it;
+
+       it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
+       it.it_value.tv_sec = milli_seconds / 1000;
+       it.it_value.tv_usec = milli_seconds * 1000;
+       setitimer(ITIMER_REAL, &it, NULL);
+       return 0;
+}
+
+#define CatchSignal(sig, handler) signal((sig), (handler))
+
+static void do_nothing(int signum)
+{
+}
+
+/* This example code is taken from SAMBA, so try not to change it. */
+static struct flock flock_struct;
+
+/* Return a value which is none of v1, v2 or v3. */
+static inline short int invalid_value(short int v1, short int v2, short int v3)
+{
+       short int try = (v1+v2+v3)^((v1+v2+v3) << 16);
+       while (try == v1 || try == v2 || try == v3)
+               try++;
+       return try;
+}
+
+/* We invalidate in as many ways as we can, so the OS rejects it */
+static void invalidate_flock_struct(int signum)
+{
+       flock_struct.l_type = invalid_value(F_RDLCK, F_WRLCK, F_UNLCK);
+       flock_struct.l_whence = invalid_value(SEEK_SET, SEEK_CUR, SEEK_END);
+       flock_struct.l_start = -1;
+       /* A large negative. */
+       flock_struct.l_len = (((off_t)1 << (sizeof(off_t)*CHAR_BIT - 1)) + 1);
+}
+
+static int timeout_lock(int fd, int rw, off_t off, off_t len, bool waitflag,
+                       void *_timeout)
+{
+       int ret, saved_errno = errno;
+       unsigned int timeout = *(unsigned int *)_timeout;
+
+       flock_struct.l_type = rw;
+       flock_struct.l_whence = SEEK_SET;
+       flock_struct.l_start = off;
+       flock_struct.l_len = len;
+
+       CatchSignal(SIGALRM, invalidate_flock_struct);
+       alarm(timeout);
+
+       for (;;) {
+               if (waitflag)
+                       ret = fcntl(fd, F_SETLKW, &flock_struct);
+               else
+                       ret = fcntl(fd, F_SETLK, &flock_struct);
+
+               if (ret == 0)
+                       break;
+
+               /* Not signalled?  Something else went wrong. */
+               if (flock_struct.l_len == len) {
+                       if (errno == EAGAIN || errno == EINTR)
+                               continue;
+                       saved_errno = errno;
+                       break;
+               } else {
+                       saved_errno = EINTR;
+                       break;
+               }
+       }
+
+       alarm(0);
+       errno = saved_errno;
+       return ret;
+}
+
+static int tdb_chainlock_with_timeout_internal(struct tdb_context *tdb,
+                                              TDB_DATA key,
+                                              unsigned int timeout,
+                                              int rw_type)
+{
+       union tdb_attribute locking;
+       enum TDB_ERROR ecode;
+
+       if (timeout) {
+               locking.base.attr = TDB_ATTRIBUTE_FLOCK;
+               ecode = tdb_get_attribute(tdb, &locking);
+               if (ecode != TDB_SUCCESS)
+                       return ecode;
+
+               /* Replace locking function with our own. */
+               locking.flock.data = &timeout;
+               locking.flock.lock = timeout_lock;
+
+               ecode = tdb_set_attribute(tdb, &locking);
+               if (ecode != TDB_SUCCESS)
+                       return ecode;
+       }
+       if (rw_type == F_RDLCK)
+               ecode = tdb_chainlock_read(tdb, key);
+       else
+               ecode = tdb_chainlock(tdb, key);
+
+       if (timeout) {
+               tdb_unset_attribute(tdb, TDB_ATTRIBUTE_FLOCK);
+       }
+       return ecode;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       TDB_DATA key = tdb_mkdata("hello", 5);
+       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
+                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+       struct agent *agent;
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 15);
+
+       agent = prepare_external_agent();
+
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               enum TDB_ERROR ecode;
+               tdb = tdb_open("run-locktimeout.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               if (!ok1(tdb))
+                       break;
+
+               /* Simple cases: should succeed. */
+               ecode = tdb_chainlock_with_timeout_internal(tdb, key, 20,
+                                                           F_RDLCK);
+               ok1(ecode == TDB_SUCCESS);
+               ok1(tap_log_messages == 0);
+
+               tdb_chainunlock_read(tdb, key);
+               ok1(tap_log_messages == 0);
+
+               ecode = tdb_chainlock_with_timeout_internal(tdb, key, 20,
+                                                           F_WRLCK);
+               ok1(ecode == TDB_SUCCESS);
+               ok1(tap_log_messages == 0);
+
+               tdb_chainunlock(tdb, key);
+               ok1(tap_log_messages == 0);
+
+               /* OK, get agent to start transaction, then we should time out. */
+               ok1(external_agent_operation(agent, OPEN, "run-locktimeout.tdb")
+                   == SUCCESS);
+               ok1(external_agent_operation(agent, TRANSACTION_START, "")
+                   == SUCCESS);
+               ecode = tdb_chainlock_with_timeout_internal(tdb, key, 20,
+                                                           F_WRLCK);
+               ok1(ecode == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+
+               /* Even if we get a different signal, should be fine. */
+               CatchSignal(SIGUSR1, do_nothing);
+               external_agent_operation(agent, SEND_SIGNAL, "");
+               ecode = tdb_chainlock_with_timeout_internal(tdb, key, 20,
+                                                           F_WRLCK);
+               ok1(ecode == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 0);
+
+               ok1(external_agent_operation(agent, TRANSACTION_COMMIT, "")
+                   == SUCCESS);
+               ok1(external_agent_operation(agent, CLOSE, "")
+                   == SUCCESS);
+               tdb_close(tdb);
+       }
+       free_external_agent(agent);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-missing-entries.c b/ccan/tdb2/test/api-missing-entries.c
new file mode 100644 (file)
index 0000000..1932947
--- /dev/null
@@ -0,0 +1,44 @@
+/* Another test revealed that we lost an entry.  This reproduces it. */
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/hash/hash.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "logging.h"
+
+#define NUM_RECORDS 1189
+
+/* We use the same seed which we saw this failure on. */
+static uint64_t failhash(const void *key, size_t len, uint64_t seed, void *p)
+{
+       seed = 699537674708983027ULL;
+       return hash64_stable((const unsigned char *)key, len, seed);
+}
+
+int main(int argc, char *argv[])
+{
+       int i;
+       struct tdb_context *tdb;
+       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
+       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
+       union tdb_attribute hattr = { .hash = { .base = { TDB_ATTRIBUTE_HASH },
+                                               .fn = failhash } };
+
+       hattr.base.next = &tap_log_attr;
+       plan_tests(1 + 2 * NUM_RECORDS + 1);
+
+       tdb = tdb_open("run-missing-entries.tdb", TDB_INTERNAL,
+                      O_RDWR|O_CREAT|O_TRUNC, 0600, &hattr);
+       ok1(tdb);
+       if (tdb) {
+               for (i = 0; i < NUM_RECORDS; i++) {
+                       ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
+                       ok1(tdb_check(tdb, NULL, NULL) == 0);
+               }
+               tdb_close(tdb);
+       }
+
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-open-multiple-times.c b/ccan/tdb2/test/api-open-multiple-times.c
new file mode 100644 (file)
index 0000000..1656206
--- /dev/null
@@ -0,0 +1,93 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+       unsigned int i, extra_messages;
+       struct tdb_context *tdb, *tdb2;
+       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
+       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
+       struct tdb_data d = { NULL, 0 }; /* Bogus GCC warning */
+       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
+                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 28);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-open-multiple-times.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               ok1(tdb);
+               if (!tdb)
+                       continue;
+
+               if (flags[i] & TDB_VERSION1) {
+                       extra_messages = 1;
+               } else {
+                       extra_messages = 0;
+               }
+               tdb2 = tdb_open("run-open-multiple-times.tdb", flags[i],
+                               O_RDWR|O_CREAT, 0600, &tap_log_attr);
+               ok1(tdb_check(tdb, NULL, NULL) == 0);
+               ok1(tdb_check(tdb2, NULL, NULL) == 0);
+
+               /* Store in one, fetch in the other. */
+               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
+               ok1(tdb_fetch(tdb2, key, &d) == TDB_SUCCESS);
+               ok1(tdb_deq(d, data));
+               free(d.dptr);
+
+               /* Vice versa, with delete. */
+               ok1(tdb_delete(tdb2, key) == 0);
+               ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_NOEXIST);
+
+               /* OK, now close first one, check second still good. */
+               ok1(tdb_close(tdb) == 0);
+
+               ok1(tdb_store(tdb2, key, data, TDB_REPLACE) == 0);
+               ok1(tdb_fetch(tdb2, key, &d) == TDB_SUCCESS);
+               ok1(tdb_deq(d, data));
+               free(d.dptr);
+
+               /* Reopen */
+               tdb = tdb_open("run-open-multiple-times.tdb", flags[i],
+                              O_RDWR|O_CREAT, 0600, &tap_log_attr);
+               ok1(tdb);
+
+               ok1(tdb_transaction_start(tdb2) == 0);
+
+               /* Anything in the other one should fail. */
+               ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK);
+               tap_log_messages -= extra_messages;
+               ok1(tap_log_messages == 1);
+               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK);
+               tap_log_messages -= extra_messages;
+               ok1(tap_log_messages == 2);
+               ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK);
+               ok1(tap_log_messages == 3);
+               ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK);
+               tap_log_messages -= extra_messages;
+               ok1(tap_log_messages == 4);
+
+               /* Transaciton should work as normal. */
+               ok1(tdb_store(tdb2, key, data, TDB_REPLACE) == TDB_SUCCESS);
+
+               /* Now... try closing with locks held. */
+               ok1(tdb_close(tdb2) == 0);
+
+               ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
+               ok1(tdb_deq(d, data));
+               free(d.dptr);
+               ok1(tdb_close(tdb) == 0);
+               ok1(tap_log_messages == 4);
+               tap_log_messages = 0;
+       }
+
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-record-expand.c b/ccan/tdb2/test/api-record-expand.c
new file mode 100644 (file)
index 0000000..48ad1cd
--- /dev/null
@@ -0,0 +1,55 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "logging.h"
+
+#define MAX_SIZE 10000
+#define SIZE_STEP 131
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+       struct tdb_data key = tdb_mkdata("key", 3);
+       struct tdb_data data;
+
+       data.dptr = malloc(MAX_SIZE);
+       memset(data.dptr, 0x24, MAX_SIZE);
+
+       plan_tests(sizeof(flags) / sizeof(flags[0])
+                  * (3 + (1 + (MAX_SIZE/SIZE_STEP)) * 2) + 1);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-record-expand.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               ok1(tdb);
+               if (!tdb)
+                       continue;
+
+               data.dsize = 0;
+               ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+               ok1(tdb_check(tdb, NULL, NULL) == 0);
+               for (data.dsize = 0;
+                    data.dsize < MAX_SIZE;
+                    data.dsize += SIZE_STEP) {
+                       memset(data.dptr, data.dsize, data.dsize);
+                       ok1(tdb_store(tdb, key, data, TDB_MODIFY) == 0);
+                       ok1(tdb_check(tdb, NULL, NULL) == 0);
+               }
+               tdb_close(tdb);
+       }
+       ok1(tap_log_messages == 0);
+       free(data.dptr);
+
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-simple-delete.c b/ccan/tdb2/test/api-simple-delete.c
new file mode 100644 (file)
index 0000000..a5b65d6
--- /dev/null
@@ -0,0 +1,43 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+       struct tdb_data key = tdb_mkdata("key", 3);
+       struct tdb_data data = tdb_mkdata("data", 4);
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * 7 + 1);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-simple-delete.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               ok1(tdb);
+               if (tdb) {
+                       /* Delete should fail. */
+                       ok1(tdb_delete(tdb, key) == TDB_ERR_NOEXIST);
+                       ok1(tdb_check(tdb, NULL, NULL) == 0);
+                       /* Insert should succeed. */
+                       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
+                       ok1(tdb_check(tdb, NULL, NULL) == 0);
+                       /* Delete should now work. */
+                       ok1(tdb_delete(tdb, key) == 0);
+                       ok1(tdb_check(tdb, NULL, NULL) == 0);
+                       tdb_close(tdb);
+               }
+       }
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/api-summary.c b/ccan/tdb2/test/api-summary.c
new file mode 100644 (file)
index 0000000..e0e292e
--- /dev/null
@@ -0,0 +1,63 @@
+#include <ccan/tdb2/tdb2.h>
+#include <ccan/tap/tap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "logging.h"
+
+int main(int argc, char *argv[])
+{
+       unsigned int i, j;
+       struct tdb_context *tdb;
+       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
+                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
+                       TDB_NOMMAP|TDB_CONVERT,
+                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
+                       TDB_NOMMAP|TDB_VERSION1,
+                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
+                       TDB_CONVERT|TDB_VERSION1,
+                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
+       struct tdb_data key = { (unsigned char *)&j, sizeof(j) };
+       struct tdb_data data = { (unsigned char *)&j, sizeof(j) };
+       char *summary;
+
+       plan_tests(sizeof(flags) / sizeof(flags[0]) * (1 + 2 * 5) + 1);
+       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+               tdb = tdb_open("run-summary.tdb", flags[i],
+                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
+               ok1(tdb);
+               if (!tdb)
+                       continue;
+
+               /* Put some stuff in there. */
+               for (j = 0; j < 500; j++) {
+                       /* Make sure padding varies to we get some graphs! */
+                       data.dsize = j % (sizeof(j) + 1);
+                       if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
+                               fail("Storing in tdb");
+               }
+
+               for (j = 0;
+                    j <= TDB_SUMMARY_HISTOGRAMS;
+                    j += TDB_SUMMARY_HISTOGRAMS) {
+                       ok1(tdb_summary(tdb, j, &summary) == TDB_SUCCESS);
+                       ok1(strstr(summary, "Number of records: 500\n"));
+                       ok1(strstr(summary, "Smallest/average/largest keys: 4/4/4\n"));
+                       ok1(strstr(summary, "Smallest/average/largest data: 0/2/4\n"));
+                       if (!(flags[i] & TDB_VERSION1)
+                           && j == TDB_SUMMARY_HISTOGRAMS) {
+                               ok1(strstr(summary, "|")
+                                   && strstr(summary, "*"));
+                       } else {
+                               ok1(!strstr(summary, "|")
+                                   && !strstr(summary, "*"));
+                       }
+                       free(summary);
+               }
+               tdb_close(tdb);
+       }
+
+       ok1(tap_log_messages == 0);
+       return exit_status();
+}
diff --git a/ccan/tdb2/test/run-12-store.c b/ccan/tdb2/test/run-12-store.c
deleted file mode 100644 (file)
index 73ffd55..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-/* We use the same seed which we saw a failure on. */
-static uint64_t fixedhash(const void *key, size_t len, uint64_t seed, void *p)
-{
-       return hash64_stable((const unsigned char *)key, len,
-                            *(uint64_t *)p);
-}
-
-int main(int argc, char *argv[])
-{
-       unsigned int i, j;
-       struct tdb_context *tdb;
-       uint64_t seed = 16014841315512641303ULL;
-       union tdb_attribute fixed_hattr
-               = { .hash = { .base = { TDB_ATTRIBUTE_HASH },
-                             .fn = fixedhash,
-                             .data = &seed } };
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
-                       TDB_NOMMAP|TDB_CONVERT };
-       struct tdb_data key = { (unsigned char *)&j, sizeof(j) };
-       struct tdb_data data = { (unsigned char *)&j, sizeof(j) };
-
-       fixed_hattr.base.next = &tap_log_attr;
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * (1 + 500 * 3) + 1);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-12-store.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &fixed_hattr);
-               ok1(tdb);
-               if (!tdb)
-                       continue;
-
-               /* We seemed to lose some keys.
-                * Insert and check they're in there! */
-               for (j = 0; j < 500; j++) {
-                       struct tdb_data d = { NULL, 0 }; /* Bogus GCC warning */
-                       ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
-                       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
-                       ok1(tdb_deq(d, data));
-                       free(d.dptr);
-               }
-               tdb_close(tdb);
-       }
-
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
-
-
diff --git a/ccan/tdb2/test/run-13-delete.c b/ccan/tdb2/test/run-13-delete.c
deleted file mode 100644 (file)
index fdbc9db..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-/* We rig the hash so adjacent-numbered records always clash. */
-static uint64_t clash(const void *key, size_t len, uint64_t seed, void *priv)
-{
-       return ((uint64_t)*(const unsigned int *)key)
-               << (64 - TDB_TOPLEVEL_HASH_BITS - 1);
-}
-
-/* We use the same seed which we saw a failure on. */
-static uint64_t fixedhash(const void *key, size_t len, uint64_t seed, void *p)
-{
-       return hash64_stable((const unsigned char *)key, len,
-                            *(uint64_t *)p);
-}
-
-static bool store_records(struct tdb_context *tdb)
-{
-       int i;
-       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
-       struct tdb_data d, data = { (unsigned char *)&i, sizeof(i) };
-
-       for (i = 0; i < 1000; i++) {
-               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
-                       return false;
-               tdb_fetch(tdb, key, &d);
-               if (!tdb_deq(d, data))
-                       return false;
-               free(d.dptr);
-       }
-       return true;
-}
-
-static void test_val(struct tdb_context *tdb, uint64_t val)
-{
-       uint64_t v;
-       struct tdb_data key = { (unsigned char *)&v, sizeof(v) };
-       struct tdb_data d, data = { (unsigned char *)&v, sizeof(v) };
-
-       /* Insert an entry, then delete it. */
-       v = val;
-       /* Delete should fail. */
-       ok1(tdb_delete(tdb, key) == TDB_ERR_NOEXIST);
-       ok1(tdb_check(tdb, NULL, NULL) == 0);
-
-       /* Insert should succeed. */
-       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-       ok1(tdb_check(tdb, NULL, NULL) == 0);
-
-       /* Delete should succeed. */
-       ok1(tdb_delete(tdb, key) == 0);
-       ok1(tdb_check(tdb, NULL, NULL) == 0);
-
-       /* Re-add it, then add collision. */
-       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-       v = val + 1;
-       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-       ok1(tdb_check(tdb, NULL, NULL) == 0);
-
-       /* Can find both? */
-       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
-       ok1(d.dsize == data.dsize);
-       free(d.dptr);
-       v = val;
-       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
-       ok1(d.dsize == data.dsize);
-       free(d.dptr);
-
-       /* Delete second one. */
-       v = val + 1;
-       ok1(tdb_delete(tdb, key) == 0);
-       ok1(tdb_check(tdb, NULL, NULL) == 0);
-
-       /* Re-add */
-       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-       ok1(tdb_check(tdb, NULL, NULL) == 0);
-
-       /* Now, try deleting first one. */
-       v = val;
-       ok1(tdb_delete(tdb, key) == 0);
-       ok1(tdb_check(tdb, NULL, NULL) == 0);
-
-       /* Can still find second? */
-       v = val + 1;
-       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
-       ok1(d.dsize == data.dsize);
-       free(d.dptr);
-
-       /* Now, this will be ideally placed. */
-       v = val + 2;
-       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-       ok1(tdb_check(tdb, NULL, NULL) == 0);
-
-       /* This will collide with both. */
-       v = val;
-       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-
-       /* We can still find them all, right? */
-       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
-       ok1(d.dsize == data.dsize);
-       free(d.dptr);
-       v = val + 1;
-       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
-       ok1(d.dsize == data.dsize);
-       free(d.dptr);
-       v = val + 2;
-       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
-       ok1(d.dsize == data.dsize);
-       free(d.dptr);
-
-       /* And if we delete val + 1, that val + 2 should not move! */
-       v = val + 1;
-       ok1(tdb_delete(tdb, key) == 0);
-       ok1(tdb_check(tdb, NULL, NULL) == 0);
-
-       v = val;
-       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
-       ok1(d.dsize == data.dsize);
-       free(d.dptr);
-       v = val + 2;
-       ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
-       ok1(d.dsize == data.dsize);
-       free(d.dptr);
-
-       /* Delete those two, so we are empty. */
-       ok1(tdb_delete(tdb, key) == 0);
-       v = val;
-       ok1(tdb_delete(tdb, key) == 0);
-
-       ok1(tdb_check(tdb, NULL, NULL) == 0);
-}
-
-int main(int argc, char *argv[])
-{
-       unsigned int i, j;
-       struct tdb_context *tdb;
-       uint64_t seed = 16014841315512641303ULL;
-       union tdb_attribute clash_hattr
-               = { .hash = { .base = { TDB_ATTRIBUTE_HASH },
-                             .fn = clash } };
-       union tdb_attribute fixed_hattr
-               = { .hash = { .base = { TDB_ATTRIBUTE_HASH },
-                             .fn = fixedhash,
-                             .data = &seed } };
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-       /* These two values gave trouble before. */
-       int vals[] = { 755, 837 };
-
-       clash_hattr.base.next = &tap_log_attr;
-       fixed_hattr.base.next = &tap_log_attr;
-
-       plan_tests(sizeof(flags) / sizeof(flags[0])
-                  * (39 * 3 + 5 + sizeof(vals)/sizeof(vals[0])*2) + 1);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-13-delete.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &clash_hattr);
-               ok1(tdb);
-               if (!tdb)
-                       continue;
-
-               /* Check start of hash table. */
-               test_val(tdb, 0);
-
-               /* Check end of hash table. */
-               test_val(tdb, -1ULL);
-
-               /* Check mixed bitpattern. */
-               test_val(tdb, 0x123456789ABCDEF0ULL);
-
-               ok1(!tdb->file || (tdb->file->allrecord_lock.count == 0
-                                  && tdb->file->num_lockrecs == 0));
-               tdb_close(tdb);
-
-               /* Deleting these entries in the db gave problems. */
-               tdb = tdb_open("run-13-delete.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &fixed_hattr);
-               ok1(tdb);
-               if (!tdb)
-                       continue;
-
-               ok1(store_records(tdb));
-               ok1(tdb_check(tdb, NULL, NULL) == 0);
-               for (j = 0; j < sizeof(vals)/sizeof(vals[0]); j++) {
-                       struct tdb_data key;
-
-                       key.dptr = (unsigned char *)&vals[j];
-                       key.dsize = sizeof(vals[j]);
-                       ok1(tdb_delete(tdb, key) == 0);
-                       ok1(tdb_check(tdb, NULL, NULL) == 0);
-               }
-               tdb_close(tdb);
-       }
-
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-14-exists.c b/ccan/tdb2/test/run-14-exists.c
deleted file mode 100644 (file)
index 7ff4514..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-static bool test_records(struct tdb_context *tdb)
-{
-       int i;
-       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
-       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
-
-       for (i = 0; i < 1000; i++) {
-               if (tdb_exists(tdb, key))
-                       return false;
-               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
-                       return false;
-               if (!tdb_exists(tdb, key))
-                       return false;
-       }
-
-       for (i = 0; i < 1000; i++) {
-               if (!tdb_exists(tdb, key))
-                       return false;
-               if (tdb_delete(tdb, key) != 0)
-                       return false;
-               if (tdb_exists(tdb, key))
-                       return false;
-       }
-       return true;
-}
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 2 + 1);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-14-exists.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               if (ok1(tdb))
-                       ok1(test_records(tdb));
-               tdb_close(tdb);
-       }
-
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-16-wipe_all.c b/ccan/tdb2/test/run-16-wipe_all.c
deleted file mode 100644 (file)
index 27d6f43..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-static bool add_records(struct tdb_context *tdb)
-{
-       int i;
-       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
-       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
-
-       for (i = 0; i < 1000; i++) {
-               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
-                       return false;
-       }
-       return true;
-}
-
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 4 + 1);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-16-wipe_all.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               if (ok1(tdb)) {
-                       struct tdb_data key;
-                       ok1(add_records(tdb));
-                       ok1(tdb_wipe_all(tdb) == TDB_SUCCESS);
-                       ok1(tdb_firstkey(tdb, &key) == TDB_ERR_NOEXIST);
-                       tdb_close(tdb);
-               }
-       }
-
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-21-parse_record.c b/ccan/tdb2/test/run-21-parse_record.c
deleted file mode 100644 (file)
index c7414a4..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-static enum TDB_ERROR parse(TDB_DATA key, TDB_DATA data, TDB_DATA *expected)
-{
-       if (!tdb_deq(data, *expected))
-               return TDB_ERR_EINVAL;
-       return TDB_SUCCESS;
-}
-
-static enum TDB_ERROR parse_err(TDB_DATA key, TDB_DATA data, void *unused)
-{
-       return 100;
-}
-
-static bool test_records(struct tdb_context *tdb)
-{
-       int i;
-       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
-       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
-
-       for (i = 0; i < 1000; i++) {
-               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
-                       return false;
-       }
-
-       for (i = 0; i < 1000; i++) {
-               if (tdb_parse_record(tdb, key, parse, &data) != TDB_SUCCESS)
-                       return false;
-       }
-
-       if (tdb_parse_record(tdb, key, parse, &data) != TDB_ERR_NOEXIST)
-               return false;
-
-       /* Test error return from parse function. */
-       i = 0;
-       if (tdb_parse_record(tdb, key, parse_err, NULL) != 100)
-               return false;
-
-       return true;
-}
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 2 + 1);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-14-exists.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               if (ok1(tdb))
-                       ok1(test_records(tdb));
-               tdb_close(tdb);
-       }
-
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-55-transaction.c b/ccan/tdb2/test/run-55-transaction.c
deleted file mode 100644 (file)
index 95545b7..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       unsigned char *buffer;
-       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
-                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-       struct tdb_data key = tdb_mkdata("key", 3);
-       struct tdb_data data;
-
-       buffer = malloc(1000);
-       for (i = 0; i < 1000; i++)
-               buffer[i] = i;
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 20 + 1);
-
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-55-transaction.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               ok1(tdb);
-               if (!tdb)
-                       continue;
-
-               ok1(tdb_transaction_start(tdb) == 0);
-               data.dptr = buffer;
-               data.dsize = 1000;
-               ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-               ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
-               ok1(data.dsize == 1000);
-               ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
-               free(data.dptr);
-
-               /* Cancelling a transaction means no store */
-               tdb_transaction_cancel(tdb);
-               ok1(tdb->file->allrecord_lock.count == 0
-                   && tdb->file->num_lockrecs == 0);
-               ok1(tdb_check(tdb, NULL, NULL) == 0);
-               ok1(tdb_fetch(tdb, key, &data) == TDB_ERR_NOEXIST);
-
-               /* Commit the transaction. */
-               ok1(tdb_transaction_start(tdb) == 0);
-               data.dptr = buffer;
-               data.dsize = 1000;
-               ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-               ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
-               ok1(data.dsize == 1000);
-               ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
-               free(data.dptr);
-               ok1(tdb_transaction_commit(tdb) == 0);
-               ok1(tdb->file->allrecord_lock.count == 0
-                   && tdb->file->num_lockrecs == 0);
-               ok1(tdb_check(tdb, NULL, NULL) == 0);
-               ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
-               ok1(data.dsize == 1000);
-               ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
-               free(data.dptr);
-
-               tdb_close(tdb);
-       }
-
-       ok1(tap_log_messages == 0);
-       free(buffer);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-80-tdb_fd.c b/ccan/tdb2/test/run-80-tdb_fd.c
deleted file mode 100644 (file)
index 7faed41..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, 
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 3);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-new_database.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               if (!ok1(tdb))
-                       continue;
-
-               if (flags[i] & TDB_INTERNAL)
-                       ok1(tdb_fd(tdb) == -1);
-               else
-                       ok1(tdb_fd(tdb) > 2);
-               tdb_close(tdb);
-               ok1(tap_log_messages == 0);
-       }
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-81-seqnum.c b/ccan/tdb2/test/run-81-seqnum.c
deleted file mode 100644 (file)
index b33d0a2..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-int main(int argc, char *argv[])
-{
-       unsigned int i, seq;
-       struct tdb_context *tdb;
-       struct tdb_data d = { NULL, 0 }; /* Bogus GCC warning */
-       struct tdb_data key = tdb_mkdata("key", 3);
-       struct tdb_data data = tdb_mkdata("data", 4);
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 15 + 8 * 13);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-new_database.tdb", flags[i]|TDB_SEQNUM,
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               if (!ok1(tdb))
-                       continue;
-               
-               seq = 0;
-               ok1(tdb_get_seqnum(tdb) == seq);
-               ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-               ok1(tdb_get_seqnum(tdb) == ++seq);
-               /* Fetch doesn't change seqnum */
-               if (ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS))
-                       free(d.dptr);
-               ok1(tdb_get_seqnum(tdb) == seq);
-               ok1(tdb_append(tdb, key, data) == TDB_SUCCESS);
-               /* Append in tdb1 (or store over value) bumps twice! */
-               if (flags[i] & TDB_VERSION1)
-                       seq++;
-               ok1(tdb_get_seqnum(tdb) == ++seq);
-
-               ok1(tdb_delete(tdb, key) == TDB_SUCCESS);
-               ok1(tdb_get_seqnum(tdb) == ++seq);
-               /* Empty append works */
-               ok1(tdb_append(tdb, key, data) == TDB_SUCCESS);
-               ok1(tdb_get_seqnum(tdb) == ++seq);
-
-               ok1(tdb_wipe_all(tdb) == TDB_SUCCESS);
-               ok1(tdb_get_seqnum(tdb) == ++seq);
-
-               if (!(flags[i] & TDB_INTERNAL)) {
-                       ok1(tdb_transaction_start(tdb) == TDB_SUCCESS);
-                       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-                       ok1(tdb_get_seqnum(tdb) == ++seq);
-                       /* Append in tdb1 (or store over value) bumps twice! */
-                       if (flags[i] & TDB_VERSION1)
-                               seq++;
-                       ok1(tdb_append(tdb, key, data) == TDB_SUCCESS);
-                       ok1(tdb_get_seqnum(tdb) == ++seq);
-                       ok1(tdb_delete(tdb, key) == TDB_SUCCESS);
-                       ok1(tdb_get_seqnum(tdb) == ++seq);
-                       ok1(tdb_transaction_commit(tdb) == TDB_SUCCESS);
-                       ok1(tdb_get_seqnum(tdb) == seq);
-
-                       ok1(tdb_transaction_start(tdb) == TDB_SUCCESS);
-                       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-                       ok1(tdb_get_seqnum(tdb) == seq + 1);
-                       tdb_transaction_cancel(tdb);
-                       ok1(tdb_get_seqnum(tdb) == seq);
-               }
-               tdb_close(tdb);
-               ok1(tap_log_messages == 0);
-       }
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-82-lockattr.c b/ccan/tdb2/test/run-82-lockattr.c
deleted file mode 100644 (file)
index acad439..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-static int mylock(int fd, int rw, off_t off, off_t len, bool waitflag,
-                 void *_err)
-{
-       int *lock_err = _err;
-       struct flock fl;
-       int ret;
-
-       if (*lock_err) {
-               errno = *lock_err;
-               return -1;
-       }
-
-       do {
-               fl.l_type = rw;
-               fl.l_whence = SEEK_SET;
-               fl.l_start = off;
-               fl.l_len = len;
-
-               if (waitflag)
-                       ret = fcntl(fd, F_SETLKW, &fl);
-               else
-                       ret = fcntl(fd, F_SETLK, &fl);
-       } while (ret != 0 && errno == EINTR);
-
-       return ret;
-}
-
-static int trav_err;
-static int trav(struct tdb_context *tdb, TDB_DATA k, TDB_DATA d, int *err)
-{
-       *err = trav_err;
-       return 0;
-}
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
-                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-       union tdb_attribute lock_attr;
-       struct tdb_data key = tdb_mkdata("key", 3);
-       struct tdb_data data = tdb_mkdata("data", 4);
-       int lock_err;
-
-       lock_attr.base.attr = TDB_ATTRIBUTE_FLOCK;
-       lock_attr.base.next = &tap_log_attr;
-       lock_attr.flock.lock = mylock;
-       lock_attr.flock.unlock = tdb_fcntl_unlock;
-       lock_attr.flock.data = &lock_err;
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 80);
-
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               struct tdb_data d;
-               unsigned int num_oom_messages;
-
-               /* TDB1 double logs here. */
-               if (flags[i] & TDB_VERSION1) {
-                       num_oom_messages = 2;
-               } else {
-                       num_oom_messages = 1;
-               }
-
-               /* Nonblocking open; expect no error message. */
-               lock_err = EAGAIN;
-               tdb = tdb_open("run-82-lockattr.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
-               ok(errno == lock_err, "Errno is %u", errno);
-               ok1(!tdb);
-               ok1(tap_log_messages == 0);
-
-               lock_err = EINTR;
-               tdb = tdb_open("run-82-lockattr.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
-               ok(errno == lock_err, "Errno is %u", errno);
-               ok1(!tdb);
-               ok1(tap_log_messages == 0);
-
-               /* Forced fail open. */
-               lock_err = ENOMEM;
-               tdb = tdb_open("run-82-lockattr.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
-               ok1(errno == lock_err);
-               ok1(!tdb);
-               ok1(tap_log_messages == 1);
-               tap_log_messages = 0;
-
-               lock_err = 0;
-               tdb = tdb_open("run-82-lockattr.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
-               if (!ok1(tdb))
-                       continue;
-               ok1(tap_log_messages == 0);
-
-               /* Nonblocking store. */
-               lock_err = EAGAIN;
-               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = EINTR;
-               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = ENOMEM;
-               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == num_oom_messages);
-               tap_log_messages = 0;
-
-               /* Nonblocking fetch. */
-               lock_err = EAGAIN;
-               ok1(!tdb_exists(tdb, key));
-               ok1(tap_log_messages == 0);
-               lock_err = EINTR;
-               ok1(!tdb_exists(tdb, key));
-               ok1(tap_log_messages == 0);
-               lock_err = ENOMEM;
-               ok1(!tdb_exists(tdb, key));
-               ok1(tap_log_messages == num_oom_messages);
-               tap_log_messages = 0;
-
-               lock_err = EAGAIN;
-               ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = EINTR;
-               ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = ENOMEM;
-               ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == num_oom_messages);
-               tap_log_messages = 0;
-
-               /* Nonblocking delete. */
-               lock_err = EAGAIN;
-               ok1(tdb_delete(tdb, key) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = EINTR;
-               ok1(tdb_delete(tdb, key) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = ENOMEM;
-               ok1(tdb_delete(tdb, key) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == num_oom_messages);
-               tap_log_messages = 0;
-
-               /* Nonblocking locks. */
-               lock_err = EAGAIN;
-               ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = EINTR;
-               ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = ENOMEM;
-               ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == num_oom_messages);
-               tap_log_messages = 0;
-
-               lock_err = EAGAIN;
-               ok1(tdb_chainlock_read(tdb, key) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = EINTR;
-               ok1(tdb_chainlock_read(tdb, key) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = ENOMEM;
-               ok1(tdb_chainlock_read(tdb, key) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == num_oom_messages);
-               tap_log_messages = 0;
-
-               lock_err = EAGAIN;
-               ok1(tdb_lockall(tdb) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = EINTR;
-               ok1(tdb_lockall(tdb) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = ENOMEM;
-               ok1(tdb_lockall(tdb) == TDB_ERR_LOCK);
-               /* This actually does divide and conquer. */
-               ok1(tap_log_messages > 0);
-               tap_log_messages = 0;
-
-               lock_err = EAGAIN;
-               ok1(tdb_lockall_read(tdb) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = EINTR;
-               ok1(tdb_lockall_read(tdb) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = ENOMEM;
-               ok1(tdb_lockall_read(tdb) == TDB_ERR_LOCK);
-               ok1(tap_log_messages > 0);
-               tap_log_messages = 0;
-
-               /* Nonblocking traverse; go nonblock partway through. */
-               lock_err = 0;
-               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
-               trav_err = EAGAIN;
-               ok1(tdb_traverse(tdb, trav, &lock_err) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               trav_err = EINTR;
-               lock_err = 0;
-               ok1(tdb_traverse(tdb, trav, &lock_err) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               trav_err = ENOMEM;
-               lock_err = 0;
-               ok1(tdb_traverse(tdb, trav, &lock_err) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == num_oom_messages);
-               tap_log_messages = 0;
-
-               /* Nonblocking transactions. */
-               lock_err = EAGAIN;
-               ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = EINTR;
-               ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-               lock_err = ENOMEM;
-               ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 1);
-               tap_log_messages = 0;
-
-               /* Nonblocking transaction prepare. */
-               lock_err = 0;
-               ok1(tdb_transaction_start(tdb) == 0);
-               ok1(tdb_delete(tdb, key) == 0);
-
-               lock_err = EAGAIN;
-               ok1(tdb_transaction_prepare_commit(tdb) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-
-               lock_err = 0;
-               ok1(tdb_transaction_prepare_commit(tdb) == 0);
-               ok1(tdb_transaction_commit(tdb) == 0);
-
-               /* And the transaction was committed, right? */
-               ok1(!tdb_exists(tdb, key));
-               tdb_close(tdb);
-               ok1(tap_log_messages == 0);
-       }
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-83-openhook.c b/ccan/tdb2/test/run-83-openhook.c
deleted file mode 100644 (file)
index 59b1e65..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdarg.h>
-#include <err.h>
-#include "external-agent.h"
-#include "logging.h"
-
-static enum TDB_ERROR clear_if_first(int fd, void *arg)
-{
-/* We hold a lock offset 4 always, so we can tell if anyone is holding it.
- * (This is compatible with tdb1's TDB_CLEAR_IF_FIRST flag).  */
-       struct flock fl;
-
-       if (arg != clear_if_first)
-               return TDB_ERR_CORRUPT;
-
-       fl.l_type = F_WRLCK;
-       fl.l_whence = SEEK_SET;
-       fl.l_start = 4;
-       fl.l_len = 1;
-
-       if (fcntl(fd, F_SETLK, &fl) == 0) {
-               /* We must be first ones to open it! */
-               diag("truncating file!");
-               if (ftruncate(fd, 0) != 0) {
-                       return TDB_ERR_IO;
-               }
-       }
-       fl.l_type = F_RDLCK;
-       if (fcntl(fd, F_SETLKW, &fl) != 0) {
-               return TDB_ERR_IO;
-       }
-       return TDB_SUCCESS;
-}
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       struct agent *agent;
-       union tdb_attribute cif;
-       struct tdb_data key = tdb_mkdata("key", 3);
-       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
-                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       cif.openhook.base.attr = TDB_ATTRIBUTE_OPENHOOK;
-       cif.openhook.base.next = &tap_log_attr;
-       cif.openhook.fn = clear_if_first;
-       cif.openhook.data = clear_if_first;
-
-       agent = prepare_external_agent();
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 13);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               /* Create it */
-               tdb = tdb_open("run-83-openhook.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, NULL);
-               ok1(tdb);
-               ok1(tdb_store(tdb, key, key, TDB_REPLACE) == 0);
-               tdb_close(tdb);
-
-               /* Now, open with CIF, should clear it. */
-               tdb = tdb_open("run-83-openhook.tdb", flags[i],
-                              O_RDWR, 0, &cif);
-               ok1(tdb);
-               ok1(!tdb_exists(tdb, key));
-               ok1(tdb_store(tdb, key, key, TDB_REPLACE) == 0);
-
-               /* Agent should not clear it, since it's still open. */
-               ok1(external_agent_operation(agent, OPEN_WITH_HOOK,
-                                            "run-83-openhook.tdb") == SUCCESS);
-               ok1(external_agent_operation(agent, FETCH, "key") == SUCCESS);
-               ok1(external_agent_operation(agent, CLOSE, "") == SUCCESS);
-
-               /* Still exists for us too. */
-               ok1(tdb_exists(tdb, key));
-
-               /* Close it, now agent should clear it. */
-               tdb_close(tdb);
-
-               ok1(external_agent_operation(agent, OPEN_WITH_HOOK,
-                                            "run-83-openhook.tdb") == SUCCESS);
-               ok1(external_agent_operation(agent, FETCH, "key") == FAILED);
-               ok1(external_agent_operation(agent, CLOSE, "") == SUCCESS);
-
-               ok1(tap_log_messages == 0);
-       }
-
-       free_external_agent(agent);
-       return exit_status();
-}
-       
diff --git a/ccan/tdb2/test/run-91-get-stats.c b/ccan/tdb2/test/run-91-get-stats.c
deleted file mode 100644 (file)
index f00abb3..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
-                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 11);
-
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               union tdb_attribute *attr;
-               struct tdb_data key = tdb_mkdata("key", 3);
-
-               tdb = tdb_open("run-91-get-stats.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               ok1(tdb);
-               ok1(tdb_store(tdb, key, key, TDB_REPLACE) == 0);
-
-               /* Use malloc so valgrind will catch overruns. */
-               attr = malloc(sizeof *attr);
-               attr->stats.base.attr = TDB_ATTRIBUTE_STATS;
-               attr->stats.size = sizeof(*attr);
-
-               ok1(tdb_get_attribute(tdb, attr) == 0);
-               ok1(attr->stats.size == sizeof(*attr));
-               ok1(attr->stats.allocs > 0);
-               ok1(attr->stats.expands > 0);
-               ok1(attr->stats.locks > 0);
-               free(attr);
-
-               /* Try short one. */
-               attr = malloc(offsetof(struct tdb_attribute_stats, allocs)
-                             + sizeof(attr->stats.allocs));
-               attr->stats.base.attr = TDB_ATTRIBUTE_STATS;
-               attr->stats.size = offsetof(struct tdb_attribute_stats, allocs)
-                       + sizeof(attr->stats.allocs);
-               ok1(tdb_get_attribute(tdb, attr) == 0);
-               ok1(attr->stats.size == sizeof(*attr));
-               ok1(attr->stats.allocs > 0);
-               free(attr);
-               ok1(tap_log_messages == 0);
-
-               tdb_close(tdb);
-
-       }
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-92-get-set-readonly.c b/ccan/tdb2/test/run-92-get-set-readonly.c
deleted file mode 100644 (file)
index c8bbe62..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-int main(int argc, char *argv[])
-{
-       unsigned int i, extra_msgs;
-       struct tdb_context *tdb;
-       struct tdb_data key = tdb_mkdata("key", 3);
-       struct tdb_data data = tdb_mkdata("data", 4);
-       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
-                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 48);
-
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               /* RW -> R0 */
-               tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               ok1(tdb);
-               ok1(!(tdb_get_flags(tdb) & TDB_RDONLY));
-
-               /* TDB1 complains multiple times. */
-               if (flags[i] & TDB_VERSION1) {
-                       extra_msgs = 1;
-               } else {
-                       extra_msgs = 0;
-               }
-
-               ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS);
-
-               tdb_add_flag(tdb, TDB_RDONLY);
-               ok1(tdb_get_flags(tdb) & TDB_RDONLY);
-
-               /* Can't store, append, delete. */
-               ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_ERR_RDONLY);
-               ok1(tap_log_messages == 1);
-               ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY);
-               tap_log_messages -= extra_msgs;
-               ok1(tap_log_messages == 2);
-               ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY);
-               tap_log_messages -= extra_msgs;
-               ok1(tap_log_messages == 3);
-
-               /* Can't start a transaction, or any write lock. */
-               ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY);
-               ok1(tap_log_messages == 4);
-               ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY);
-               tap_log_messages -= extra_msgs;
-               ok1(tap_log_messages == 5);
-               ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY);
-               ok1(tap_log_messages == 6);
-               ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY);
-               ok1(tap_log_messages == 7);
-
-               /* Back to RW. */
-               tdb_remove_flag(tdb, TDB_RDONLY);
-               ok1(!(tdb_get_flags(tdb) & TDB_RDONLY));
-
-               ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_SUCCESS);
-               ok1(tdb_append(tdb, key, data) == TDB_SUCCESS);
-               ok1(tdb_delete(tdb, key) == TDB_SUCCESS);
-
-               ok1(tdb_transaction_start(tdb) == TDB_SUCCESS);
-               ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS);
-               ok1(tdb_transaction_commit(tdb) == TDB_SUCCESS);
-
-               ok1(tdb_chainlock(tdb, key) == TDB_SUCCESS);
-               tdb_chainunlock(tdb, key);
-               ok1(tdb_lockall(tdb) == TDB_SUCCESS);
-               tdb_unlockall(tdb);
-               ok1(tdb_wipe_all(tdb) == TDB_SUCCESS);
-               ok1(tap_log_messages == 7);
-
-               tdb_close(tdb);
-
-               /* R0 -> RW */
-               tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i],
-                              O_RDONLY, 0600, &tap_log_attr);
-               ok1(tdb);
-               ok1(tdb_get_flags(tdb) & TDB_RDONLY);
-
-               /* Can't store, append, delete. */
-               ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_ERR_RDONLY);
-               ok1(tap_log_messages == 8);
-               ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY);
-               tap_log_messages -= extra_msgs;
-               ok1(tap_log_messages == 9);
-               ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY);
-               tap_log_messages -= extra_msgs;
-               ok1(tap_log_messages == 10);
-
-               /* Can't start a transaction, or any write lock. */
-               ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY);
-               ok1(tap_log_messages == 11);
-               ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY);
-               tap_log_messages -= extra_msgs;
-               ok1(tap_log_messages == 12);
-               ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY);
-               ok1(tap_log_messages == 13);
-               ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY);
-               ok1(tap_log_messages == 14);
-
-               /* Can't remove TDB_RDONLY since we opened with O_RDONLY */
-               tdb_remove_flag(tdb, TDB_RDONLY);
-               ok1(tap_log_messages == 15);
-               ok1(tdb_get_flags(tdb) & TDB_RDONLY);
-               tdb_close(tdb);
-
-               ok1(tap_log_messages == 15);
-               tap_log_messages = 0;
-       }
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-93-repack.c b/ccan/tdb2/test/run-93-repack.c
deleted file mode 100644 (file)
index 906a17b..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-#define NUM_TESTS 50000
-
-static bool store_all(struct tdb_context *tdb)
-{
-       unsigned int i;
-       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
-       struct tdb_data dbuf = { (unsigned char *)&i, sizeof(i) };
-
-       for (i = 0; i < NUM_TESTS; i++) {
-               if (tdb_store(tdb, key, dbuf, TDB_INSERT) != TDB_SUCCESS)
-                       return false;
-       }
-       return true;
-}
-
-static int mark_entry(struct tdb_context *tdb,
-                     TDB_DATA key, TDB_DATA data, bool found[])
-{
-       unsigned int num;
-
-       if (key.dsize != sizeof(num))
-               return -1;
-       memcpy(&num, key.dptr, key.dsize);
-       if (num >= NUM_TESTS)
-               return -1;
-       if (found[num])
-               return -1;
-       found[num] = true;
-       return 0;
-}
-
-static bool is_all_set(bool found[], unsigned int num)
-{
-       unsigned int i;
-
-       for (i = 0; i < num; i++)
-               if (!found[i])
-                       return false;
-       return true;
-}
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       bool found[NUM_TESTS];
-       struct tdb_context *tdb;
-       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
-       };
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 6 + 1);
-
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-93-repack.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               ok1(tdb);
-               if (!tdb)
-                       break;
-
-               ok1(store_all(tdb));
-
-               ok1(tdb_repack(tdb) == TDB_SUCCESS);
-               memset(found, 0, sizeof(found));
-               ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
-               ok1(tdb_traverse(tdb, mark_entry, found) == NUM_TESTS);
-               ok1(is_all_set(found, NUM_TESTS));
-               tdb_close(tdb);
-       }
-
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-add-remove-flags.c b/ccan/tdb2/test/run-add-remove-flags.c
deleted file mode 100644 (file)
index 54c4881..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, 
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       plan_tests(173);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-add-remove-flags.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               ok1(tdb);
-               if (!tdb)
-                       continue;
-
-               ok1(tdb_get_flags(tdb) == tdb->flags);
-               tap_log_messages = 0;
-               tdb_add_flag(tdb, TDB_NOLOCK);
-               if (flags[i] & TDB_INTERNAL)
-                       ok1(tap_log_messages == 1);
-               else {
-                       ok1(tap_log_messages == 0);
-                       ok1(tdb_get_flags(tdb) & TDB_NOLOCK);
-               }
-
-               tap_log_messages = 0;
-               tdb_add_flag(tdb, TDB_NOMMAP);
-               if (flags[i] & TDB_INTERNAL)
-                       ok1(tap_log_messages == 1);
-               else {
-                       ok1(tap_log_messages == 0);
-                       ok1(tdb_get_flags(tdb) & TDB_NOMMAP);
-                       ok1(tdb->file->map_ptr == NULL);
-               }
-
-               tap_log_messages = 0;
-               tdb_add_flag(tdb, TDB_NOSYNC);
-               if (flags[i] & TDB_INTERNAL)
-                       ok1(tap_log_messages == 1);
-               else {
-                       ok1(tap_log_messages == 0);
-                       ok1(tdb_get_flags(tdb) & TDB_NOSYNC);
-               }
-
-               ok1(tdb_get_flags(tdb) == tdb->flags);
-
-               tap_log_messages = 0;
-               tdb_remove_flag(tdb, TDB_NOLOCK);
-               if (flags[i] & TDB_INTERNAL)
-                       ok1(tap_log_messages == 1);
-               else {
-                       ok1(tap_log_messages == 0);
-                       ok1(!(tdb_get_flags(tdb) & TDB_NOLOCK));
-               }
-
-               tap_log_messages = 0;
-               tdb_remove_flag(tdb, TDB_NOMMAP);
-               if (flags[i] & TDB_INTERNAL)
-                       ok1(tap_log_messages == 1);
-               else {
-                       ok1(tap_log_messages == 0);
-                       ok1(!(tdb_get_flags(tdb) & TDB_NOMMAP));
-                       ok1(tdb->file->map_ptr != NULL);
-               }
-
-               tap_log_messages = 0;
-               tdb_remove_flag(tdb, TDB_NOSYNC);
-               if (flags[i] & TDB_INTERNAL)
-                       ok1(tap_log_messages == 1);
-               else {
-                       ok1(tap_log_messages == 0);
-                       ok1(!(tdb_get_flags(tdb) & TDB_NOSYNC));
-               }
-
-               tdb_close(tdb);
-       }
-
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-check-callback.c b/ccan/tdb2/test/run-check-callback.c
deleted file mode 100644 (file)
index 91a4d28..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-#define NUM_RECORDS 1000
-
-static bool store_records(struct tdb_context *tdb)
-{
-       int i;
-       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
-       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
-
-       for (i = 0; i < NUM_RECORDS; i++)
-               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
-                       return false;
-       return true;
-}
-
-static enum TDB_ERROR check(struct tdb_data key,
-                           struct tdb_data data,
-                           bool *array)
-{
-       int val;
-
-       if (key.dsize != sizeof(val)) {
-               diag("Wrong key size: %u\n", key.dsize);
-               return TDB_ERR_CORRUPT;
-       }
-
-       if (key.dsize != data.dsize
-           || memcmp(key.dptr, data.dptr, sizeof(val)) != 0) {
-               diag("Key and data differ\n");
-               return TDB_ERR_CORRUPT;
-       }
-
-       memcpy(&val, key.dptr, sizeof(val));
-       if (val >= NUM_RECORDS || val < 0) {
-               diag("check value %i\n", val);
-               return TDB_ERR_CORRUPT;
-       }
-
-       if (array[val]) {
-               diag("Value %i already seen\n", val);
-               return TDB_ERR_CORRUPT;
-       }
-
-       array[val] = true;
-       return TDB_SUCCESS;
-}
-
-int main(int argc, char *argv[])
-{
-       unsigned int i, j;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, 
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 4 + 1);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               bool array[NUM_RECORDS];
-
-               tdb = tdb_open("run-check-callback.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               ok1(tdb);
-               if (!tdb)
-                       continue;
-
-               ok1(store_records(tdb));
-               for (j = 0; j < NUM_RECORDS; j++)
-                       array[j] = false;
-               ok1(tdb_check(tdb, check, array) == TDB_SUCCESS);
-               for (j = 0; j < NUM_RECORDS; j++)
-                       if (!array[j])
-                               break;
-               ok1(j == NUM_RECORDS);
-               tdb_close(tdb);
-       }
-
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-firstkey-nextkey.c b/ccan/tdb2/test/run-firstkey-nextkey.c
deleted file mode 100644 (file)
index 1eb265e..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-#define NUM_RECORDS 1000
-
-static bool store_records(struct tdb_context *tdb)
-{
-       int i;
-       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
-       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
-
-       for (i = 0; i < NUM_RECORDS; i++)
-               if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
-                       return false;
-       return true;
-}
-
-struct trav_data {
-       unsigned int records[NUM_RECORDS];
-       unsigned int calls;
-};
-
-static int trav(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, void *p)
-{
-       struct trav_data *td = p;
-       int val;
-
-       memcpy(&val, dbuf.dptr, dbuf.dsize);
-       td->records[td->calls++] = val;
-       return 0;
-}
-
-/* Since tdb_nextkey frees dptr, we need to clone it. */
-static TDB_DATA dup_key(TDB_DATA key)
-{
-       void *p = malloc(key.dsize);
-       memcpy(p, key.dptr, key.dsize);
-       key.dptr = p;
-       return key;
-}
-
-int main(int argc, char *argv[])
-{
-       unsigned int i, j;
-       int num;
-       struct trav_data td;
-       TDB_DATA k;
-       struct tdb_context *tdb;
-       union tdb_attribute seed_attr;
-       enum TDB_ERROR ecode;
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, 
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       seed_attr.base.attr = TDB_ATTRIBUTE_SEED;
-       seed_attr.base.next = &tap_log_attr;
-       seed_attr.seed.seed = 6334326220117065685ULL;
-
-       plan_tests(sizeof(flags) / sizeof(flags[0])
-                  * (NUM_RECORDS*6 + (NUM_RECORDS-1)*3 + 22) + 1);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-traverse.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600,
-                              flags[i] & TDB_VERSION1 ? NULL : &seed_attr);
-               ok1(tdb);
-               if (!tdb)
-                       continue;
-
-               ok1(tdb_firstkey(tdb, &k) == TDB_ERR_NOEXIST);
-
-               /* One entry... */
-               k.dptr = (unsigned char *)&num;
-               k.dsize = sizeof(num);
-               num = 0;
-               ok1(tdb_store(tdb, k, k, TDB_INSERT) == 0);
-               ok1(tdb_firstkey(tdb, &k) == TDB_SUCCESS);
-               ok1(k.dsize == sizeof(num));
-               ok1(memcmp(k.dptr, &num, sizeof(num)) == 0);
-               ok1(tdb_nextkey(tdb, &k) == TDB_ERR_NOEXIST);
-
-               /* Two entries. */
-               k.dptr = (unsigned char *)&num;
-               k.dsize = sizeof(num);
-               num = 1;
-               ok1(tdb_store(tdb, k, k, TDB_INSERT) == 0);
-               ok1(tdb_firstkey(tdb, &k) == TDB_SUCCESS);
-               ok1(k.dsize == sizeof(num));
-               memcpy(&num, k.dptr, sizeof(num));
-               ok1(num == 0 || num == 1);
-               ok1(tdb_nextkey(tdb, &k) == TDB_SUCCESS);
-               ok1(k.dsize == sizeof(j));
-               memcpy(&j, k.dptr, sizeof(j));
-               ok1(j == 0 || j == 1);
-               ok1(j != num);
-               ok1(tdb_nextkey(tdb, &k) == TDB_ERR_NOEXIST);
-
-               /* Clean up. */
-               k.dptr = (unsigned char *)&num;
-               k.dsize = sizeof(num);
-               num = 0;
-               ok1(tdb_delete(tdb, k) == 0);
-               num = 1;
-               ok1(tdb_delete(tdb, k) == 0);
-
-               /* Now lots of records. */
-               ok1(store_records(tdb));
-               td.calls = 0;
-
-               num = tdb_traverse(tdb, trav, &td);
-               ok1(num == NUM_RECORDS);
-               ok1(td.calls == NUM_RECORDS);
-
-               /* Simple loop should match tdb_traverse */
-               for (j = 0, ecode = tdb_firstkey(tdb, &k); j < td.calls; j++) {
-                       int val;
-
-                       ok1(ecode == TDB_SUCCESS);
-                       ok1(k.dsize == sizeof(val));
-                       memcpy(&val, k.dptr, k.dsize);
-                       ok1(td.records[j] == val);
-                       ecode = tdb_nextkey(tdb, &k);
-               }
-
-               /* But arbitrary orderings should work too. */
-               for (j = td.calls-1; j > 0; j--) {
-                       k.dptr = (unsigned char *)&td.records[j-1];
-                       k.dsize = sizeof(td.records[j-1]);
-                       k = dup_key(k);
-                       ok1(tdb_nextkey(tdb, &k) == TDB_SUCCESS);
-                       ok1(k.dsize == sizeof(td.records[j]));
-                       ok1(memcmp(k.dptr, &td.records[j], k.dsize) == 0);
-                       free(k.dptr);
-               }
-
-               /* Even delete should work. */
-               for (j = 0, ecode = tdb_firstkey(tdb, &k);
-                    ecode != TDB_ERR_NOEXIST;
-                    j++) {
-                       ok1(ecode == TDB_SUCCESS);
-                       ok1(k.dsize == 4);
-                       ok1(tdb_delete(tdb, k) == 0);
-                       ecode = tdb_nextkey(tdb, &k);
-               }
-
-               diag("delete using first/nextkey gave %u of %u records",
-                    j, NUM_RECORDS);
-               ok1(j == NUM_RECORDS);
-               tdb_close(tdb);
-       }
-
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-fork-test.c b/ccan/tdb2/test/run-fork-test.c
deleted file mode 100644 (file)
index 7ff7136..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/* Test forking while holding lock.
- *
- * There are only five ways to do this currently:
- * (1) grab a tdb_chainlock, then fork.
- * (2) grab a tdb_lockall, then fork.
- * (3) grab a tdb_lockall_read, then fork.
- * (4) start a transaction, then fork.
- * (5) fork from inside a tdb_parse() callback.
- *
- * Note that we don't hold a lock across tdb_traverse callbacks, so
- * that doesn't matter.
- */
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include "logging.h"
-
-static enum TDB_ERROR fork_in_parse(TDB_DATA key, TDB_DATA data,
-                                   struct tdb_context *tdb)
-{
-       int status, extra_messages;
-
-       if (tdb_get_flags(tdb) & TDB_VERSION1) {
-               extra_messages = 1;
-       } else {
-               extra_messages = 0;
-       }
-
-       if (fork() == 0) {
-               /* We expect this to fail. */
-               if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
-                       exit(1);
-               tap_log_messages -= extra_messages;
-
-               if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
-                       exit(1);
-
-               tap_log_messages -= extra_messages;
-               if (tap_log_messages != 2)
-                       exit(2);
-
-               tdb_close(tdb);
-               if (tap_log_messages != 2)
-                       exit(3);
-               exit(0);
-       }
-       wait(&status);
-       ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
-       return TDB_SUCCESS;
-}
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
-                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-       struct tdb_data key = tdb_mkdata("key", 3);
-       struct tdb_data data = tdb_mkdata("data", 4);
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 14);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               int status, extra_messages;
-
-               if (flags[i] & TDB_VERSION1) {
-                       extra_messages = 1;
-               } else {
-                       extra_messages = 0;
-               }
-
-               tap_log_messages = 0;
-
-               tdb = tdb_open("run-fork-test.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               if (!ok1(tdb))
-                       continue;
-
-               /* Put a record in here. */
-               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_SUCCESS);
-
-               ok1(tdb_chainlock(tdb, key) == TDB_SUCCESS);
-               if (fork() == 0) {
-                       /* We expect this to fail. */
-                       if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
-                               return 1;
-                       tap_log_messages -= extra_messages;
-
-                       if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
-                               return 1;
-                       tap_log_messages -= extra_messages;
-
-                       if (tap_log_messages != 2)
-                               return 2;
-
-                       tdb_chainunlock(tdb, key);
-                       if (tap_log_messages != 3)
-                               return 3;
-                       tdb_close(tdb);
-                       if (tap_log_messages != 3)
-                               return 4;
-                       return 0;
-               }
-               wait(&status);
-               ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
-               tdb_chainunlock(tdb, key);
-
-               ok1(tdb_lockall(tdb) == TDB_SUCCESS);
-               if (fork() == 0) {
-                       /* We expect this to fail. */
-                       if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
-                               return 1;
-                       tap_log_messages -= extra_messages;
-
-                       if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
-                               return 1;
-                       tap_log_messages -= extra_messages;
-
-                       if (tap_log_messages != 2)
-                               return 2;
-
-                       tdb_unlockall(tdb);
-                       if (tap_log_messages != 2)
-                               return 3;
-                       tdb_close(tdb);
-                       if (tap_log_messages != 2)
-                               return 4;
-                       return 0;
-               }
-               wait(&status);
-               ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
-               tdb_unlockall(tdb);
-
-               ok1(tdb_lockall_read(tdb) == TDB_SUCCESS);
-               if (fork() == 0) {
-                       /* We expect this to fail. */
-                       /* This would always fail anyway... */
-                       if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
-                               return 1;
-                       tap_log_messages -= extra_messages;
-
-                       if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
-                               return 1;
-                       tap_log_messages -= extra_messages;
-
-                       if (tap_log_messages != 2)
-                               return 2;
-
-                       tdb_unlockall_read(tdb);
-                       if (tap_log_messages != 2)
-                               return 3;
-                       tdb_close(tdb);
-                       if (tap_log_messages != 2)
-                               return 4;
-                       return 0;
-               }
-               wait(&status);
-               ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
-               tdb_unlockall_read(tdb);
-
-               ok1(tdb_transaction_start(tdb) == TDB_SUCCESS);
-               /* If transactions is empty, noop "commit" succeeds. */
-               ok1(tdb_delete(tdb, key) == TDB_SUCCESS);
-               if (fork() == 0) {
-                       /* We expect this to fail. */
-                       if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
-                               return 1;
-                       tap_log_messages -= extra_messages;
-
-                       if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
-                               return 1;
-                       tap_log_messages -= extra_messages;
-
-                       if (tap_log_messages != 2)
-                               return 2;
-
-                       if (tdb_transaction_commit(tdb) != TDB_ERR_LOCK)
-                               return 3;
-                       tap_log_messages -= extra_messages;
-
-                       tdb_close(tdb);
-                       if (tap_log_messages < 3)
-                               return 4;
-                       return 0;
-               }
-               wait(&status);
-               ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
-               tdb_transaction_cancel(tdb);
-
-               ok1(tdb_parse_record(tdb, key, fork_in_parse, tdb)
-                   == TDB_SUCCESS);
-               tdb_close(tdb);
-               ok1(tap_log_messages == 0);
-       }
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-locktimeout.c b/ccan/tdb2/test/run-locktimeout.c
deleted file mode 100644 (file)
index 18b6e1a..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-#include "external-agent.h"
-
-#undef alarm
-#define alarm fast_alarm
-
-/* Speed things up by doing things in milliseconds. */
-static unsigned int fast_alarm(unsigned int milli_seconds)
-{
-       struct itimerval it;
-
-       it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
-       it.it_value.tv_sec = milli_seconds / 1000;
-       it.it_value.tv_usec = milli_seconds * 1000;
-       setitimer(ITIMER_REAL, &it, NULL);
-       return 0;
-}
-
-#define CatchSignal(sig, handler) signal((sig), (handler))
-
-static void do_nothing(int signum)
-{
-}
-
-/* This example code is taken from SAMBA, so try not to change it. */
-static struct flock flock_struct;
-
-/* Return a value which is none of v1, v2 or v3. */
-static inline short int invalid_value(short int v1, short int v2, short int v3)
-{
-       short int try = (v1+v2+v3)^((v1+v2+v3) << 16);
-       while (try == v1 || try == v2 || try == v3)
-               try++;
-       return try;
-}
-
-/* We invalidate in as many ways as we can, so the OS rejects it */
-static void invalidate_flock_struct(int signum)
-{
-       flock_struct.l_type = invalid_value(F_RDLCK, F_WRLCK, F_UNLCK);
-       flock_struct.l_whence = invalid_value(SEEK_SET, SEEK_CUR, SEEK_END);
-       flock_struct.l_start = -1;
-       /* A large negative. */
-       flock_struct.l_len = (((off_t)1 << (sizeof(off_t)*CHAR_BIT - 1)) + 1);
-}
-
-static int timeout_lock(int fd, int rw, off_t off, off_t len, bool waitflag,
-                       void *_timeout)
-{
-       int ret, saved_errno = errno;
-       unsigned int timeout = *(unsigned int *)_timeout;
-
-       flock_struct.l_type = rw;
-       flock_struct.l_whence = SEEK_SET;
-       flock_struct.l_start = off;
-       flock_struct.l_len = len;
-
-       CatchSignal(SIGALRM, invalidate_flock_struct);
-       alarm(timeout);
-
-       for (;;) {
-               if (waitflag)
-                       ret = fcntl(fd, F_SETLKW, &flock_struct);
-               else
-                       ret = fcntl(fd, F_SETLK, &flock_struct);
-
-               if (ret == 0)
-                       break;
-
-               /* Not signalled?  Something else went wrong. */
-               if (flock_struct.l_len == len) {
-                       if (errno == EAGAIN || errno == EINTR)
-                               continue;
-                       saved_errno = errno;
-                       break;
-               } else {
-                       saved_errno = EINTR;
-                       break;
-               }
-       }
-
-       alarm(0);
-       errno = saved_errno;
-       return ret;
-}
-
-static int tdb_chainlock_with_timeout_internal(struct tdb_context *tdb,
-                                              TDB_DATA key,
-                                              unsigned int timeout,
-                                              int rw_type)
-{
-       union tdb_attribute locking;
-       enum TDB_ERROR ecode;
-
-       if (timeout) {
-               locking.base.attr = TDB_ATTRIBUTE_FLOCK;
-               ecode = tdb_get_attribute(tdb, &locking);
-               if (ecode != TDB_SUCCESS)
-                       return ecode;
-
-               /* Replace locking function with our own. */
-               locking.flock.data = &timeout;
-               locking.flock.lock = timeout_lock;
-
-               ecode = tdb_set_attribute(tdb, &locking);
-               if (ecode != TDB_SUCCESS)
-                       return ecode;
-       }
-       if (rw_type == F_RDLCK)
-               ecode = tdb_chainlock_read(tdb, key);
-       else
-               ecode = tdb_chainlock(tdb, key);
-
-       if (timeout) {
-               tdb_unset_attribute(tdb, TDB_ATTRIBUTE_FLOCK);
-       }
-       return ecode;
-}
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       TDB_DATA key = tdb_mkdata("hello", 5);
-       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
-                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-       struct agent *agent;
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 15);
-
-       agent = prepare_external_agent();
-
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               enum TDB_ERROR ecode;
-               tdb = tdb_open("run-locktimeout.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               if (!ok1(tdb))
-                       break;
-
-               /* Simple cases: should succeed. */ 
-               ecode = tdb_chainlock_with_timeout_internal(tdb, key, 20,
-                                                           F_RDLCK);
-               ok1(ecode == TDB_SUCCESS);
-               ok1(tap_log_messages == 0);
-
-               tdb_chainunlock_read(tdb, key);
-               ok1(tap_log_messages == 0);
-
-               ecode = tdb_chainlock_with_timeout_internal(tdb, key, 20,
-                                                           F_WRLCK);
-               ok1(ecode == TDB_SUCCESS);
-               ok1(tap_log_messages == 0);
-
-               tdb_chainunlock(tdb, key);
-               ok1(tap_log_messages == 0);
-
-               /* OK, get agent to start transaction, then we should time out. */
-               ok1(external_agent_operation(agent, OPEN, "run-locktimeout.tdb")
-                   == SUCCESS);
-               ok1(external_agent_operation(agent, TRANSACTION_START, "") 
-                   == SUCCESS);
-               ecode = tdb_chainlock_with_timeout_internal(tdb, key, 20,
-                                                           F_WRLCK);
-               ok1(ecode == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-
-               /* Even if we get a different signal, should be fine. */
-               CatchSignal(SIGUSR1, do_nothing);
-               external_agent_operation(agent, SEND_SIGNAL, "");
-               ecode = tdb_chainlock_with_timeout_internal(tdb, key, 20,
-                                                           F_WRLCK);
-               ok1(ecode == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 0);
-
-               ok1(external_agent_operation(agent, TRANSACTION_COMMIT, "")
-                   == SUCCESS);
-               ok1(external_agent_operation(agent, CLOSE, "")
-                   == SUCCESS);
-               tdb_close(tdb);
-       }
-       free_external_agent(agent);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-missing-entries.c b/ccan/tdb2/test/run-missing-entries.c
deleted file mode 100644 (file)
index 22d6ba4..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "tdb2-source.h"
-/* Another test revealed that we lost an entry.  This reproduces it. */
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-#define NUM_RECORDS 1189
-
-/* We use the same seed which we saw this failure on. */
-static uint64_t failhash(const void *key, size_t len, uint64_t seed, void *p)
-{
-       seed = 699537674708983027ULL;
-       return hash64_stable((const unsigned char *)key, len, seed);
-}
-
-int main(int argc, char *argv[])
-{
-       int i;
-       struct tdb_context *tdb;
-       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
-       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
-       union tdb_attribute hattr = { .hash = { .base = { TDB_ATTRIBUTE_HASH },
-                                               .fn = failhash } };
-
-       hattr.base.next = &tap_log_attr;
-       plan_tests(1 + 2 * NUM_RECORDS + 1);
-
-       tdb = tdb_open("run-missing-entries.tdb", TDB_INTERNAL,
-                      O_RDWR|O_CREAT|O_TRUNC, 0600, &hattr);
-       ok1(tdb);
-       if (tdb) {
-               for (i = 0; i < NUM_RECORDS; i++) {
-                       ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
-                       ok1(tdb_check(tdb, NULL, NULL) == 0);
-               }
-               tdb_close(tdb);
-       }
-
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-open-multiple-times.c b/ccan/tdb2/test/run-open-multiple-times.c
deleted file mode 100644 (file)
index 4d60b20..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-int main(int argc, char *argv[])
-{
-       unsigned int i, extra_messages;
-       struct tdb_context *tdb, *tdb2;
-       struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
-       struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
-       struct tdb_data d = { NULL, 0 }; /* Bogus GCC warning */
-       int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
-                       TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 28);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-open-multiple-times.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               ok1(tdb);
-               if (!tdb)
-                       continue;
-
-               if (flags[i] & TDB_VERSION1) {
-                       extra_messages = 1;
-               } else {
-                       extra_messages = 0;
-               }
-               tdb2 = tdb_open("run-open-multiple-times.tdb", flags[i],
-                               O_RDWR|O_CREAT, 0600, &tap_log_attr);
-               ok1(tdb_check(tdb, NULL, NULL) == 0);
-               ok1(tdb_check(tdb2, NULL, NULL) == 0);
-
-               /* Store in one, fetch in the other. */
-               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
-               ok1(tdb_fetch(tdb2, key, &d) == TDB_SUCCESS);
-               ok1(tdb_deq(d, data));
-               free(d.dptr);
-
-               /* Vice versa, with delete. */
-               ok1(tdb_delete(tdb2, key) == 0);
-               ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_NOEXIST);
-
-               /* OK, now close first one, check second still good. */
-               ok1(tdb_close(tdb) == 0);
-
-               ok1(tdb_store(tdb2, key, data, TDB_REPLACE) == 0);
-               ok1(tdb_fetch(tdb2, key, &d) == TDB_SUCCESS);
-               ok1(tdb_deq(d, data));
-               free(d.dptr);
-
-               /* Reopen */
-               tdb = tdb_open("run-open-multiple-times.tdb", flags[i],
-                              O_RDWR|O_CREAT, 0600, &tap_log_attr);
-               ok1(tdb);
-
-               ok1(tdb_transaction_start(tdb2) == 0);
-
-               /* Anything in the other one should fail. */
-               ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK);
-               tap_log_messages -= extra_messages;
-               ok1(tap_log_messages == 1);
-               ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK);
-               tap_log_messages -= extra_messages;
-               ok1(tap_log_messages == 2);
-               ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK);
-               ok1(tap_log_messages == 3);
-               ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK);
-               tap_log_messages -= extra_messages;
-               ok1(tap_log_messages == 4);
-
-               /* Transaciton should work as normal. */
-               ok1(tdb_store(tdb2, key, data, TDB_REPLACE) == TDB_SUCCESS);
-
-               /* Now... try closing with locks held. */
-               ok1(tdb_close(tdb2) == 0);
-
-               ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
-               ok1(tdb_deq(d, data));
-               free(d.dptr);
-               ok1(tdb_close(tdb) == 0);
-               ok1(tap_log_messages == 4);
-               tap_log_messages = 0;
-       }
-
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-record-expand.c b/ccan/tdb2/test/run-record-expand.c
deleted file mode 100644 (file)
index 2cde873..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-#define MAX_SIZE 10000
-#define SIZE_STEP 131
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, 
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-       struct tdb_data key = tdb_mkdata("key", 3);
-       struct tdb_data data;
-
-       data.dptr = malloc(MAX_SIZE);
-       memset(data.dptr, 0x24, MAX_SIZE);
-
-       plan_tests(sizeof(flags) / sizeof(flags[0])
-                  * (3 + (1 + (MAX_SIZE/SIZE_STEP)) * 2) + 1);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-record-expand.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               ok1(tdb);
-               if (!tdb)
-                       continue;
-
-               data.dsize = 0;
-               ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-               ok1(tdb_check(tdb, NULL, NULL) == 0);
-               for (data.dsize = 0;
-                    data.dsize < MAX_SIZE;
-                    data.dsize += SIZE_STEP) {
-                       memset(data.dptr, data.dsize, data.dsize);
-                       ok1(tdb_store(tdb, key, data, TDB_MODIFY) == 0);
-                       ok1(tdb_check(tdb, NULL, NULL) == 0);
-               }
-               tdb_close(tdb);
-       }
-       ok1(tap_log_messages == 0);
-       free(data.dptr);
-
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-simple-delete.c b/ccan/tdb2/test/run-simple-delete.c
deleted file mode 100644 (file)
index 84acd19..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-int main(int argc, char *argv[])
-{
-       unsigned int i;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, 
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-       struct tdb_data key = tdb_mkdata("key", 3);
-       struct tdb_data data = tdb_mkdata("data", 4);
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * 7 + 1);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-simple-delete.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               ok1(tdb);
-               if (tdb) {
-                       /* Delete should fail. */
-                       ok1(tdb_delete(tdb, key) == TDB_ERR_NOEXIST);
-                       ok1(tdb_check(tdb, NULL, NULL) == 0);
-                       /* Insert should succeed. */
-                       ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
-                       ok1(tdb_check(tdb, NULL, NULL) == 0);
-                       /* Delete should now work. */
-                       ok1(tdb_delete(tdb, key) == 0);
-                       ok1(tdb_check(tdb, NULL, NULL) == 0);
-                       tdb_close(tdb);
-               }
-       }
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
diff --git a/ccan/tdb2/test/run-summary.c b/ccan/tdb2/test/run-summary.c
deleted file mode 100644 (file)
index 73e180d..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#include "tdb2-source.h"
-#include <ccan/tap/tap.h>
-#include "logging.h"
-
-int main(int argc, char *argv[])
-{
-       unsigned int i, j;
-       struct tdb_context *tdb;
-       int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
-                       TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
-                       TDB_NOMMAP|TDB_CONVERT,
-                       TDB_INTERNAL|TDB_VERSION1, TDB_VERSION1,
-                       TDB_NOMMAP|TDB_VERSION1,
-                       TDB_INTERNAL|TDB_CONVERT|TDB_VERSION1,
-                       TDB_CONVERT|TDB_VERSION1,
-                       TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };
-       struct tdb_data key = { (unsigned char *)&j, sizeof(j) };
-       struct tdb_data data = { (unsigned char *)&j, sizeof(j) };
-       char *summary;
-
-       plan_tests(sizeof(flags) / sizeof(flags[0]) * (1 + 2 * 5) + 1);
-       for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
-               tdb = tdb_open("run-summary.tdb", flags[i],
-                              O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
-               ok1(tdb);
-               if (!tdb)
-                       continue;
-
-               /* Put some stuff in there. */
-               for (j = 0; j < 500; j++) {
-                       /* Make sure padding varies to we get some graphs! */
-                       data.dsize = j % (sizeof(j) + 1);
-                       if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
-                               fail("Storing in tdb");
-               }
-
-               for (j = 0;
-                    j <= TDB_SUMMARY_HISTOGRAMS;
-                    j += TDB_SUMMARY_HISTOGRAMS) {
-                       ok1(tdb_summary(tdb, j, &summary) == TDB_SUCCESS);
-                       ok1(strstr(summary, "Number of records: 500\n"));
-                       ok1(strstr(summary, "Smallest/average/largest keys: 4/4/4\n"));
-                       ok1(strstr(summary, "Smallest/average/largest data: 0/2/4\n"));
-                       if (!(flags[i] & TDB_VERSION1)
-                           && j == TDB_SUMMARY_HISTOGRAMS) {
-                               ok1(strstr(summary, "|")
-                                   && strstr(summary, "*"));
-                       } else {
-                               ok1(!strstr(summary, "|")
-                                   && !strstr(summary, "*"));
-                       }
-                       free(summary);
-               }
-               tdb_close(tdb);
-       }
-
-       ok1(tap_log_messages == 0);
-       return exit_status();
-}
-
-