]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb/test/run-corrupt.c
tdb: add test for tdb_summary
[ccan] / ccan / tdb / test / run-corrupt.c
index 6d190c2aff976547272dd1f6326155c4f6c90a5b..6f753ea6d46c81c9dbd3f9e388c1f3078c98e30e 100644 (file)
@@ -1,17 +1,19 @@
 #define _XOPEN_SOURCE 500
-#include "tdb/tdb.h"
-#include "tdb/io.c"
-#include "tdb/tdb.c"
-#include "tdb/lock.c"
-#include "tdb/freelist.c"
-#include "tdb/traverse.c"
-#include "tdb/transaction.c"
-#include "tdb/error.c"
-#include "tdb/open.c"
-#include "tdb/check.c"
-#include "tap/tap.h"
+#include <ccan/tdb/tdb.h>
+#include <ccan/tdb/io.c>
+#include <ccan/tdb/tdb.c>
+#include <ccan/tdb/lock.c>
+#include <ccan/tdb/freelist.c>
+#include <ccan/tdb/traverse.c>
+#include <ccan/tdb/transaction.c>
+#include <ccan/tdb/error.c>
+#include <ccan/tdb/open.c>
+#include <ccan/tdb/check.c>
+#include <ccan/tdb/hash.c>
+#include <ccan/tap/tap.h>
 #include <stdlib.h>
 #include <err.h>
+#include "logging.h"
 
 static int check(TDB_DATA key, TDB_DATA data, void *private)
 {
@@ -32,18 +34,28 @@ static int check(TDB_DATA key, TDB_DATA data, void *private)
        return 0;
 }
 
-int main(int argc, char *argv[])
+static void tdb_flip_bit(struct tdb_context *tdb, unsigned int bit)
+{
+       unsigned int off = bit / CHAR_BIT;
+       unsigned char mask = (1 << (bit % CHAR_BIT));
+
+       if (tdb->map_ptr)
+               ((unsigned char *)tdb->map_ptr)[off] ^= mask;
+       else {
+               unsigned char c;
+               if (pread(tdb->fd, &c, 1, off) != 1)
+                       err(1, "pread");
+               c ^= mask;
+               if (pwrite(tdb->fd, &c, 1, off) != 1)
+                       err(1, "pwrite");
+       }
+}
+
+static void check_test(struct tdb_context *tdb)
 {
-       struct tdb_context *tdb;
        TDB_DATA key, data;
        unsigned int i, verifiable, corrupt, sizes[2], dsize, ksize;
 
-       plan_tests(2);
-       tdb = tdb_open("/tmp/test6.tdb", 2, TDB_CLEAR_IF_FIRST,
-                      O_CREAT|O_TRUNC|O_RDWR, 0600);
-
-       if (!tdb)
-               abort();
        ok1(tdb_check(tdb, NULL, NULL) == 0);
        
        key.dptr = (void *)"hello";
@@ -64,29 +76,53 @@ int main(int argc, char *argv[])
        /* This is how many bytes we expect to be verifiable. */
        /* From the file header. */
        verifiable = strlen(TDB_MAGIC_FOOD) + 1
-               + 2 * sizeof(uint32_t) + 2 * sizeof(tdb_off_t);
+               + 2 * sizeof(uint32_t) + 2 * sizeof(tdb_off_t)
+               + 2 * sizeof(uint32_t);
        /* From the free list chain and hash chains. */
        verifiable += 3 * sizeof(tdb_off_t);
        /* From the record headers & tailer */
-       verifiable += 5 * (sizeof(struct list_struct) + sizeof(uint32_t));
+       verifiable += 5 * (sizeof(struct tdb_record) + sizeof(uint32_t));
        /* The free block: we ignore datalen, keylen, full_hash. */
-       verifiable += sizeof(struct list_struct) - 3*sizeof(uint32_t) +
+       verifiable += sizeof(struct tdb_record) - 3*sizeof(uint32_t) +
                sizeof(uint32_t);
        /* Our check function verifies the key and data. */
        verifiable += ksize + dsize;
 
        /* Flip one bit at a time, make sure it detects verifiable bytes. */
        for (i = 0, corrupt = 0; i < tdb->map_size * CHAR_BIT; i++) {
-               bit_flip(tdb->map_ptr, i);
+               tdb_flip_bit(tdb, i);
                memset(sizes, 0, sizeof(sizes));
                if (tdb_check(tdb, check, sizes) != 0)
                        corrupt++;
                else if (sizes[0] != ksize || sizes[1] != dsize)
                        corrupt++;
-               bit_flip(tdb->map_ptr, i);
+               tdb_flip_bit(tdb, i);
        }
        ok(corrupt == verifiable * CHAR_BIT, "corrupt %u should be %u",
           corrupt, verifiable * CHAR_BIT);
+}
+
+int main(int argc, char *argv[])
+{
+       struct tdb_context *tdb;
+
+       plan_tests(4);
+       /* This should use mmap. */
+       tdb = tdb_open_ex("run-corrupt.tdb", 2, TDB_CLEAR_IF_FIRST,
+                         O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL);
+
+       if (!tdb)
+               abort();
+       check_test(tdb);
+       tdb_close(tdb);
+
+       /* This should not. */
+       tdb = tdb_open_ex("run-corrupt.tdb", 2, TDB_CLEAR_IF_FIRST|TDB_NOMMAP,
+                         O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL);
+
+       if (!tdb)
+               abort();
+       check_test(tdb);
        tdb_close(tdb);
 
        return exit_status();