Browse Source

tdb2: fix leak in tests.

Rusty Russell 15 years ago
parent
commit
c56e2b1b5e

+ 7 - 0
ccan/tdb2/test/external-agent.c

@@ -187,3 +187,10 @@ const char *operation_name(enum operation op)
 	}
 	}
 	return "**INVALID**";
 	return "**INVALID**";
 }
 }
+
+void free_external_agent(struct agent *agent)
+{
+	close(agent->cmdfd);
+	close(agent->responsefd);
+	free(agent);
+}

+ 1 - 0
ccan/tdb2/test/external-agent.h

@@ -37,4 +37,5 @@ enum agent_return external_agent_operation(struct agent *handle,
 const char *agent_return_name(enum agent_return ret);
 const char *agent_return_name(enum agent_return ret);
 const char *operation_name(enum operation op);
 const char *operation_name(enum operation op);
 
 
+void free_external_agent(struct agent *agent);
 #endif /* TDB2_TEST_EXTERNAL_AGENT_H */
 #endif /* TDB2_TEST_EXTERNAL_AGENT_H */

+ 14 - 0
ccan/tdb2/test/layout.c

@@ -320,3 +320,17 @@ struct tdb_context *tdb_layout_get(struct tdb_layout *layout)
 
 
 	return tdb;
 	return tdb;
 }
 }
+
+void tdb_layout_free(struct tdb_layout *layout)
+{
+	unsigned int i;
+
+	for (i = 0; i < layout->num_elems; i++) {
+		if (layout->elem[i].base.type == DATA) {
+			free(layout->elem[i].used.key.dptr);
+			free(layout->elem[i].used.data.dptr);
+		}
+	}
+	free(layout->elem);
+	free(layout);
+}

+ 1 - 0
ccan/tdb2/test/layout.h

@@ -16,6 +16,7 @@ void tdb_layout_add_hashtable(struct tdb_layout *layout,
 			      tdb_len_t extra);
 			      tdb_len_t extra);
 #endif
 #endif
 struct tdb_context *tdb_layout_get(struct tdb_layout *layout);
 struct tdb_context *tdb_layout_get(struct tdb_layout *layout);
+void tdb_layout_free(struct tdb_layout *layout);
 
 
 enum layout_type {
 enum layout_type {
 	FREETABLE, FREE, DATA, HASHTABLE,
 	FREETABLE, FREE, DATA, HASHTABLE,

+ 5 - 0
ccan/tdb2/test/run-03-coalesce.c

@@ -54,6 +54,7 @@ int main(int argc, char *argv[])
 	ok1(free_record_length(tdb, layout->elem[1].base.off) == len);
 	ok1(free_record_length(tdb, layout->elem[1].base.off) == len);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	tdb_close(tdb);
 	tdb_close(tdb);
+	tdb_layout_free(layout);
 
 
 	/* No coalescing can be done due to used record */
 	/* No coalescing can be done due to used record */
 	layout = new_tdb_layout(NULL);
 	layout = new_tdb_layout(NULL);
@@ -73,6 +74,7 @@ int main(int argc, char *argv[])
 	ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
 	ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	tdb_close(tdb);
 	tdb_close(tdb);
+	tdb_layout_free(layout);
 
 
 	/* Coalescing can be done due to two free records, then EOF */
 	/* Coalescing can be done due to two free records, then EOF */
 	layout = new_tdb_layout(NULL);
 	layout = new_tdb_layout(NULL);
@@ -94,6 +96,7 @@ int main(int argc, char *argv[])
 	    == 1024 + sizeof(struct tdb_used_record) + 2048);
 	    == 1024 + sizeof(struct tdb_used_record) + 2048);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	tdb_close(tdb);
 	tdb_close(tdb);
+	tdb_layout_free(layout);
 
 
 	/* Coalescing can be done due to two free records, then data */
 	/* Coalescing can be done due to two free records, then data */
 	layout = new_tdb_layout(NULL);
 	layout = new_tdb_layout(NULL);
@@ -116,6 +119,7 @@ int main(int argc, char *argv[])
 	    == 1024 + sizeof(struct tdb_used_record) + 512);
 	    == 1024 + sizeof(struct tdb_used_record) + 512);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	tdb_close(tdb);
 	tdb_close(tdb);
+	tdb_layout_free(layout);
 
 
 	/* Coalescing can be done due to three free records, then EOF */
 	/* Coalescing can be done due to three free records, then EOF */
 	layout = new_tdb_layout(NULL);
 	layout = new_tdb_layout(NULL);
@@ -140,6 +144,7 @@ int main(int argc, char *argv[])
 	    + sizeof(struct tdb_used_record) + 256);
 	    + sizeof(struct tdb_used_record) + 256);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	tdb_close(tdb);
 	tdb_close(tdb);
