From 4f13ebef5d6711ac121b9c41e2fbbe2cd3b6da0e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 Sep 2004 06:31:14 +0000 Subject: r2744: ben elliston taught me about gcov today, which allows you to measure the % coverage in terms of lines of code of a test suite. I thought a good first place to start with gcov was the talloc test suite. When I started the test suite covered about 60% of all lines of code in talloc.c, and now it covers about 99%. The only lines not covered are talloc corruption errors, as that would cause smb_panic() to fire. It will be interesting to try gcov on the main Samba test suite for smbd. We won't achieve 100% coverage, but it would be nice to get to 90% or more. I also modified the talloc.c sources to be able to be build standalone, using: gcc -c -D_STANDALONE_ -Iinlcude lib/talloc.c that should make it much easier to re-use talloc in other projects (This used to be commit 8d4dc99b82efdf24b6811851c7bdd4af5a4c52c9) --- source4/torture/local/talloc.c | 320 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 300 insertions(+), 20 deletions(-) (limited to 'source4/torture') diff --git a/source4/torture/local/talloc.c b/source4/torture/local/talloc.c index e046ae8dc5..a3bfb45f54 100644 --- a/source4/torture/local/talloc.c +++ b/source4/torture/local/talloc.c @@ -24,8 +24,8 @@ #define CHECK_BLOCKS(ptr, tblocks) do { \ if (talloc_total_blocks(ptr) != (tblocks)) { \ - printf("(%d) failed: wrong '%s' tree size: got %u expected %u\n", \ - __LINE__, #ptr, \ + printf(__location__ " failed: wrong '%s' tree blocks: got %u expected %u\n", \ + #ptr, \ (unsigned)talloc_total_blocks(ptr), \ (unsigned)tblocks); \ talloc_report_full(ptr, stdout); \ @@ -33,6 +33,17 @@ } \ } while (0) +#define CHECK_SIZE(ptr, tsize) do { \ + if (talloc_total_size(ptr) != (tsize)) { \ + printf(__location__ " failed: wrong '%s' tree size: got %u expected %u\n", \ + #ptr, \ + (unsigned)talloc_total_size(ptr), \ + (unsigned)tsize); \ + talloc_report_full(ptr, stdout); \ + return False; \ + } \ +} while (0) + /* test references */ @@ -77,10 +88,7 @@ static BOOL test_ref1(void) CHECK_BLOCKS(root, 1); - if (talloc_total_size(root) != 0) { - printf("failed: non-zero total size\n"); - return False; - } + CHECK_SIZE(root, 0); talloc_free(root); @@ -136,10 +144,7 @@ static BOOL test_ref2(void) talloc_free(r1); talloc_report_full(root, stdout); - if (talloc_total_size(root) != 0) { - printf("failed: non-zero total size\n"); - return False; - } + CHECK_SIZE(root, 0); talloc_free(root); @@ -177,10 +182,7 @@ static BOOL test_ref3(void) talloc_free(p2); talloc_report_full(root, stdout); - if (talloc_total_size(root) != 0) { - printf("failed: non-zero total size\n"); - return False; - } + CHECK_SIZE(root, 0); talloc_free(root); @@ -228,10 +230,7 @@ static BOOL test_ref4(void) talloc_free(p1); talloc_report_full(root, stdout); - if (talloc_total_size(root) != 0) { - printf("failed: non-zero total size\n"); - return False; - } + CHECK_SIZE(root, 0); talloc_free(root); @@ -275,16 +274,293 @@ static BOOL test_unref1(void) talloc_free(p1); talloc_report_full(root, stdout); - if (talloc_total_size(root) != 0) { - printf("failed: non-zero total size\n"); + CHECK_SIZE(root, 0); + + talloc_free(root); + + return True; +} + +static int fail_destructor(void *ptr) +{ + return -1; +} + +/* + miscellaneous tests to try to get a higher test coverage percentage +*/ +static BOOL test_misc(void) +{ + void *root, *p1; + char *p2; + double *d; + + printf("TESTING MISCELLANEOUS\n"); + + root = talloc(NULL, 0); + + p1 = talloc(root, 0x7fffffff); + if (p1) { + printf("failed: large talloc allowed\n"); + return False; + } + + p1 = talloc_strdup(root, "foo"); + talloc_increase_ref_count(p1); + talloc_increase_ref_count(p1); + talloc_increase_ref_count(p1); + CHECK_BLOCKS(p1, 1); + CHECK_BLOCKS(root, 2); + talloc_free(p1); + CHECK_BLOCKS(p1, 1); + CHECK_BLOCKS(root, 2); + talloc_unreference(NULL, p1); + CHECK_BLOCKS(p1, 1); + CHECK_BLOCKS(root, 2); + if (talloc_unreference(root, p1) != NULL) { + printf("failed: talloc_unreference() of non-reference context should return NULL\n"); + return False; + } + talloc_free(p1); + CHECK_BLOCKS(p1, 1); + CHECK_BLOCKS(root, 2); + + talloc_set_name(p1, "my name is %s", "foo"); + if (strcmp(talloc_get_name(p1), "my name is foo") != 0) { + printf("failed: wrong name after talloc_set_name\n"); + return False; + } + CHECK_BLOCKS(p1, 2); + CHECK_BLOCKS(root, 3); + + talloc_set_name_const(p1, NULL); + if (strcmp(talloc_get_name(p1), "UNNAMED") != 0) { + printf("failed: wrong name after talloc_set_name(NULL)\n"); + return False; + } + CHECK_BLOCKS(p1, 2); + CHECK_BLOCKS(root, 3); + + + if (talloc_free(NULL) != -1) { + printf("talloc_free(NULL) should give -1\n"); + return False; + } + + talloc_set_destructor(p1, fail_destructor); + if (talloc_free(p1) != -1) { + printf("Failed destructor should cause talloc_free to fail\n"); + return False; + } + talloc_set_destructor(p1, NULL); + + talloc_report(root, stdout); + + + p2 = talloc_zero(p1, 20); + if (p2[19] != 0) { + printf("Failed to give zero memory\n"); + return False; + } + talloc_free(p2); + + if (talloc_strdup(root, NULL) != NULL) { + printf("failed: strdup on NULL should give NULL\n"); + return False; + } + + p2 = talloc_strndup(p1, "foo", 2); + if (strcmp("fo", p2) != 0) { + printf("failed: strndup doesn't work\n"); + return False; + } + p2 = talloc_asprintf_append(p2, "o%c", 'd'); + if (strcmp("food", p2) != 0) { + printf("failed: talloc_asprintf_append doesn't work\n"); + return False; + } + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(p1, 3); + + p2 = talloc_asprintf_append(NULL, "hello %s", "world"); + if (strcmp("hello world", p2) != 0) { + printf("failed: talloc_asprintf_append doesn't work\n"); + return False; + } + CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS(p1, 3); + talloc_free(p2); + + d = talloc_array_p(p1, double, 0x20000000); + if (d) { + printf("failed: integer overflow not detected\n"); + return False; + } + + d = talloc_realloc_p(p1, d, double, 0x20000000); + if (d) { + printf("failed: integer overflow not detected\n"); + return False; + } + + talloc_free(p1); + CHECK_BLOCKS(root, 1); + + talloc_report(root, stdout); + talloc_report(NULL, stdout); + + CHECK_SIZE(root, 0); + + talloc_free(root); + + CHECK_SIZE(NULL, 0); + + talloc_enable_leak_report(); + talloc_enable_leak_report_full(); + + return True; +} + + +/* + test realloc +*/ +static BOOL test_realloc(void) +{ + void *root, *p1, *p2; + + printf("TESTING REALLOC\n"); + + root = talloc(NULL, 0); + + p1 = talloc(root, 10); + CHECK_SIZE(p1, 10); + + p1 = talloc_realloc(NULL, p1, 20); + CHECK_SIZE(p1, 20); + + talloc(p1, 0); + + p2 = talloc_realloc(p1, NULL, 30); + + talloc(p1, 0); + + p2 = talloc_realloc(p1, p2, 40); + + CHECK_SIZE(p2, 40); + CHECK_SIZE(root, 60); + CHECK_BLOCKS(p1, 4); + + p1 = talloc_realloc(NULL, p1, 20); + CHECK_SIZE(p1, 60); + + talloc_increase_ref_count(p2); + if (talloc_realloc(NULL, p2, 5) != NULL) { + printf("failed: talloc_realloc() on a referenced pointer should fail\n"); return False; } + CHECK_BLOCKS(p1, 4); + + talloc_realloc(NULL, p2, 0); + talloc_realloc(NULL, p2, 0); + CHECK_BLOCKS(p1, 3); + + if (talloc_realloc(NULL, p1, 0x7fffffff) != NULL) { + printf("failed: oversize talloc should fail\n"); + return False; + } + + talloc_realloc(NULL, p1, 0); + + CHECK_BLOCKS(root, 1); + CHECK_SIZE(root, 0); talloc_free(root); return True; } +/* + test steal +*/ +static BOOL test_steal(void) +{ + void *root, *p1, *p2; + + printf("TESTING STEAL\n"); + + root = talloc(NULL, 0); + + p1 = talloc_array_p(root, char, 10); + CHECK_SIZE(p1, 10); + + p2 = talloc_realloc_p(root, NULL, char, 20); + CHECK_SIZE(p1, 10); + CHECK_SIZE(root, 30); + + if (talloc_steal(p1, NULL) != NULL) { + printf("failed: stealing NULL should give NULL\n"); + return False; + } + + if (talloc_steal(p1, p1) != p1) { + printf("failed: stealing to ourselves is a nop\n"); + return False; + } + CHECK_BLOCKS(root, 3); + CHECK_SIZE(root, 30); + + talloc_steal(NULL, p1); + talloc_steal(NULL, p2); + CHECK_BLOCKS(root, 1); + CHECK_SIZE(root, 0); + + talloc_free(p1); + talloc_steal(root, p2); + CHECK_BLOCKS(root, 2); + CHECK_SIZE(root, 20); + + talloc_free(p2); + + CHECK_BLOCKS(root, 1); + CHECK_SIZE(root, 0); + + talloc_free(root); + + p1 = talloc(NULL, 3); + CHECK_SIZE(NULL, 3); + talloc_free(p1); + + return True; +} + +/* + test ldb alloc fn +*/ +static BOOL test_ldb(void) +{ + void *root, *p1; + + printf("TESTING LDB\n"); + + root = talloc(NULL, 0); + + p1 = talloc_ldb_alloc(root, NULL, 10); + CHECK_BLOCKS(root, 2); + CHECK_SIZE(root, 10); + p1 = talloc_ldb_alloc(root, p1, 20); + CHECK_BLOCKS(root, 2); + CHECK_SIZE(root, 20); + p1 = talloc_ldb_alloc(root, p1, 0); + CHECK_BLOCKS(root, 1); + CHECK_SIZE(root, 0); + + talloc_free(root); + + + return True; +} + /* measure the speed of talloc versus malloc */ @@ -340,6 +616,10 @@ BOOL torture_local_talloc(int dummy) ret &= test_ref3(); ret &= test_ref4(); ret &= test_unref1(); + ret &= test_misc(); + ret &= test_realloc(); + ret &= test_steal(); + ret &= test_ldb(); ret &= test_speed(); return ret; -- cgit