diff options
author | Andrew Tridgell <tridge@samba.org> | 2006-10-21 00:23:27 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:15:35 -0500 |
commit | 2729f448c073232bc33feba4b520871bb6a583c9 (patch) | |
tree | 46d32aa6a39e6c66382699504b330ebca3232a0a /source3/lib/talloc | |
parent | 7a390a0dabcdadb30196662b6cdec512bf81dcb4 (diff) | |
download | samba-2729f448c073232bc33feba4b520871bb6a583c9.tar.gz samba-2729f448c073232bc33feba4b520871bb6a583c9.tar.bz2 samba-2729f448c073232bc33feba4b520871bb6a583c9.zip |
r19431: merge recent talloc performance improvements from Samba4
(This used to be commit ced12bd6d8c95a103cb2c84166a64f9a21bd32ad)
Diffstat (limited to 'source3/lib/talloc')
-rw-r--r-- | source3/lib/talloc/config.mk | 4 | ||||
-rw-r--r-- | source3/lib/talloc/talloc.c | 527 | ||||
-rw-r--r-- | source3/lib/talloc/testsuite.c | 723 |
3 files changed, 660 insertions, 594 deletions
diff --git a/source3/lib/talloc/config.mk b/source3/lib/talloc/config.mk index 3a8a22aa57..0b06687dab 100644 --- a/source3/lib/talloc/config.mk +++ b/source3/lib/talloc/config.mk @@ -12,3 +12,7 @@ DESCRIPTION = A hierarchical pool based memory system with destructors # End LIBRARY LIBTALLOC ################################################ +[BINARY::TALLOC] +OBJ_FILES = testsuite.o +PRIVATE_DEPENDENCIES = LIBTALLOC +INSTALLDIR = TORTUREDIR/LOCAL diff --git a/source3/lib/talloc/talloc.c b/source3/lib/talloc/talloc.c index 15b27c61ee..bae1942f43 100644 --- a/source3/lib/talloc/talloc.c +++ b/source3/lib/talloc/talloc.c @@ -77,6 +77,17 @@ #endif #endif +/* these macros gain us a few percent of speed on gcc */ +#if (__GNUC__ >= 3) +/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1 + as its first argument */ +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) x +#define unlikely(x) x +#endif + /* this null_context is only used if talloc_enable_leak_report() or talloc_enable_leak_report_full() is called, otherwise it remains NULL @@ -106,15 +117,16 @@ struct talloc_chunk { #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) /* panic if we get a bad magic value */ -static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) +static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { const char *pp = (const char *)ptr; struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); - if ((tc->flags & ~0xF) != TALLOC_MAGIC) { - TALLOC_ABORT("Bad talloc magic value - unknown value"); - } - if (tc->flags & TALLOC_FLAG_FREE) { - TALLOC_ABORT("Bad talloc magic value - double free"); + if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { + if (tc->flags & TALLOC_FLAG_FREE) { + TALLOC_ABORT("Bad talloc magic value - double free"); + } else { + TALLOC_ABORT("Bad talloc magic value - unknown value"); + } } return tc; } @@ -163,23 +175,43 @@ void *talloc_parent(const void *ptr) return tc? TC_PTR_FROM_CHUNK(tc) : NULL; } +/* + find parents name +*/ +const char *talloc_parent_name(const void *context) +{ + struct talloc_chunk *tc; + + if (unlikely(context == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(context); + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + } + return tc->name; +} + + /* Allocate a bit of memory as a child of an existing pointer */ -void *_talloc(const void *context, size_t size) +static inline void *__talloc(const void *context, size_t size) { struct talloc_chunk *tc; - if (context == NULL) { + if (unlikely(context == NULL)) { context = null_context; } - if (size >= MAX_TALLOC_SIZE) { + if (unlikely(size >= MAX_TALLOC_SIZE)) { return NULL; } tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size); - if (tc == NULL) return NULL; + if (unlikely(tc == NULL)) return NULL; tc->size = size; tc->flags = TALLOC_MAGIC; @@ -188,16 +220,19 @@ void *_talloc(const void *context, size_t size) tc->name = NULL; tc->refs = NULL; - if (context) { + if (likely(context)) { struct talloc_chunk *parent = talloc_chunk_from_ptr(context); - tc->parent = parent; - if (parent->child) { parent->child->parent = NULL; + tc->next = parent->child; + tc->next->prev = tc; + } else { + tc->next = NULL; } - - _TLIST_ADD(parent->child, tc); + tc->parent = parent; + tc->prev = NULL; + parent->child = tc; } else { tc->next = tc->prev = tc->parent = NULL; } @@ -205,7 +240,6 @@ void *_talloc(const void *context, size_t size) return TC_PTR_FROM_CHUNK(tc); } - /* setup a destructor to be called on free of a pointer the destructor should return 0 on success, or -1 on failure. @@ -223,7 +257,7 @@ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)) */ int talloc_increase_ref_count(const void *ptr) { - if (!talloc_reference(null_context, ptr)) { + if (unlikely(!talloc_reference(null_context, ptr))) { return -1; } return 0; @@ -240,6 +274,33 @@ static int talloc_reference_destructor(struct talloc_reference_handle *handle) } /* + more efficient way to add a name to a pointer - the name must point to a + true string constant +*/ +static inline void _talloc_set_name_const(const void *ptr, const char *name) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = name; +} + +/* + internal talloc_named_const() +*/ +static inline void *_talloc_named_const(const void *context, size_t size, const char *name) +{ + void *ptr; + + ptr = __talloc(context, size); + if (unlikely(ptr == NULL)) { + return NULL; + } + + _talloc_set_name_const(ptr, name); + + return ptr; +} + +/* make a secondary reference to a pointer, hanging off the given context. the pointer remains valid until both the original caller and this given context are freed. @@ -252,13 +313,13 @@ void *_talloc_reference(const void *context, const void *ptr) { struct talloc_chunk *tc; struct talloc_reference_handle *handle; - if (ptr == NULL) return NULL; + if (unlikely(ptr == NULL)) return NULL; tc = talloc_chunk_from_ptr(ptr); - handle = (struct talloc_reference_handle *)talloc_named_const(context, + handle = (struct talloc_reference_handle *)_talloc_named_const(context, sizeof(struct talloc_reference_handle), TALLOC_MAGIC_REFERENCE); - if (handle == NULL) return NULL; + if (unlikely(handle == NULL)) return NULL; /* note that we hang the destructor off the handle, not the main context as that allows the caller to still setup their @@ -269,6 +330,152 @@ void *_talloc_reference(const void *context, const void *ptr) return handle->ptr; } + +/* + internal talloc_free call +*/ +static inline int _talloc_free(void *ptr) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return -1; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(tc->refs)) { + int is_child; + /* check this is a reference from a child or grantchild + * back to it's parent or grantparent + * + * in that case we need to remove the reference and + * call another instance of talloc_free() on the current + * pointer. + */ + is_child = talloc_is_parent(tc->refs, ptr); + _talloc_free(tc->refs); + if (is_child) { + return _talloc_free(ptr); + } + return -1; + } + + if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) { + /* we have a free loop - stop looping */ + return 0; + } + + if (unlikely(tc->destructor)) { + talloc_destructor_t d = tc->destructor; + if (d == (talloc_destructor_t)-1) { + return -1; + } + tc->destructor = (talloc_destructor_t)-1; + if (d(ptr) == -1) { + tc->destructor = d; + return -1; + } + tc->destructor = NULL; + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + while (tc->child) { + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = TC_PTR_FROM_CHUNK(tc->child); + const void *new_parent = null_context; + if (unlikely(tc->child->refs)) { + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + if (unlikely(_talloc_free(child) == -1)) { + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + talloc_steal(new_parent, child); + } + } + + tc->flags |= TALLOC_FLAG_FREE; + free(tc); + return 0; +} + +/* + move a lump of memory from one talloc context to another return the + ptr on success, or NULL if it could not be transferred. + passing NULL as ptr will always return NULL with no side effects. +*/ +void *_talloc_steal(const void *new_ctx, const void *ptr) +{ + struct talloc_chunk *tc, *new_tc; + + if (unlikely(!ptr)) { + return NULL; + } + + if (unlikely(new_ctx == NULL)) { + new_ctx = null_context; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(new_ctx == NULL)) { + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = tc->next = tc->prev = NULL; + return discard_const_p(void, ptr); + } + + new_tc = talloc_chunk_from_ptr(new_ctx); + + if (unlikely(tc == new_tc || tc->parent == new_tc)) { + return discard_const_p(void, ptr); + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = new_tc; + if (new_tc->child) new_tc->child->parent = NULL; + _TLIST_ADD(new_tc->child, tc); + + return discard_const_p(void, ptr); +} + + + /* remove a secondary reference to a pointer. This undo's what talloc_reference() has done. The context and pointer arguments @@ -279,7 +486,7 @@ static int talloc_unreference(const void *context, const void *ptr) struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); struct talloc_reference_handle *h; - if (context == NULL) { + if (unlikely(context == NULL)) { context = null_context; } @@ -295,7 +502,7 @@ static int talloc_unreference(const void *context, const void *ptr) return -1; } - return talloc_free(h); + return _talloc_free(h); } /* @@ -332,7 +539,7 @@ int talloc_unlink(const void *context, void *ptr) tc_p = talloc_chunk_from_ptr(ptr); if (tc_p->refs == NULL) { - return talloc_free(ptr); + return _talloc_free(ptr); } new_p = talloc_parent_chunk(tc_p->refs); @@ -360,8 +567,8 @@ static const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list a { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); tc->name = talloc_vasprintf(ptr, fmt, ap); - if (tc->name) { - talloc_set_name_const(tc->name, ".name"); + if (likely(tc->name)) { + _talloc_set_name_const(tc->name, ".name"); } return tc->name; } @@ -379,15 +586,6 @@ const char *talloc_set_name(const void *ptr, const char *fmt, ...) return name; } -/* - more efficient way to add a name to a pointer - the name must point to a - true string constant -*/ -void talloc_set_name_const(const void *ptr, const char *name) -{ - struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - tc->name = name; -} /* create a named talloc pointer. Any talloc pointer can be named, and @@ -400,15 +598,15 @@ void *talloc_named(const void *context, size_t size, const char *fmt, ...) void *ptr; const char *name; - ptr = _talloc(context, size); - if (ptr == NULL) return NULL; + ptr = __talloc(context, size); + if (unlikely(ptr == NULL)) return NULL; va_start(ap, fmt); name = talloc_set_name_v(ptr, fmt, ap); va_end(ap); - if (name == NULL) { - talloc_free(ptr); + if (unlikely(name == NULL)) { + _talloc_free(ptr); return NULL; } @@ -416,34 +614,15 @@ void *talloc_named(const void *context, size_t size, const char *fmt, ...) } /* - create a named talloc pointer. Any talloc pointer can be named, and - talloc_named() operates just like talloc() except that it allows you - to name the pointer. -*/ -void *talloc_named_const(const void *context, size_t size, const char *name) -{ - void *ptr; - - ptr = _talloc(context, size); - if (ptr == NULL) { - return NULL; - } - - talloc_set_name_const(ptr, name); - - return ptr; -} - -/* return the name of a talloc ptr, or "UNNAMED" */ const char *talloc_get_name(const void *ptr) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); - if (tc->name == TALLOC_MAGIC_REFERENCE) { + if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) { return ".reference"; } - if (tc->name) { + if (likely(tc->name)) { return tc->name; } return "UNNAMED"; @@ -457,9 +636,9 @@ const char *talloc_get_name(const void *ptr) void *talloc_check_name(const void *ptr, const char *name) { const char *pname; - if (ptr == NULL) return NULL; + if (unlikely(ptr == NULL)) return NULL; pname = talloc_get_name(ptr); - if (pname == name || strcmp(pname, name) == 0) { + if (likely(pname == name || strcmp(pname, name) == 0)) { return discard_const_p(void, ptr); } return NULL; @@ -482,15 +661,15 @@ void *talloc_init(const char *fmt, ...) */ talloc_enable_null_tracking(); - ptr = _talloc(NULL, 0); - if (ptr == NULL) return NULL; + ptr = __talloc(NULL, 0); + if (unlikely(ptr == NULL)) return NULL; va_start(ap, fmt); name = talloc_set_name_v(ptr, fmt, ap); va_end(ap); - if (name == NULL) { - talloc_free(ptr); + if (unlikely(name == NULL)) { + _talloc_free(ptr); return NULL; } @@ -506,7 +685,7 @@ void talloc_free_children(void *ptr) { struct talloc_chunk *tc; - if (ptr == NULL) { + if (unlikely(ptr == NULL)) { return; } @@ -520,11 +699,11 @@ void talloc_free_children(void *ptr) final choice is the null context. */ void *child = TC_PTR_FROM_CHUNK(tc->child); const void *new_parent = null_context; - if (tc->child->refs) { + if (unlikely(tc->child->refs)) { struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); if (p) new_parent = TC_PTR_FROM_CHUNK(p); } - if (talloc_free(child) == -1) { + if (unlikely(_talloc_free(child) == -1)) { if (new_parent == null_context) { struct talloc_chunk *p = talloc_parent_chunk(ptr); if (p) new_parent = TC_PTR_FROM_CHUNK(p); @@ -535,6 +714,32 @@ void talloc_free_children(void *ptr) } /* + Allocate a bit of memory as a child of an existing pointer +*/ +void *_talloc(const void *context, size_t size) +{ + return __talloc(context, size); +} + +/* + externally callable talloc_set_name_const() +*/ +void talloc_set_name_const(const void *ptr, const char *name) +{ + _talloc_set_name_const(ptr, name); +} + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +void *talloc_named_const(const void *context, size_t size, const char *name) +{ + return _talloc_named_const(context, size, name); +} + +/* free a talloc pointer. This also frees all child pointers of this pointer recursively @@ -544,68 +749,7 @@ void talloc_free_children(void *ptr) */ int talloc_free(void *ptr) { - struct talloc_chunk *tc; - int old_errno; - - if (ptr == NULL) { - return -1; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (tc->refs) { - int is_child; - /* check this is a reference from a child or grantchild - * back to it's parent or grantparent - * - * in that case we need to remove the reference and - * call another instance of talloc_free() on the current - * pointer. - */ - is_child = talloc_is_parent(tc->refs, ptr); - talloc_free(tc->refs); - if (is_child) { - return talloc_free(ptr); - } - return -1; - } - - if (tc->flags & TALLOC_FLAG_LOOP) { - /* we have a free loop - stop looping */ - return 0; - } - - if (tc->destructor) { - talloc_destructor_t d = tc->destructor; - if (d == (talloc_destructor_t)-1) { - return -1; - } - tc->destructor = (talloc_destructor_t)-1; - if (d(ptr) == -1) { - tc->destructor = d; - return -1; - } - tc->destructor = NULL; - } - - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->flags |= TALLOC_FLAG_LOOP; - talloc_free_children(ptr); - - tc->flags |= TALLOC_FLAG_FREE; - old_errno = errno; - free(tc); - errno = old_errno; - return 0; + return _talloc_free(ptr); } @@ -620,24 +764,24 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n void *new_ptr; /* size zero is equivalent to free() */ - if (size == 0) { - talloc_free(ptr); + if (unlikely(size == 0)) { + _talloc_free(ptr); return NULL; } - if (size >= MAX_TALLOC_SIZE) { + if (unlikely(size >= MAX_TALLOC_SIZE)) { return NULL; } /* realloc(NULL) is equavalent to malloc() */ if (ptr == NULL) { - return talloc_named_const(context, size, name); + return _talloc_named_const(context, size, name); } tc = talloc_chunk_from_ptr(ptr); /* don't allow realloc on referenced pointers */ - if (tc->refs) { + if (unlikely(tc->refs)) { return NULL; } @@ -653,7 +797,7 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n #else new_ptr = realloc(tc, size + TC_HDR_SIZE); #endif - if (!new_ptr) { + if (unlikely(!new_ptr)) { tc->flags &= ~TALLOC_FLAG_FREE; return NULL; } @@ -675,68 +819,11 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n } tc->size = size; - talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); + _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); return TC_PTR_FROM_CHUNK(tc); } -/* - move a lump of memory from one talloc context to another return the - ptr on success, or NULL if it could not be transferred. - passing NULL as ptr will always return NULL with no side effects. -*/ -void *_talloc_steal(const void *new_ctx, const void *ptr) -{ - struct talloc_chunk *tc, *new_tc; - - if (!ptr) { - return NULL; - } - - if (new_ctx == NULL) { - new_ctx = null_context; - } - - tc = talloc_chunk_from_ptr(ptr); - - if (new_ctx == NULL) { - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->parent = tc->next = tc->prev = NULL; - return discard_const_p(void, ptr); - } - - new_tc = talloc_chunk_from_ptr(new_ctx); - - if (tc == new_tc || tc->parent == new_tc) { - return discard_const_p(void, ptr); - } - - if (tc->parent) { - _TLIST_REMOVE(tc->parent->child, tc); - if (tc->parent->child) { - tc->parent->child->parent = tc->parent; - } - } else { - if (tc->prev) tc->prev->next = tc->next; - if (tc->next) tc->next->prev = tc->prev; - } - - tc->parent = new_tc; - if (new_tc->child) new_tc->child->parent = NULL; - _TLIST_ADD(new_tc->child, tc); - - return discard_const_p(void, ptr); -} - /* a wrapper around talloc_steal() for situations where you are moving a pointer between two structures, and want the old pointer to be set to NULL @@ -880,12 +967,29 @@ static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_ return; } - fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", + fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", depth*4, "", name, (unsigned long)talloc_total_size(ptr), (unsigned long)talloc_total_blocks(ptr), - (int)talloc_reference_count(ptr)); + (int)talloc_reference_count(ptr), ptr); + +#if 0 + fprintf(f, "content: "); + if (talloc_total_size(ptr)) { + int tot = talloc_total_size(ptr); + int i; + + for (i = 0; i < tot; i++) { + if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) { + fprintf(f, "%c", ((char *)ptr)[i]); + } else { + fprintf(f, "~%02x", ((char *)ptr)[i]); + } + } + } + fprintf(f, "\n"); +#endif } /* @@ -939,7 +1043,7 @@ static void talloc_report_null_full(void) void talloc_enable_null_tracking(void) { if (null_context == NULL) { - null_context = talloc_named_const(NULL, 0, "null_context"); + null_context = _talloc_named_const(NULL, 0, "null_context"); } } @@ -948,7 +1052,7 @@ void talloc_enable_null_tracking(void) */ void talloc_disable_null_tracking(void) { - talloc_free(null_context); + _talloc_free(null_context); null_context = NULL; } @@ -975,7 +1079,7 @@ void talloc_enable_leak_report_full(void) */ void *_talloc_zero(const void *ctx, size_t size, const char *name) { - void *p = talloc_named_const(ctx, size, name); + void *p = _talloc_named_const(ctx, size, name); if (p) { memset(p, '\0', size); @@ -990,9 +1094,9 @@ void *_talloc_zero(const void *ctx, size_t size, const char *name) */ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) { - void *newp = talloc_named_const(t, size, name); + void *newp = _talloc_named_const(t, size, name); - if (newp) { + if (likely(newp)) { memcpy(newp, p, size); } @@ -1009,8 +1113,8 @@ char *talloc_strdup(const void *t, const char *p) return NULL; } ret = (char *)talloc_memdup(t, p, strlen(p) + 1); - if (ret) { - talloc_set_name_const(ret, ret); + if (likely(ret)) { + _talloc_set_name_const(ret, ret); } return ret; } @@ -1049,11 +1153,11 @@ char *talloc_strndup(const void *t, const char *p, size_t n) for (len=0; len<n && p[len]; len++) ; - ret = (char *)_talloc(t, len + 1); + ret = (char *)__talloc(t, len + 1); if (!ret) { return NULL; } memcpy(ret, p, len); ret[len] = 0; - talloc_set_name_const(ret, ret); + _talloc_set_name_const(ret, ret); return ret; } @@ -1079,11 +1183,11 @@ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) return NULL; } - ret = (char *)_talloc(t, len+1); + ret = (char *)__talloc(t, len+1); if (ret) { va_copy(ap2, ap); vsnprintf(ret, len+1, fmt, ap2); - talloc_set_name_const(ret, ret); + _talloc_set_name_const(ret, ret); } return ret; @@ -1143,7 +1247,7 @@ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) va_copy(ap2, ap); vsnprintf(s+s_len, len+1, fmt, ap2); - talloc_set_name_const(s, s); + _talloc_set_name_const(s, s); return s; } @@ -1171,7 +1275,7 @@ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char if (count >= MAX_TALLOC_SIZE/el_size) { return NULL; } - return talloc_named_const(ctx, el_size * count, name); + return _talloc_named_const(ctx, el_size * count, name); } /* @@ -1216,7 +1320,7 @@ static int talloc_autofree_destructor(void *ptr) static void talloc_autofree(void) { - talloc_free(autofree_context); + _talloc_free(autofree_context); } /* @@ -1226,7 +1330,7 @@ static void talloc_autofree(void) void *talloc_autofree_context(void) { if (autofree_context == NULL) { - autofree_context = talloc_named_const(NULL, 0, "autofree_context"); + autofree_context = _talloc_named_const(NULL, 0, "autofree_context"); talloc_set_destructor(autofree_context, talloc_autofree_destructor); atexit(talloc_autofree); } @@ -1290,6 +1394,7 @@ void talloc_show_parents(const void *context, FILE *file) tc = tc->parent; } } + fflush(file); } /* diff --git a/source3/lib/talloc/testsuite.c b/source3/lib/talloc/testsuite.c index 1a2a60a3a3..f51252e57b 100644 --- a/source3/lib/talloc/testsuite.c +++ b/source3/lib/talloc/testsuite.c @@ -28,8 +28,6 @@ #include "system/time.h" #include "talloc.h" -struct torture_context; - static struct timeval timeval_current(void) { struct timeval tv; @@ -44,6 +42,19 @@ static double timeval_elapsed(struct timeval *tv) (tv2.tv_usec - tv->tv_usec)*1.0e-6; } +#define torture_assert(test, expr, str) if (!(expr)) { \ + printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \ + test, __location__, #expr, str); \ + return false; \ +} + +#define torture_assert_str_equal(test, arg1, arg2, desc) \ + if (strcmp(arg1, arg2)) { \ + printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \ + test, __location__, arg1, arg2, desc); \ + return false; \ + } + #if _SAMBA_BUILD_==3 #ifdef malloc #undef malloc @@ -53,10 +64,10 @@ static double timeval_elapsed(struct timeval *tv) #endif #endif -#define CHECK_SIZE(ptr, tsize) do { \ +#define CHECK_SIZE(test, ptr, tsize) do { \ if (talloc_total_size(ptr) != (tsize)) { \ - printf(__location__ " failed: wrong '%s' tree size: got %u expected %u\n", \ - #ptr, \ + printf("failed: %s [\nwrong '%s' tree size: got %u expected %u\n]\n", \ + test, #ptr, \ (unsigned)talloc_total_size(ptr), \ (unsigned)tsize); \ talloc_report_full(ptr, stdout); \ @@ -64,10 +75,10 @@ static double timeval_elapsed(struct timeval *tv) } \ } while (0) -#define CHECK_BLOCKS(ptr, tblocks) do { \ +#define CHECK_BLOCKS(test, ptr, tblocks) do { \ if (talloc_total_blocks(ptr) != (tblocks)) { \ - printf(__location__ " failed: wrong '%s' tree blocks: got %u expected %u\n", \ - #ptr, \ + printf("failed: %s [\nwrong '%s' tree blocks: got %u expected %u\n]\n", \ + test, #ptr, \ (unsigned)talloc_total_blocks(ptr), \ (unsigned)tblocks); \ talloc_report_full(ptr, stdout); \ @@ -75,10 +86,10 @@ static double timeval_elapsed(struct timeval *tv) } \ } while (0) -#define CHECK_PARENT(ptr, parent) do { \ +#define CHECK_PARENT(test, ptr, parent) do { \ if (talloc_parent(ptr) != (parent)) { \ - printf(__location__ " failed: '%s' has wrong parent: got %p expected %p\n", \ - #ptr, \ + printf("failed: %s [\n'%s' has wrong parent: got %p expected %p\n]\n", \ + test, #ptr, \ talloc_parent(ptr), \ (parent)); \ talloc_report_full(ptr, stdout); \ @@ -96,7 +107,7 @@ static bool test_ref1(void) { void *root, *p1, *p2, *ref, *r1; - printf("TESTING SINGLE REFERENCE FREE\n"); + printf("test: ref1 [\nSINGLE REFERENCE FREE\n]\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "p1"); @@ -107,41 +118,41 @@ static bool test_ref1(void) r1 = talloc_named_const(root, 1, "r1"); ref = talloc_reference(r1, p2); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 2); + CHECK_BLOCKS("ref1", p1, 5); + CHECK_BLOCKS("ref1", p2, 1); + CHECK_BLOCKS("ref1", r1, 2); - printf("Freeing p2\n"); + fprintf(stderr, "Freeing p2\n"); talloc_free(p2); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 1); + CHECK_BLOCKS("ref1", p1, 5); + CHECK_BLOCKS("ref1", p2, 1); + CHECK_BLOCKS("ref1", r1, 1); - printf("Freeing p1\n"); + fprintf(stderr, "Freeing p1\n"); talloc_free(p1); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(r1, 1); + CHECK_BLOCKS("ref1", r1, 1); - printf("Freeing r1\n"); + fprintf(stderr, "Freeing r1\n"); talloc_free(r1); - talloc_report_full(NULL, stdout); + talloc_report_full(NULL, stderr); - printf("Testing NULL\n"); + fprintf(stderr, "Testing NULL\n"); if (talloc_reference(root, NULL)) { return false; } - CHECK_BLOCKS(root, 1); + CHECK_BLOCKS("ref1", root, 1); - CHECK_SIZE(root, 0); + CHECK_SIZE("ref1", root, 0); talloc_free(root); - + printf("success: ref1\n"); return true; } @@ -152,8 +163,7 @@ static bool test_ref2(void) { void *root, *p1, *p2, *ref, *r1; - printf("TESTING DOUBLE REFERENCE FREE\n"); - + printf("test: ref2 [\nDOUBLE REFERENCE FREE\n]\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "p1"); talloc_named_const(p1, 1, "x1"); @@ -163,41 +173,41 @@ static bool test_ref2(void) r1 = talloc_named_const(root, 1, "r1"); ref = talloc_reference(r1, p2); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 2); + CHECK_BLOCKS("ref2", p1, 5); + CHECK_BLOCKS("ref2", p2, 1); + CHECK_BLOCKS("ref2", r1, 2); - printf("Freeing ref\n"); + fprintf(stderr, "Freeing ref\n"); talloc_free(ref); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 1); + CHECK_BLOCKS("ref2", p1, 5); + CHECK_BLOCKS("ref2", p2, 1); + CHECK_BLOCKS("ref2", r1, 1); - printf("Freeing p2\n"); + fprintf(stderr, "Freeing p2\n"); talloc_free(p2); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p1, 4); - CHECK_BLOCKS(r1, 1); + CHECK_BLOCKS("ref2", p1, 4); + CHECK_BLOCKS("ref2", r1, 1); - printf("Freeing p1\n"); + fprintf(stderr, "Freeing p1\n"); talloc_free(p1); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(r1, 1); + CHECK_BLOCKS("ref2", r1, 1); - printf("Freeing r1\n"); + fprintf(stderr, "Freeing r1\n"); talloc_free(r1); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_SIZE(root, 0); + CHECK_SIZE("ref2", root, 0); talloc_free(root); - + printf("success: ref2\n"); return true; } @@ -208,34 +218,35 @@ static bool test_ref3(void) { void *root, *p1, *p2, *ref, *r1; - printf("TESTING PARENT REFERENCE FREE\n"); + printf("test: ref3 [\nPARENT REFERENCE FREE\n]\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "p1"); p2 = talloc_named_const(root, 1, "p2"); r1 = talloc_named_const(p1, 1, "r1"); ref = talloc_reference(p2, r1); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p1, 2); - CHECK_BLOCKS(p2, 2); - CHECK_BLOCKS(r1, 1); + CHECK_BLOCKS("ref3", p1, 2); + CHECK_BLOCKS("ref3", p2, 2); + CHECK_BLOCKS("ref3", r1, 1); - printf("Freeing p1\n"); + fprintf(stderr, "Freeing p1\n"); talloc_free(p1); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p2, 2); - CHECK_BLOCKS(r1, 1); + CHECK_BLOCKS("ref3", p2, 2); + CHECK_BLOCKS("ref3", r1, 1); - printf("Freeing p2\n"); + fprintf(stderr, "Freeing p2\n"); talloc_free(p2); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_SIZE(root, 0); + CHECK_SIZE("ref3", root, 0); talloc_free(root); + printf("success: ref3\n"); return true; } @@ -246,7 +257,7 @@ static bool test_ref4(void) { void *root, *p1, *p2, *ref, *r1; - printf("TESTING REFERRER REFERENCE FREE\n"); + printf("test: ref4 [\nREFERRER REFERENCE FREE\n]\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "p1"); @@ -257,33 +268,34 @@ static bool test_ref4(void) r1 = talloc_named_const(root, 1, "r1"); ref = talloc_reference(r1, p2); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 2); + CHECK_BLOCKS("ref4", p1, 5); + CHECK_BLOCKS("ref4", p2, 1); + CHECK_BLOCKS("ref4", r1, 2); - printf("Freeing r1\n"); + fprintf(stderr, "Freeing r1\n"); talloc_free(r1); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p1, 5); - CHECK_BLOCKS(p2, 1); + CHECK_BLOCKS("ref4", p1, 5); + CHECK_BLOCKS("ref4", p2, 1); - printf("Freeing p2\n"); + fprintf(stderr, "Freeing p2\n"); talloc_free(p2); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p1, 4); + CHECK_BLOCKS("ref4", p1, 4); - printf("Freeing p1\n"); + fprintf(stderr, "Freeing p1\n"); talloc_free(p1); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_SIZE(root, 0); + CHECK_SIZE("ref4", root, 0); talloc_free(root); + printf("success: ref4\n"); return true; } @@ -295,7 +307,7 @@ static bool test_unlink1(void) { void *root, *p1, *p2, *ref, *r1; - printf("TESTING UNLINK\n"); + printf("test: unlink [\nUNLINK\n]\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "p1"); @@ -306,28 +318,29 @@ static bool test_unlink1(void) r1 = talloc_named_const(p1, 1, "r1"); ref = talloc_reference(r1, p2); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p1, 7); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 2); + CHECK_BLOCKS("unlink", p1, 7); + CHECK_BLOCKS("unlink", p2, 1); + CHECK_BLOCKS("unlink", r1, 2); - printf("Unreferencing r1\n"); + fprintf(stderr, "Unreferencing r1\n"); talloc_unlink(r1, p2); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_BLOCKS(p1, 6); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(r1, 1); + CHECK_BLOCKS("unlink", p1, 6); + CHECK_BLOCKS("unlink", p2, 1); + CHECK_BLOCKS("unlink", r1, 1); - printf("Freeing p1\n"); + fprintf(stderr, "Freeing p1\n"); talloc_free(p1); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); - CHECK_SIZE(root, 0); + CHECK_SIZE("unlink", root, 0); talloc_free(root); + printf("success: unlink\n"); return true; } @@ -346,183 +359,146 @@ static bool test_misc(void) double *d; const char *name; - printf("TESTING MISCELLANEOUS\n"); + printf("test: misc [\nMISCELLANEOUS\n]\n"); root = talloc_new(NULL); p1 = talloc_size(root, 0x7fffffff); - if (p1) { - printf("failed: large talloc allowed\n"); - return false; - } + torture_assert("misc", !p1, "failed: large talloc allowed\n"); 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); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); talloc_free(p1); - CHECK_BLOCKS(p1, 1); - CHECK_BLOCKS(root, 2); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); talloc_unlink(NULL, p1); - CHECK_BLOCKS(p1, 1); - CHECK_BLOCKS(root, 2); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); p2 = talloc_strdup(p1, "foo"); - if (talloc_unlink(root, p2) != -1) { - printf("failed: talloc_unlink() of non-reference context should return -1\n"); - return false; - } - if (talloc_unlink(p1, p2) != 0) { - printf("failed: talloc_unlink() of parent should succeed\n"); - return false; - } + torture_assert("misc", talloc_unlink(root, p2) == -1, + "failed: talloc_unlink() of non-reference context should return -1\n"); + torture_assert("misc", talloc_unlink(p1, p2) == 0, + "failed: talloc_unlink() of parent should succeed\n"); talloc_free(p1); - CHECK_BLOCKS(p1, 1); - CHECK_BLOCKS(root, 2); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); name = 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(my name is foo) - '%s'=>'%s'\n", - (name?name:"NULL"), talloc_get_name(p1)); - return false; - } - CHECK_BLOCKS(p1, 2); - CHECK_BLOCKS(root, 3); + torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo", + "failed: wrong name after talloc_set_name(my name is foo)"); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", 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) - '%s'\n", - talloc_get_name(p1)); - return false; - } - CHECK_BLOCKS(p1, 2); - CHECK_BLOCKS(root, 3); - + torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED", + "failed: wrong name after talloc_set_name(NULL)"); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); - if (talloc_free(NULL) != -1) { - printf("talloc_free(NULL) should give -1\n"); - return false; - } + torture_assert("misc", talloc_free(NULL) == -1, + "talloc_free(NULL) should give -1\n"); talloc_set_destructor(p1, fail_destructor); - if (talloc_free(p1) != -1) { - printf("Failed destructor should cause talloc_free to fail\n"); - return false; - } + torture_assert("misc", talloc_free(p1) == -1, + "Failed destructor should cause talloc_free to fail\n"); talloc_set_destructor(p1, NULL); - talloc_report(root, stdout); + talloc_report(root, stderr); p2 = (char *)talloc_zero_size(p1, 20); - if (p2[19] != 0) { - printf("Failed to give zero memory\n"); - return false; - } + torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n"); talloc_free(p2); - if (talloc_strdup(root, NULL) != NULL) { - printf("failed: strdup on NULL should give NULL\n"); - return false; - } + torture_assert("misc", talloc_strdup(root, NULL) == NULL, + "failed: strdup on NULL should give NULL\n"); p2 = talloc_strndup(p1, "foo", 2); - if (strcmp("fo", p2) != 0) { - printf("failed: strndup doesn't work\n"); - return false; - } + torture_assert("misc", strcmp("fo", p2) == 0, + "strndup doesn't work\n"); 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); + torture_assert("misc", strcmp("food", p2) == 0, + "talloc_asprintf_append doesn't work\n"); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", 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); + torture_assert("misc", strcmp("hello world", p2) == 0, + "talloc_asprintf_append doesn't work\n"); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 3); talloc_free(p2); d = talloc_array(p1, double, 0x20000000); - if (d) { - printf("failed: integer overflow not detected\n"); - return false; - } + torture_assert("misc", !d, "failed: integer overflow not detected\n"); d = talloc_realloc(p1, d, double, 0x20000000); - if (d) { - printf("failed: integer overflow not detected\n"); - return false; - } + torture_assert("misc", !d, "failed: integer overflow not detected\n"); talloc_free(p1); - CHECK_BLOCKS(root, 1); + CHECK_BLOCKS("misc", root, 1); p1 = talloc_named(root, 100, "%d bytes", 100); - CHECK_BLOCKS(p1, 2); - CHECK_BLOCKS(root, 3); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); talloc_unlink(root, p1); p1 = talloc_init("%d bytes", 200); p2 = talloc_asprintf(p1, "my test '%s'", "string"); - if (strcmp(p2, "my test 'string'") != 0) { - printf("failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"\n", p2); - return false; - } - CHECK_BLOCKS(p1, 3); - CHECK_SIZE(p2, 17); - CHECK_BLOCKS(root, 1); + torture_assert_str_equal("misc", p2, "my test 'string'", + "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\""); + CHECK_BLOCKS("misc", p1, 3); + CHECK_SIZE("misc", p2, 17); + CHECK_BLOCKS("misc", root, 1); talloc_unlink(NULL, p1); p1 = talloc_named_const(root, 10, "p1"); p2 = (char *)talloc_named_const(root, 20, "p2"); (void)talloc_reference(p1, p2); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); talloc_unlink(root, p2); - talloc_report_full(root, stdout); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(p1, 2); - CHECK_BLOCKS(root, 3); + talloc_report_full(root, stderr); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 2); + CHECK_BLOCKS("misc", root, 3); talloc_unlink(p1, p2); talloc_unlink(root, p1); p1 = talloc_named_const(root, 10, "p1"); p2 = (char *)talloc_named_const(root, 20, "p2"); (void)talloc_reference(NULL, p2); - talloc_report_full(root, stdout); + talloc_report_full(root, stderr); talloc_unlink(root, p2); - talloc_report_full(root, stdout); - CHECK_BLOCKS(p2, 1); - CHECK_BLOCKS(p1, 1); - CHECK_BLOCKS(root, 2); + talloc_report_full(root, stderr); + CHECK_BLOCKS("misc", p2, 1); + CHECK_BLOCKS("misc", p1, 1); + CHECK_BLOCKS("misc", root, 2); talloc_unlink(NULL, p2); talloc_unlink(root, p1); /* Test that talloc_unlink is a no-op */ - if (talloc_unlink(root, NULL) != -1) { - printf("failed: talloc_unlink(root, NULL) == -1\n"); - return false; - } + torture_assert("misc", talloc_unlink(root, NULL) == -1, + "failed: talloc_unlink(root, NULL) == -1\n"); - talloc_report(root, stdout); - talloc_report(NULL, stdout); + talloc_report(root, stderr); + talloc_report(NULL, stderr); - CHECK_SIZE(root, 0); + CHECK_SIZE("misc", root, 0); talloc_free(root); - CHECK_SIZE(NULL, 0); + CHECK_SIZE("misc", NULL, 0); talloc_enable_leak_report(); talloc_enable_leak_report_full(); + printf("success: misc\n"); + return true; } @@ -534,15 +510,15 @@ static bool test_realloc(void) { void *root, *p1, *p2; - printf("TESTING REALLOC\n"); + printf("test: realloc [\nREALLOC\n]\n"); root = talloc_new(NULL); p1 = talloc_size(root, 10); - CHECK_SIZE(p1, 10); + CHECK_SIZE("realloc", p1, 10); p1 = talloc_realloc_size(NULL, p1, 20); - CHECK_SIZE(p1, 20); + CHECK_SIZE("realloc", p1, 20); talloc_new(p1); @@ -552,36 +528,34 @@ static bool test_realloc(void) p2 = talloc_realloc_size(p1, p2, 40); - CHECK_SIZE(p2, 40); - CHECK_SIZE(root, 60); - CHECK_BLOCKS(p1, 4); + CHECK_SIZE("realloc", p2, 40); + CHECK_SIZE("realloc", root, 60); + CHECK_BLOCKS("realloc", p1, 4); p1 = talloc_realloc_size(NULL, p1, 20); - CHECK_SIZE(p1, 60); + CHECK_SIZE("realloc", p1, 60); talloc_increase_ref_count(p2); - if (talloc_realloc_size(NULL, p2, 5) != NULL) { - printf("failed: talloc_realloc() on a referenced pointer should fail\n"); - return false; - } - CHECK_BLOCKS(p1, 4); + torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL, + "failed: talloc_realloc() on a referenced pointer should fail\n"); + CHECK_BLOCKS("realloc", p1, 4); talloc_realloc_size(NULL, p2, 0); talloc_realloc_size(NULL, p2, 0); - CHECK_BLOCKS(p1, 3); + CHECK_BLOCKS("realloc", p1, 3); - if (talloc_realloc_size(NULL, p1, 0x7fffffff) != NULL) { - printf("failed: oversize talloc should fail\n"); - return false; - } + torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL, + "failed: oversize talloc should fail\n"); talloc_realloc_size(NULL, p1, 0); - CHECK_BLOCKS(root, 1); - CHECK_SIZE(root, 0); + CHECK_BLOCKS("realloc", root, 1); + CHECK_SIZE("realloc", root, 0); talloc_free(root); + printf("success: REALLOC\n"); + return true; } @@ -599,7 +573,7 @@ static bool test_realloc_child(void) struct el2 **list, **list2, **list3; } *el1; - printf("TESTING REALLOC WITH CHILD\n"); + printf("test: REALLOC WITH CHILD\n"); root = talloc_new(NULL); @@ -626,10 +600,10 @@ static bool test_realloc_child(void) talloc_free(root); + printf("success: REALLOC WITH CHILD\n"); return true; } - /* test type checking */ @@ -644,7 +618,7 @@ static bool test_type(void) }; struct el1 *el1; - printf("TESTING talloc type checking\n"); + printf("test: type [\ntalloc type checking\n]\n"); root = talloc_new(NULL); @@ -652,22 +626,17 @@ static bool test_type(void) el1->count = 1; - if (talloc_get_type(el1, struct el1) != el1) { - printf("type check failed on el1\n"); - return false; - } - if (talloc_get_type(el1, struct el2) != NULL) { - printf("type check failed on el1 with el2\n"); - return false; - } + torture_assert("type", talloc_get_type(el1, struct el1) == el1, + "type check failed on el1\n"); + torture_assert("type", talloc_get_type(el1, struct el2) == NULL, + "type check failed on el1 with el2\n"); talloc_set_type(el1, struct el2); - if (talloc_get_type(el1, struct el2) != (struct el2 *)el1) { - printf("type set failed on el1 with el2\n"); - return false; - } + torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1, + "type set failed on el1 with el2\n"); talloc_free(root); + printf("success: type\n"); return true; } @@ -678,51 +647,48 @@ static bool test_steal(void) { void *root, *p1, *p2; - printf("TESTING STEAL\n"); + printf("test: steal [\nSTEAL\n]\n"); root = talloc_new(NULL); p1 = talloc_array(root, char, 10); - CHECK_SIZE(p1, 10); + CHECK_SIZE("steal", p1, 10); p2 = talloc_realloc(root, NULL, char, 20); - CHECK_SIZE(p1, 10); - CHECK_SIZE(root, 30); + CHECK_SIZE("steal", p1, 10); + CHECK_SIZE("steal", root, 30); - if (talloc_steal(p1, NULL) != NULL) { - printf("failed: stealing NULL should give NULL\n"); - return false; - } + torture_assert("steal", talloc_steal(p1, NULL) == NULL, + "failed: stealing NULL should give NULL\n"); - 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); + torture_assert("steal", talloc_steal(p1, p1) == p1, + "failed: stealing to ourselves is a nop\n"); + CHECK_BLOCKS("steal", root, 3); + CHECK_SIZE("steal", root, 30); talloc_steal(NULL, p1); talloc_steal(NULL, p2); - CHECK_BLOCKS(root, 1); - CHECK_SIZE(root, 0); + CHECK_BLOCKS("steal", root, 1); + CHECK_SIZE("steal", root, 0); talloc_free(p1); talloc_steal(root, p2); - CHECK_BLOCKS(root, 2); - CHECK_SIZE(root, 20); + CHECK_BLOCKS("steal", root, 2); + CHECK_SIZE("steal", root, 20); talloc_free(p2); - CHECK_BLOCKS(root, 1); - CHECK_SIZE(root, 0); + CHECK_BLOCKS("steal", root, 1); + CHECK_SIZE("steal", root, 0); talloc_free(root); p1 = talloc_size(NULL, 3); - talloc_report_full(NULL, stdout); - CHECK_SIZE(NULL, 3); + talloc_report_full(NULL, stderr); + CHECK_SIZE("steal", NULL, 3); talloc_free(p1); + printf("success: steal\n"); return true; } @@ -736,7 +702,8 @@ static bool test_move(void) char *p; int *x; } *t1, *t2; - printf("TESTING MOVE\n"); + + printf("test: move [\nMOVE\n]\n"); root = talloc_new(NULL); @@ -748,15 +715,14 @@ static bool test_move(void) t2->p = talloc_move(t2, &t1->p); t2->x = talloc_move(t2, &t1->x); - if (t1->p != NULL || t1->x != NULL || - strcmp(t2->p, "foo") || - *t2->x != 42) { - printf("talloc move failed\n"); - return false; - } + torture_assert("move", t1->p == NULL && t1->x == NULL && + strcmp(t2->p, "foo") == 0 && *t2->x == 42, + "talloc move failed"); talloc_free(root); + printf("success: move\n"); + return true; } @@ -767,23 +733,23 @@ static bool test_realloc_fn(void) { void *root, *p1; - printf("TESTING talloc_realloc_fn\n"); + printf("test: realloc_fn [\ntalloc_realloc_fn\n]\n"); root = talloc_new(NULL); p1 = talloc_realloc_fn(root, NULL, 10); - CHECK_BLOCKS(root, 2); - CHECK_SIZE(root, 10); + CHECK_BLOCKS("realloc_fn", root, 2); + CHECK_SIZE("realloc_fn", root, 10); p1 = talloc_realloc_fn(root, p1, 20); - CHECK_BLOCKS(root, 2); - CHECK_SIZE(root, 20); + CHECK_BLOCKS("realloc_fn", root, 2); + CHECK_SIZE("realloc_fn", root, 20); p1 = talloc_realloc_fn(root, p1, 0); - CHECK_BLOCKS(root, 1); - CHECK_SIZE(root, 0); + CHECK_BLOCKS("realloc_fn", root, 1); + CHECK_SIZE("realloc_fn", root, 0); talloc_free(root); - + printf("success: realloc_fn\n"); return true; } @@ -792,7 +758,7 @@ static bool test_unref_reparent(void) { void *root, *p1, *p2, *c1; - printf("TESTING UNREFERENCE AFTER PARENT FREED\n"); + printf("test: unref_reparent [\nUNREFERENCE AFTER PARENT FREED\n]\n"); root = talloc_named_const(NULL, 0, "root"); p1 = talloc_named_const(root, 1, "orig parent"); @@ -801,19 +767,20 @@ static bool test_unref_reparent(void) c1 = talloc_named_const(p1, 1, "child"); talloc_reference(p2, c1); - CHECK_PARENT(c1, p1); + CHECK_PARENT("unref_reparent", c1, p1); talloc_free(p1); - CHECK_PARENT(c1, p2); + CHECK_PARENT("unref_reparent", c1, p2); talloc_unlink(p2, c1); - CHECK_SIZE(root, 1); + CHECK_SIZE("unref_reparent", root, 1); talloc_free(p2); talloc_free(root); + printf("success: unref_reparent\n"); return true; } @@ -824,22 +791,26 @@ static bool test_speed(void) { void *ctx = talloc_new(NULL); unsigned count; + const int loop = 1000; + int i; struct timeval tv; - printf("MEASURING TALLOC VS MALLOC SPEED\n"); + printf("test: speed [\nTALLOC VS MALLOC SPEED\n]\n"); tv = timeval_current(); count = 0; do { void *p1, *p2, *p3; - p1 = talloc_size(ctx, count); - p2 = talloc_strdup(p1, "foo bar"); - p3 = talloc_size(p1, 300); - talloc_free(p1); - count += 3; + for (i=0;i<loop;i++) { + p1 = talloc_size(ctx, loop % 100); + p2 = talloc_strdup(p1, "foo bar"); + p3 = talloc_size(p1, 300); + talloc_free(p1); + } + count += 3 * loop; } while (timeval_elapsed(&tv) < 5.0); - printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); + fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); talloc_free(ctx); @@ -847,41 +818,44 @@ static bool test_speed(void) count = 0; do { void *p1, *p2, *p3; - p1 = malloc(count); - p2 = strdup("foo bar"); - p3 = malloc(300); - free(p1); - free(p2); - free(p3); - count += 3; + for (i=0;i<loop;i++) { + p1 = malloc(loop % 100); + p2 = strdup("foo bar"); + p3 = malloc(300); + free(p1); + free(p2); + free(p3); + } + count += 3 * loop; } while (timeval_elapsed(&tv) < 5.0); + fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); - printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv)); + printf("success: speed\n"); - return true; + return true; } - static bool test_lifeless(void) { void *top = talloc_new(NULL); char *parent, *child; void *child_owner = talloc_new(NULL); - printf("TESTING TALLOC_UNLINK LOOP\n"); + printf("test: lifeless [\nTALLOC_UNLINK LOOP\n]\n"); parent = talloc_strdup(top, "parent"); child = talloc_strdup(parent, "child"); (void)talloc_reference(child, parent); (void)talloc_reference(child_owner, child); - talloc_report_full(top, stdout); + talloc_report_full(top, stderr); talloc_unlink(top, parent); talloc_free(child); - talloc_report_full(top, stdout); + talloc_report_full(top, stderr); talloc_free(top); talloc_free(child_owner); talloc_free(child); + printf("success: lifeless\n"); return true; } @@ -889,7 +863,6 @@ static int loop_destructor_count; static int test_loop_destructor(char *ptr) { - printf("loop destructor\n"); loop_destructor_count++; return 0; } @@ -902,25 +875,25 @@ static bool test_loop(void) char *req2, *req3; } *req1; - printf("TESTING TALLOC LOOP DESTRUCTION\n"); + printf("test: loop [\nTALLOC LOOP DESTRUCTION\n]\n"); + parent = talloc_strdup(top, "parent"); req1 = talloc(parent, struct req1); req1->req2 = talloc_strdup(req1, "req2"); talloc_set_destructor(req1->req2, test_loop_destructor); req1->req3 = talloc_strdup(req1, "req3"); (void)talloc_reference(req1->req3, req1); - talloc_report_full(top, stdout); + talloc_report_full(top, stderr); talloc_free(parent); - talloc_report_full(top, stdout); - talloc_report_full(NULL, stdout); + talloc_report_full(top, stderr); + talloc_report_full(NULL, stderr); talloc_free(top); - if (loop_destructor_count != 1) { - printf("FAILED TO FIRE LOOP DESTRUCTOR\n"); - return false; - } + torture_assert("loop", loop_destructor_count == 1, + "FAILED TO FIRE LOOP DESTRUCTOR\n"); loop_destructor_count = 0; + printf("success: loop\n"); return true; } @@ -936,7 +909,8 @@ static bool test_free_parent_deny_child(void) char *level2; char *level3; - printf("TESTING TALLOC FREE PARENT DENY CHILD\n"); + printf("test: free_parent_deny_child [\nTALLOC FREE PARENT DENY CHILD\n]\n"); + level1 = talloc_strdup(top, "level1"); level2 = talloc_strdup(level1, "level2"); level3 = talloc_strdup(level2, "level3"); @@ -945,16 +919,16 @@ static bool test_free_parent_deny_child(void) talloc_free(level1); talloc_set_destructor(level3, NULL); - CHECK_PARENT(level3, top); + CHECK_PARENT("free_parent_deny_child", level3, top); talloc_free(top); + printf("success: free_parent_deny_child\n"); return true; } static bool test_talloc_ptrtype(void) { - bool ret = true; void *top = talloc_new(NULL); struct struct1 { int foo; @@ -965,140 +939,123 @@ static bool test_talloc_ptrtype(void) const char *location3; const char *location4; - printf("TESTING TALLOC PTRTYPE\n"); + printf("test: ptrtype [\nTALLOC PTRTYPE\n]\n"); + s1 = talloc_ptrtype(top, s1);location1 = __location__; if (talloc_get_size(s1) != sizeof(struct struct1)) { - printf("%s: talloc_ptrtype() allocated the wrong size %lu " - "(should be %lu)\n", - __location__, (unsigned long)talloc_get_size(s1), - (unsigned long)sizeof(struct struct1)); - ret = false; + printf("failure: ptrtype [\n" + "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n" + "]\n", (unsigned long)talloc_get_size(s1), + (unsigned long)sizeof(struct struct1)); + return false; } if (strcmp(location1, talloc_get_name(s1)) != 0) { - printf("%s: talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n", - __location__, talloc_get_name(s1), location1); - ret = false; + printf("failure: ptrtype [\n" + "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n", + talloc_get_name(s1), location1); + return false; } s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__; if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) { - printf("%s: talloc_array_ptrtype() allocated the wrong size " - "%lu (should be %lu)\n", - __location__, (unsigned long)talloc_get_size(s2), - (unsigned long)(sizeof(struct struct1)*10)); - ret = false; + printf("failure: ptrtype [\n" + "talloc_array_ptrtype() allocated the wrong size " + "%lu (should be %lu)\n]\n", + (unsigned long)talloc_get_size(s2), + (unsigned long)(sizeof(struct struct1)*10)); + return false; } if (strcmp(location2, talloc_get_name(s2)) != 0) { - printf("%s: talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n", - __location__, talloc_get_name(s2), - location2); - ret = false; + printf("failure: ptrtype [\n" + "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n", + talloc_get_name(s2), location2); + return false; } s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__; if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) { - printf("%s: talloc_array_ptrtype() allocated the wrong size " - "%lu (should be %lu)\n", - __location__, (unsigned long)talloc_get_size(s3), + printf("failure: ptrtype [\n" + "talloc_array_ptrtype() allocated the wrong size " + "%lu (should be %lu)\n]\n", + (unsigned long)talloc_get_size(s3), (unsigned long)(sizeof(struct struct1 *)*10)); - ret = false; + return false; } - if (strcmp(location3, talloc_get_name(s3)) != 0) { - printf("%s: talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n", - __location__, talloc_get_name(s3), location3); - ret = false; - } + torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3), + "talloc_array_ptrtype() sets the wrong name"); s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__; if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) { - printf("%s: talloc_array_ptrtype() allocated the wrong size " - "%lu (should be %lu)\n", - __location__, (unsigned long)talloc_get_size(s4), + printf("failure: TALLOC PTRTYPE [\n" + "talloc_array_ptrtype() allocated the wrong size " + "%lu (should be %lu)\n]\n", + (unsigned long)talloc_get_size(s4), (unsigned long)(sizeof(struct struct1 **)*10)); - ret = false; + return false; } - if (strcmp(location4, talloc_get_name(s4)) != 0) { - printf("%s: talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n", - __location__, talloc_get_name(s4), location4); - ret = false; - } + torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4), + "talloc_array_ptrtype() sets the wrong name"); talloc_free(top); - return ret; + printf("success: ptrtype\n"); + return true; } static bool test_autofree(void) { -#if _SAMBA_BUILD_>=4 - /* - * we can't run this inside smbtorture in samba4 - * as smbtorture uses talloc_autofree_context() - */ - printf("SKIPPING TALLOC AUTOFREE CONTEXT (not supported from smbtorture)\n"); -#else void *p; - - printf("TESTING TALLOC AUTOFREE CONTEXT\n"); + printf("test: autofree [\nTALLOC AUTOFREE CONTEXT\n]\n"); p = talloc_autofree_context(); talloc_free(p); p = talloc_autofree_context(); talloc_free(p); -#endif + + printf("success: autofree\n"); return true; } -bool torture_local_talloc(struct torture_context *torture) +int main(void) { bool ret = true; talloc_disable_null_tracking(); talloc_enable_null_tracking(); - ret = ret && test_ref1(); - ret = ret && test_ref2(); - ret = ret && test_ref3(); - ret = ret && test_ref4(); - ret = ret && test_unlink1(); - ret = ret && test_misc(); - ret = ret && test_realloc(); - ret = ret && test_realloc_child(); - ret = ret && test_steal(); - ret = ret && test_move(); - ret = ret && test_unref_reparent(); - ret = ret && test_realloc_fn(); - ret = ret && test_type(); - ret = ret && test_lifeless(); - ret = ret && test_loop(); - ret = ret && test_free_parent_deny_child(); - ret = ret && test_talloc_ptrtype(); + ret &= test_ref1(); + ret &= test_ref2(); + ret &= test_ref3(); + ret &= test_ref4(); + ret &= test_unlink1(); + ret &= test_misc(); + ret &= test_realloc(); + ret &= test_realloc_child(); + ret &= test_steal(); + ret &= test_move(); + ret &= test_unref_reparent(); + ret &= test_realloc_fn(); + ret &= test_type(); + ret &= test_lifeless(); + ret &= test_loop(); + ret &= test_free_parent_deny_child(); + ret &= test_talloc_ptrtype(); + if (ret) { - ret = ret && test_speed(); + ret &= test_speed(); } - ret = ret && test_autofree(); - - return ret; -} + ret &= test_autofree(); - - -#if _SAMBA_BUILD_<4 - int main(void) -{ - if (!torture_local_talloc(NULL)) { - printf("ERROR: TESTSUITE FAILED\n"); + if (!ret) return -1; - } return 0; } -#endif |