+	tdb_layout_free(layout);
 
 
 	ok1(tap_log_messages == 0);
 	ok1(tap_log_messages == 0);
 	return exit_status();
 	return exit_status();

+ 1 - 0
ccan/tdb2/test/run-11-simple-fetch.c

@@ -37,6 +37,7 @@ int main(int argc, char *argv[])
 			/* Fetch should now work. */
 			/* Fetch should now work. */
 			d = tdb_fetch(tdb, key);
 			d = tdb_fetch(tdb, key);
 			ok1(data_equal(d, data));
 			ok1(data_equal(d, data));
+			free(d.dptr);
 			ok1(tdb_check(tdb, NULL, NULL) == 0);
 			ok1(tdb_check(tdb, NULL, NULL) == 0);
 			tdb_close(tdb);
 			tdb_close(tdb);
 		}
 		}

+ 4 - 1
ccan/tdb2/test/run-12-store.c

@@ -50,8 +50,11 @@ int main(int argc, char *argv[])
 		/* We seemed to lose some keys.
 		/* We seemed to lose some keys.
 		 * Insert and check they're in there! */
 		 * Insert and check they're in there! */
 		for (j = 0; j < 500; j++) {
 		for (j = 0; j < 500; j++) {
+			struct tdb_data d;
 			ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
 			ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
-			ok1(equal(tdb_fetch(tdb, key), data));
+			d = tdb_fetch(tdb, key);
+			ok1(equal(d, data));
+			free(d.dptr);
 		}
 		}
 		tdb_close(tdb);
 		tdb_close(tdb);
 	}
 	}

+ 31 - 11
ccan/tdb2/test/run-13-delete.c

@@ -26,13 +26,17 @@ static bool store_records(struct tdb_context *tdb)
 {
 {
 	int i;
 	int i;
 	struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
 	struct tdb_data key = { (unsigned char *)&i, sizeof(i) };
-	struct tdb_data data = { (unsigned char *)&i, sizeof(i) };
+	struct tdb_data d, data = { (unsigned char *)&i, sizeof(i) };
 
 
 	for (i = 0; i < 1000; i++) {
 	for (i = 0; i < 1000; i++) {
 		if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
 		if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
 			return false;
 			return false;
-		if (tdb_fetch(tdb, key).dsize != data.dsize)
+		d = tdb_fetch(tdb, key);
+		if (d.dsize != data.dsize)
 			return false;
 			return false;
+		if (memcmp(d.dptr, data.dptr, d.dsize) != 0)
+			return false;
+		free(d.dptr);
 	}
 	}
 	return true;
 	return true;
 }
 }
@@ -41,7 +45,7 @@ static void test_val(struct tdb_context *tdb, uint64_t val)
 {
 {
 	uint64_t v;
 	uint64_t v;
 	struct tdb_data key = { (unsigned char *)&v, sizeof(v) };
 	struct tdb_data key = { (unsigned char *)&v, sizeof(v) };
-	struct tdb_data data = { (unsigned char *)&v, sizeof(v) };
+	struct tdb_data d, data = { (unsigned char *)&v, sizeof(v) };
 
 
 	/* Insert an entry, then delete it. */
 	/* Insert an entry, then delete it. */
 	v = val;
 	v = val;
@@ -65,9 +69,13 @@ static void test_val(struct tdb_context *tdb, uint64_t val)
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 
 
 	/* Can find both? */
 	/* Can find both? */
-	ok1(tdb_fetch(tdb, key).dsize == data.dsize);
+	d = tdb_fetch(tdb, key);
+	ok1(d.dsize == data.dsize);
+	free(d.dptr);
 	v = val;
 	v = val;
-	ok1(tdb_fetch(tdb, key).dsize == data.dsize);
+	d = tdb_fetch(tdb, key);
+	ok1(d.dsize == data.dsize);
+	free(d.dptr);
 
 
 	/* Delete second one. */
 	/* Delete second one. */
 	v = val + 1;
 	v = val + 1;
@@ -85,7 +93,9 @@ static void test_val(struct tdb_context *tdb, uint64_t val)
 
 
 	/* Can still find second? */
 	/* Can still find second? */
 	v = val + 1;
 	v = val + 1;
-	ok1(tdb_fetch(tdb, key).dsize == data.dsize);
+	d = tdb_fetch(tdb, key);
+	ok1(d.dsize == data.dsize);
+	free(d.dptr);
 
 
 	/* Now, this will be ideally placed. */
 	/* Now, this will be ideally placed. */
 	v = val + 2;
 	v = val + 2;
@@ -97,11 +107,17 @@ static void test_val(struct tdb_context *tdb, uint64_t val)
 	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
 	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
 
 
 	/* We can still find them all, right? */
 	/* We can still find them all, right? */
-	ok1(tdb_fetch(tdb, key).dsize == data.dsize);
+	d = tdb_fetch(tdb, key);
+	ok1(d.dsize == data.dsize);
+	free(d.dptr);
 	v = val + 1;
 	v = val + 1;
-	ok1(tdb_fetch(tdb, key).dsize == data.dsize);
+	d = tdb_fetch(tdb, key);
+	ok1(d.dsize == data.dsize);
+	free(d.dptr);
 	v = val + 2;
 	v = val + 2;
-	ok1(tdb_fetch(tdb, key).dsize == data.dsize);
+	d = tdb_fetch(tdb, key);
+	ok1(d.dsize == data.dsize);
+	free(d.dptr);
 
 
 	/* And if we delete val + 1, that val + 2 should not move! */
 	/* And if we delete val + 1, that val + 2 should not move! */
 	v = val + 1;
 	v = val + 1;
@@ -109,9 +125,13 @@ static void test_val(struct tdb_context *tdb, uint64_t val)
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 	ok1(tdb_check(tdb, NULL, NULL) == 0);
 
 
 	v = val;
 	v = val;
-	ok1(tdb_fetch(tdb, key).dsize == data.dsize);
+	d = tdb_fetch(tdb, key);
+	ok1(d.dsize == data.dsize);
+	free(d.dptr);
 	v = val + 2;
 	v = val + 2;
-	ok1(tdb_fetch(tdb, key).dsize == data.dsize);
+	d = tdb_fetch(tdb, key);
+	ok1(d.dsize == data.dsize);
+	free(d.dptr);
 
 
 	/* Delete those two, so we are empty. */
 	/* Delete those two, so we are empty. */
 	ok1(tdb_delete(tdb, key) == 0);
 	ok1(tdb_delete(tdb, key) == 0);

+ 1 - 0
ccan/tdb2/test/run-15-append.c

@@ -126,5 +126,6 @@ int main(int argc, char *argv[])
 	}
 	}
 
 
 	ok1(tap_log_messages == 0);
 	ok1(tap_log_messages == 0);
