run-delete.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include <ccan/tdb2/tdb.c>
  2. #include <ccan/tdb2/free.c>
  3. #include <ccan/tdb2/lock.c>
  4. #include <ccan/tdb2/io.c>
  5. #include <ccan/tdb2/check.c>
  6. #include <ccan/tap/tap.h>
  7. #include "logging.h"
  8. /* We rig the hash so adjacent-numbered records always clash. */
  9. static uint64_t clash(const void *key, size_t len, uint64_t seed, void *priv)
  10. {
  11. return *(unsigned int *)key / 2;
  12. }
  13. static void test_val(struct tdb_context *tdb, unsigned int val)
  14. {
  15. unsigned int v;
  16. struct tdb_data key = { (unsigned char *)&v, sizeof(v) };
  17. struct tdb_data data = { (unsigned char *)&v, sizeof(v) };
  18. /* Insert an entry, then delete it. */
  19. v = val;
  20. /* Delete should fail. */
  21. ok1(tdb_delete(tdb, key) == -1);
  22. ok1(tdb_error(tdb) == TDB_ERR_NOEXIST);
  23. ok1(tdb_check(tdb, NULL, NULL) == 0);
  24. /* Insert should succeed. */
  25. ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
  26. ok1(tdb_check(tdb, NULL, NULL) == 0);
  27. /* Delete should succeed. */
  28. ok1(tdb_delete(tdb, key) == 0);
  29. ok1(tdb_check(tdb, NULL, NULL) == 0);
  30. /* Re-add it, then add collision. */
  31. ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
  32. v = val + 1;
  33. ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
  34. ok1(tdb_check(tdb, NULL, NULL) == 0);
  35. /* Can find both? */
  36. ok1(tdb_fetch(tdb, key).dsize == data.dsize);
  37. v = val;
  38. ok1(tdb_fetch(tdb, key).dsize == data.dsize);
  39. /* Delete second one. */
  40. v = val + 1;
  41. ok1(tdb_delete(tdb, key) == 0);
  42. ok1(tdb_check(tdb, NULL, NULL) == 0);
  43. /* Re-add */
  44. ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
  45. ok1(tdb_check(tdb, NULL, NULL) == 0);
  46. /* Now, try deleting first one. */
  47. v = val;
  48. ok1(tdb_delete(tdb, key) == 0);
  49. ok1(tdb_check(tdb, NULL, NULL) == 0);
  50. /* Can still find second? */
  51. v = val + 1;
  52. ok1(tdb_fetch(tdb, key).dsize == data.dsize);
  53. /* Delete that, so we are empty. */
  54. ok1(tdb_delete(tdb, key) == 0);
  55. ok1(tdb_check(tdb, NULL, NULL) == 0);
  56. }
  57. int main(int argc, char *argv[])
  58. {
  59. unsigned int i;
  60. struct tdb_context *tdb;
  61. union tdb_attribute hattr = { .hash = { .base = { TDB_ATTRIBUTE_HASH },
  62. .hash_fn = clash } };
  63. int flags[] = { TDB_INTERNAL, TDB_DEFAULT,
  64. TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT };
  65. hattr.base.next = &tap_log_attr;
  66. plan_tests(sizeof(flags) / sizeof(flags[0]) * 44 + 1);
  67. for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
  68. tdb = tdb_open("run-delete.tdb", flags[i],
  69. O_RDWR|O_CREAT|O_TRUNC, 0600, &hattr);
  70. ok1(tdb);
  71. if (!tdb)
  72. continue;
  73. /* Check start of hash table. */
  74. test_val(tdb, 0);
  75. /* Check end of hash table (will wrap around!). */
  76. test_val(tdb, ((1 << tdb->header.v.hash_bits) - 1) * 2);
  77. ok1(!tdb_has_locks(tdb));
  78. tdb_close(tdb);
  79. }
  80. ok1(tap_log_messages == 0);
  81. return exit_status();
  82. }