+	free(buffer);
 	return exit_status();
 	return exit_status();
 }
 }

+ 3 - 0
ccan/tdb2/test/run-25-hashoverload.c

@@ -62,6 +62,7 @@ int main(int argc, char *argv[])
 			ok1(d.dsize == sizeof(j));
 			ok1(d.dsize == sizeof(j));
 			ok1(d.dptr != NULL);
 			ok1(d.dptr != NULL);
 			ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0);
 			ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0);
+			free(d.dptr);
 		}
 		}
 
 
 		/* Now add a *lot* more. */
 		/* Now add a *lot* more. */
@@ -73,6 +74,7 @@ int main(int argc, char *argv[])
 			ok1(d.dsize == sizeof(j));
 			ok1(d.dsize == sizeof(j));
 			ok1(d.dptr != NULL);
 			ok1(d.dptr != NULL);
 			ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0);
 			ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0);
+			free(d.dptr);
 		}
 		}
 		ok1(tdb_check(tdb, NULL, NULL) == 0);
 		ok1(tdb_check(tdb, NULL, NULL) == 0);
 
 
@@ -92,6 +94,7 @@ int main(int argc, char *argv[])
 			ok1(d.dsize == sizeof(j));
 			ok1(d.dsize == sizeof(j));
 			ok1(d.dptr != NULL);
 			ok1(d.dptr != NULL);
 			ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0);
 			ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0);
+			free(d.dptr);
 		}
 		}
 
 
 		/* Traverse through them. */
 		/* Traverse through them. */

+ 1 - 0
ccan/tdb2/test/run-50-multiple-freelists.c

@@ -65,6 +65,7 @@ int main(int argc, char *argv[])
 	ok1(off == 0);
 	ok1(off == 0);
 
 
 	tdb_close(tdb);
 	tdb_close(tdb);
+	tdb_layout_free(layout);
 
 
 	ok1(tap_log_messages == 0);
 	ok1(tap_log_messages == 0);
 	return exit_status();
 	return exit_status();

+ 1 - 0
ccan/tdb2/test/run-55-transaction.c

@@ -69,5 +69,6 @@ int main(int argc, char *argv[])
 	}
 	}
 
 
 	ok1(tap_log_messages == 0);
 	ok1(tap_log_messages == 0);
+	free(buffer);
 	return exit_status();
 	return exit_status();
 }
 }

+ 57 - 7
ccan/tdb2/test/run-57-die-during-transaction.c

@@ -1,6 +1,9 @@
 #define _XOPEN_SOURCE 500
 #define _XOPEN_SOURCE 500
 #include <unistd.h>
 #include <unistd.h>
 #include "lock-tracking.h"
 #include "lock-tracking.h"
+#include <ccan/tap/tap.h>
+#include <stdlib.h>
+#include <assert.h>
 static ssize_t pwrite_check(int fd, const void *buf, size_t count, off_t offset);
 static ssize_t pwrite_check(int fd, const void *buf, size_t count, off_t offset);
 static ssize_t write_check(int fd, const void *buf, size_t count);
 static ssize_t write_check(int fd, const void *buf, size_t count);
 static int ftruncate_check(int fd, off_t length);
 static int ftruncate_check(int fd, off_t length);
@@ -10,6 +13,51 @@ static int ftruncate_check(int fd, off_t length);
 #define fcntl fcntl_with_lockcheck
 #define fcntl fcntl_with_lockcheck
 #define ftruncate ftruncate_check
 #define ftruncate ftruncate_check
 
 
+/* There's a malloc inside transaction_setup_recovery, and valgrind complains
+ * when we longjmp and leak it. */
+#define MAX_ALLOCATIONS 200
+static void *allocated[MAX_ALLOCATIONS];
+
+static void *malloc_noleak(size_t len)
+{
+	unsigned int i;
+
+	for (i = 0; i < MAX_ALLOCATIONS; i++)
+		if (!allocated[i]) {
+			allocated[i] = malloc(len);
+			return allocated[i];
+		}
+	diag("Too many allocations!");
+	abort();
+}
+
+static void free_noleak(void *p)
+{
+	unsigned int i;
+
+	/* We don't catch realloc, so don't care if we miss one. */
+	for (i = 0; i < MAX_ALLOCATIONS; i++) {
+		if (allocated[i] == p) {
+			allocated[i] = NULL;
+			break;
+		}
+	}
+	free(p);
+}
+
+static void free_all(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < MAX_ALLOCATIONS; i++) {
+		free(allocated[i]);
+		allocated[i] = NULL;
+	}
+}
+
+#define malloc malloc_noleak
+#define free free_noleak
+
 #include <ccan/tdb2/tdb.c>
 #include <ccan/tdb2/tdb.c>
 #include <ccan/tdb2/free.c>
 #include <ccan/tdb2/free.c>
 #include <ccan/tdb2/lock.c>
 #include <ccan/tdb2/lock.c>
@@ -17,8 +65,13 @@ static int ftruncate_check(int fd, off_t length);
 #include <ccan/tdb2/hash.c>
 #include <ccan/tdb2/hash.c>
 #include <ccan/tdb2/check.c>
 #include <ccan/tdb2/check.c>
 #include <ccan/tdb2/transaction.c>
 #include <ccan/tdb2/transaction.c>
-#include <ccan/tap/tap.h>
-#include <stdlib.h>
+#undef malloc
+#undef free
+#undef write
+#undef pwrite
+#undef fcntl
+#undef ftruncate
+
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdarg.h>
 #include <stdarg.h>
 #include <err.h>
 #include <err.h>
@@ -26,11 +79,6 @@ static int ftruncate_check(int fd, off_t length);
 #include "external-agent.h"
 #include "external-agent.h"
 #include "logging.h"
 #include "logging.h"
 
 
-#undef write
-#undef pwrite
-#undef fcntl
-#undef ftruncate
-
 static bool in_transaction;
 static bool in_transaction;
 static int target, current;
 static int target, current;
 static jmp_buf jmpbuf;
 static jmp_buf jmpbuf;
@@ -150,6 +198,7 @@ reset:
 		suppress_lockcheck = false;
 		suppress_lockcheck = false;
 		target++;
 		target++;
 		current = 0;
 		current = 0;
+		free_all();
 		goto reset;
 		goto reset;
 	}
 	}
 
 
@@ -217,5 +266,6 @@ int main(int argc, char *argv[])
 		ok1(test_death(ops[i], agent));
 		ok1(test_death(ops[i], agent));
 	}
 	}
 
 
+	free_external_agent(agent);
 	return exit_status();
 	return exit_status();
 }
 }

+ 2 - 0
ccan/tdb2/test/run-record-expand.c

@@ -46,5 +46,7 @@ int main(int argc, char *argv[])
 		tdb_close(tdb);
 		tdb_close(tdb);
 	}
 	}
 	ok1(tap_log_messages == 0);
 	ok1(tap_log_messages == 0);
+	free(data.dptr);
+
 	return exit_status();
 	return exit_status();
 }
 }

+ 1 - 0
ccan/tdb2/test/run-remap-in-read_traverse.c

@@ -58,5 +58,6 @@ int main(int argc, char *argv[])
 	/* Now store something! */
 	/* Now store something! */
 	ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0);
 	ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0);
 	ok1(tap_log_messages == 0);
 	ok1(tap_log_messages == 0);
+	free_external_agent(agent);
 	return exit_status();
 	return exit_status();
 }
 }