Merged revisions 376575 via svnmerge from

file:///srv/subversion/repos/asterisk/trunk

........
  r376575 | rmudgett | 2012-11-21 12:33:16 -0600 (Wed, 21 Nov 2012) | 20 lines
  
  Add red-black tree container type to astobj2.
  
  * Add red-black tree container type.
  
  * Add CLI command "astobj2 container dump <name>"
  
  * Added ao2_container_dump() so the container could be dumped by other
  modules for debugging purposes.
  
  * Changed ao2_container_stats() so it can be used by other modules like
  ao2_container_check() for debugging purposes.
  
  * Updated the unit tests to check red-black tree containers.
  
  (closes issue ASTERISK-19970)
  Reported by: rmudgett
  Tested by: rmudgett
  
  Review: https://reviewboard.asterisk.org/r/2110/
........


git-svn-id: https://origsvn.digium.com/svn/asterisk/team/mmichelson/threadpool@376580 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/78/78/1
Automerge script 13 years ago
parent b362853a32
commit d16d0200d2

@ -2774,6 +2774,10 @@ static int replace_callno(const void *obj)
static int callno_hash(const void *obj, const int flags)
{
/*
* XXX A hash function should always return the same value for
* the same inputs.
*/
return abs(ast_random());
}
@ -2781,6 +2785,15 @@ static int create_callno_pools(void)
{
uint16_t i;
/*!
* \todo XXX A different method of randomly picking an available
* IAX2 callno needs to be devised.
*
* A hash function should always return the same value for the
* same inputs. This game with the hash function prevents
* astob2.c from generically checking the integrity of hash
* containers while the system runs.
*/
if (!(callno_pool = ao2_container_alloc(CALLNO_POOL_BUCKETS, callno_hash, NULL))) {
return -1;
}

@ -872,6 +872,10 @@ enum search_flags {
* not found in the starting bucket defined by the hash value on
* the argument.
*
* For rbtree containers, if the search key is not in the
* container, the search will start either at the first item
* before the search key or the first item after the search key.
*
* \note The supplied ao2_callback_fn is called for every node
* in the container from the starting point.
*/
@ -932,6 +936,24 @@ enum search_flags {
OBJ_ORDER_ASCENDING = (0 << 8),
/*! \brief Traverse in descending order (Last to first container object) */
OBJ_ORDER_DESCENDING = (1 << 8),
/*!
* \brief Traverse in pre-order (Node then children, for tree container)
*
* \note For non-tree containers, it is up to the container type
* to make the best interpretation of the order. For list and
* hash containers, this also means ascending order because a
* binary tree can degenerate into a list.
*/
OBJ_ORDER_PRE = (2 << 8),
/*!
* \brief Traverse in post-order (Children then node, for tree container)
*
* \note For non-tree containers, it is up to the container type
* to make the best interpretation of the order. For list and
* hash containers, this also means descending order because a
* binary tree can degenerate into a list.
*/
OBJ_ORDER_POST = (3 << 8),
};
/*!
@ -1184,6 +1206,49 @@ struct ao2_container *__ao2_container_alloc_list_debug(unsigned int ao2_options,
unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
const char *tag, const char *file, int line, const char *func, int ref_debug);
/*!
* \brief Allocate and initialize a red-black tree container.
*
* \param ao2_options Container ao2 object options (See enum ao2_alloc_opts)
* \param container_options Container behaviour options (See enum ao2_container_opts)
* \param sort_fn Pointer to a sort function.
* \param cmp_fn Pointer to a compare function used by ao2_find. (NULL to match everything)
* \param tag used for debugging.
*
* \return A pointer to a struct container.
*
* \note Destructor is set implicitly.
*/
#if defined(REF_DEBUG)
#define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \
__ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
#define ao2_container_alloc_rbtree(ao2_options, container_options, , sort_fn, cmp_fn) \
__ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
#elif defined(__AST_DEBUG_MALLOC)
#define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \
__ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn) \
__ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
#else
#define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \
__ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn))
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn) \
__ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn))
#endif
struct ao2_container *__ao2_container_alloc_rbtree(unsigned int ao2_options, unsigned int container_options,
ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn);
struct ao2_container *__ao2_container_alloc_rbtree_debug(unsigned int ao2_options, unsigned int container_options,
ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
const char *tag, const char *file, int line, const char *func, int ref_debug);
/*! \brief
* Returns the number of elements in a container.
*/
@ -1241,6 +1306,58 @@ struct ao2_container *__ao2_container_clone_debug(struct ao2_container *orig, en
#endif
/*!
* \brief Print output.
* \since 12.0.0
*
* \param where User data pointer needed to determine where to put output.
* \param fmt printf type format string.
*
* \return Nothing
*/
typedef void (ao2_prnt_fn)(void *where, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
/*!
* \brief Print object key.
* \since 12.0.0
*
* \param v_obj A pointer to the object we want the key printed.
* \param where User data needed by prnt to determine where to put output.
* \param prnt Print output callback function to use.
*
* \return Nothing
*/
typedef void (ao2_prnt_obj_fn)(void *v_obj, void *where, ao2_prnt_fn *prnt);
/*!
* \brief Display contents of the specified container.
* \since 12.0.0
*
* \param self Container to dump.
* \param flags OBJ_NOLOCK if a lock is already held on the container.
* \param name Container name. (NULL if anonymous)
* \param where User data needed by prnt to determine where to put output.
* \param prnt Print output callback function to use.
* \param prnt_obj Callback function to print the given object's key. (NULL if not available)
*
* \return Nothing
*/
void ao2_container_dump(struct ao2_container *self, enum search_flags flags, const char *name, void *where, ao2_prnt_fn *prnt, ao2_prnt_obj_fn *prnt_obj);
/*!
* \brief Display statistics of the specified container.
* \since 12.0.0
*
* \param self Container to display statistics.
* \param flags OBJ_NOLOCK if a lock is already held on the container.
* \param name Container name. (NULL if anonymous)
* \param where User data needed by prnt to determine where to put output.
* \param prnt Print output callback function to use.
*
* \return Nothing
*/
void ao2_container_stats(struct ao2_container *self, enum search_flags flags, const char *name, void *where, ao2_prnt_fn *prnt);
/*!
* \brief Perform an integrity check on the specified container.
* \since 12.0.0
@ -1259,11 +1376,12 @@ int ao2_container_check(struct ao2_container *self, enum search_flags flags);
*
* \param name Name to register the container under.
* \param self Container to register.
* \param prnt_obj Callback function to print the given object's key. (NULL if not available)
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ao2_container_register(const char *name, struct ao2_container *self);
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj);
/*!
* \brief Unregister a container for CLI stats and integrity check.

@ -127,6 +127,7 @@
#define AST_TEST_REGISTER(cb)
#define AST_TEST_UNREGISTER(cb)
#define ast_test_status_update(a,b,c...)
#define ast_test_debug(test, fmt, ...) ast_cli /* Dummy function that should not be called. */
#endif
@ -255,6 +256,17 @@ int ast_test_unregister(ast_test_cb_t *cb);
*/
int ast_test_register(ast_test_cb_t *cb);
/*!
* \brief Unit test debug output.
* \since 12.0.0
*
* \param test Unit test control structure.
* \param fmt printf type format string.
*
* \return Nothing
*/
void ast_test_debug(struct ast_test *test, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
/*!
* \brief update test's status during testing.
*

File diff suppressed because it is too large Load Diff

@ -8596,6 +8596,27 @@ static const struct ast_data_entry channel_providers[] = {
AST_DATA_ENTRY("/asterisk/core/channeltypes", &channeltypes_provider),
};
/*!
* \internal
* \brief Print channel object key (name).
* \since 12.0.0
*
* \param v_obj A pointer to the object we want the key printed.
* \param where User data needed by prnt to determine where to put output.
* \param prnt Print output callback function to use.
*
* \return Nothing
*/
static void prnt_channel_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
{
struct ast_channel *chan = v_obj;
if (!chan) {
return;
}
prnt(where, "%s", ast_channel_name(chan));
}
static void channels_shutdown(void)
{
ast_data_unregister(NULL);
@ -8610,7 +8631,7 @@ void ast_channels_init(void)
channels = ao2_container_alloc(NUM_CHANNEL_BUCKETS,
ast_channel_hash_cb, ast_channel_cmp_cb);
if (channels) {
ao2_container_register("channels", channels);
ao2_container_register("channels", channels, prnt_channel_key);
}
ast_cli_register_multiple(cli_channel, ARRAY_LEN(cli_channel));

@ -100,6 +100,27 @@ static int test_insert(struct ast_test *test);
static struct ast_test *test_remove(ast_test_cb_t *cb);
static int test_cat_cmp(const char *cat1, const char *cat2);
void ast_test_debug(struct ast_test *test, const char *fmt, ...)
{
struct ast_str *buf = NULL;
va_list ap;
buf = ast_str_create(128);
if (!buf) {
return;
}
va_start(ap, fmt);
ast_str_set_va(&buf, 0, fmt, ap);
va_end(ap);
if (test->cli) {
ast_cli(test->cli->fd, "%s", ast_str_buffer(buf));
}
ast_free(buf);
}
int __ast_test_status_update(const char *file, const char *func, int line,
struct ast_test *test, const char *fmt, ...)
{

@ -37,9 +37,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/test.h"
#include "asterisk/astobj2.h"
/* Uncomment the following line to dump the container contents during tests. */
//#define TEST_CONTAINER_DEBUG_DUMP 1
enum test_container_type {
TEST_CONTAINER_LIST,
TEST_CONTAINER_HASH,
TEST_CONTAINER_RBTREE,
};
/*!
@ -63,6 +67,9 @@ static const char *test_container2str(enum test_container_type type)
case TEST_CONTAINER_HASH:
c_type = "Hash";
break;
case TEST_CONTAINER_RBTREE:
c_type = "RBTree";
break;
}
return c_type;
}
@ -199,6 +206,29 @@ static int test_sort_cb(const void *obj_left, const void *obj_right, int flags)
}
}
#if defined(TEST_CONTAINER_DEBUG_DUMP)
/*!
* \internal
* \brief Print test object key.
* \since 12.0.0
*
* \param v_obj A pointer to the object we want the key printed.
* \param where User data needed by prnt to determine where to put output.
* \param prnt Print output callback function to use.
*
* \return Nothing
*/
static void test_prnt_obj(void *v_obj, void *where, ao2_prnt_fn *prnt)
{
struct test_obj *obj = v_obj;
if (!obj) {
return;
}
prnt(where, "%6d-%d", obj->i, obj->dup_number);
}
#endif /* defined(TEST_CONTAINER_DEBUG_DUMP) */
/*!
* \internal
* \brief Test container cloning.
@ -457,6 +487,12 @@ static int astobj2_test_1_helper(int tst_num, enum test_container_type type, int
c1 = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, n_buckets,
test_hash_cb, use_sort ? test_sort_cb : NULL, test_cmp_cb, "test");
break;
case TEST_CONTAINER_RBTREE:
/* RBTrees just have one bucket. */
n_buckets = 1;
c1 = ao2_t_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
test_sort_cb, test_cmp_cb, "test");
break;
}
c2 = ao2_t_container_alloc(1, NULL, NULL, "test");
@ -467,27 +503,27 @@ static int astobj2_test_1_helper(int tst_num, enum test_container_type type, int
}
/* Create objects and link into container */
destructor_count = lim;
for (num = 0; num < lim; ++num) {
if (!(obj = ao2_t_alloc(sizeof(struct test_obj), test_obj_destructor, "making zombies"))) {
ast_test_status_update(test, "ao2_alloc failed.\n");
res = AST_TEST_FAIL;
goto cleanup;
}
++destructor_count;
obj->destructor_count = &destructor_count;
obj->i = num;
ao2_link(c1, obj);
ao2_t_ref(obj, -1, "test");
if (ao2_container_check(c1, 0)) {
ast_test_status_update(test, "container integrity check failed linking obj num:%d\n", num);
res = AST_TEST_FAIL;
goto cleanup;
}
if (ao2_container_count(c1) != num + 1) {
ast_test_status_update(test, "container did not link correctly\n");
res = AST_TEST_FAIL;
}
}
if (ao2_container_check(c1, 0)) {
ast_test_status_update(test, "container integrity check failed\n");
res = AST_TEST_FAIL;
goto cleanup;
}
ast_test_status_update(test, "%s container created: buckets: %d, items: %d\n",
c_type, n_buckets, lim);
@ -721,6 +757,10 @@ static int astobj2_test_1_helper(int tst_num, enum test_container_type type, int
ast_test_status_update(test, "container integrity check failed\n");
res = AST_TEST_FAIL;
}
#if defined(TEST_CONTAINER_DEBUG_DUMP)
ao2_container_dump(c1, 0, "test_1 c1", (void *) test, (ao2_prnt_fn *) ast_test_debug, test_prnt_obj);
ao2_container_stats(c1, 0, "test_1 c1", (void *) test, (ao2_prnt_fn *) ast_test_debug);
#endif /* defined(TEST_CONTAINER_DEBUG_DUMP) */
cleanup:
/* destroy containers */
@ -777,6 +817,10 @@ AST_TEST_DEFINE(astobj2_test_1)
return res;
}
if ((res = astobj2_test_1_helper(4, TEST_CONTAINER_RBTREE, 1, 1000, test)) == AST_TEST_FAIL) {
return res;
}
return res;
}
@ -1071,6 +1115,9 @@ static struct ao2_container *test_make_nonsorted(enum test_container_type type,
container = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, options, 5,
test_hash_cb, NULL, test_cmp_cb);
break;
case TEST_CONTAINER_RBTREE:
/* Container type must be sorted. */
break;
}
return container;
@ -1101,6 +1148,10 @@ static struct ao2_container *test_make_sorted(enum test_container_type type, int
container = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, options, 5,
test_hash_cb, test_sort_cb, test_cmp_cb, "test");
break;
case TEST_CONTAINER_RBTREE:
container = ao2_t_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_MUTEX, options,
test_sort_cb, test_cmp_cb, "test");
break;
}
return container;
@ -1142,6 +1193,11 @@ static int insert_test_vector(struct ao2_container *container, int *destroy_coun
obj->i = vector[idx];
ao2_link(container, obj);
ao2_t_ref(obj, -1, "test");
if (ao2_container_check(container, 0)) {
ast_test_status_update(test, "%s: Container integrity check failed linking vector[%d]:%d\n",
prefix, idx, vector[idx]);
return -1;
}
if (ao2_container_count(container) != idx + 1) {
ast_test_status_update(test,
@ -1150,10 +1206,6 @@ static int insert_test_vector(struct ao2_container *container, int *destroy_coun
return -1;
}
}
if (ao2_container_check(container, 0)) {
ast_test_status_update(test, "%s: Container integrity check failed\n", prefix);
return -1;
}
return 0;
}
@ -1214,6 +1266,15 @@ static int insert_test_duplicates(struct ao2_container *container, int *destroy_
} else {
ao2_t_ref(obj, -1, "test");
}
if (ao2_container_check(container, 0)) {
ast_test_status_update(test, "%s: Container integrity check failed linking num:%d dup:%d\n",
prefix, number, count);
if (obj_dup) {
ao2_t_ref(obj_dup, -1, "test");
}
return -1;
}
}
/* Add the duplicate object. */
@ -1221,7 +1282,8 @@ static int insert_test_duplicates(struct ao2_container *container, int *destroy_
ao2_t_ref(obj_dup, -1, "test");
if (ao2_container_check(container, 0)) {
ast_test_status_update(test, "%s: Container integrity check failed\n", prefix);
ast_test_status_update(test, "%s: Container integrity check failed linking obj_dup\n",
prefix);
return -1;
}
@ -1469,6 +1531,7 @@ static int test_traversal_nonsorted(int res, int tst_num, enum test_container_ty
/* Create container that inserts objects at the end. */
c1 = test_make_nonsorted(type, 0);
if (!c1) {
ast_test_status_update(test, "Container c1 creation failed.\n");
res = AST_TEST_FAIL;
goto test_cleanup;
}
@ -1480,6 +1543,7 @@ static int test_traversal_nonsorted(int res, int tst_num, enum test_container_ty
/* Create container that inserts objects at the beginning. */
c2 = test_make_nonsorted(type, AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN);
if (!c2) {
ast_test_status_update(test, "Container c2 creation failed.\n");
res = AST_TEST_FAIL;
goto test_cleanup;
}
@ -1520,6 +1584,8 @@ static int test_traversal_nonsorted(int res, int tst_num, enum test_container_ty
test_hash_begin_backward, ARRAY_LEN(test_hash_begin_backward),
"Iteration (descending, insert begin)", test);
break;
case TEST_CONTAINER_RBTREE:
break;
}
/* Check container traversal directions */
@ -1554,6 +1620,8 @@ static int test_traversal_nonsorted(int res, int tst_num, enum test_container_ty
test_hash_begin_backward, ARRAY_LEN(test_hash_begin_backward),
"Traversal (descending, insert begin)", test);
break;
case TEST_CONTAINER_RBTREE:
break;
}
/* Check traversal with OBJ_PARTIAL_KEY search range. */
@ -1580,6 +1648,8 @@ static int test_traversal_nonsorted(int res, int tst_num, enum test_container_ty
test_hash_partial_backward, ARRAY_LEN(test_hash_partial_backward),
"Traversal OBJ_PARTIAL_KEY (descending)", test);
break;
case TEST_CONTAINER_RBTREE:
break;
}
test_cleanup:
@ -1687,6 +1757,7 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
/* Create container that inserts duplicate objects after matching objects. */
c1 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW);
if (!c1) {
ast_test_status_update(test, "Container c1 creation failed.\n");
res = AST_TEST_FAIL;
goto test_cleanup;
}
@ -1698,6 +1769,7 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
/* Create container that inserts duplicate objects before matching objects. */
c2 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN | AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW);
if (!c2) {
ast_test_status_update(test, "Container c2 creation failed.\n");
res = AST_TEST_FAIL;
goto test_cleanup;
}
@ -1706,8 +1778,16 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
goto test_cleanup;
}
#if defined(TEST_CONTAINER_DEBUG_DUMP)
ao2_container_dump(c1, 0, "c1(DUPS_ALLOW)", (void *) test, (ao2_prnt_fn *) ast_test_debug, test_prnt_obj);
ao2_container_stats(c1, 0, "c1(DUPS_ALLOW)", (void *) test, (ao2_prnt_fn *) ast_test_debug);
ao2_container_dump(c2, 0, "c2(DUPS_ALLOW)", (void *) test, (ao2_prnt_fn *) ast_test_debug, test_prnt_obj);
ao2_container_stats(c2, 0, "c2(DUPS_ALLOW)", (void *) test, (ao2_prnt_fn *) ast_test_debug);
#endif /* defined(TEST_CONTAINER_DEBUG_DUMP) */
/* Check container iteration directions */
switch (type) {
case TEST_CONTAINER_RBTREE:
case TEST_CONTAINER_LIST:
res = test_ao2_iteration(res, c1, 0,
test_forward, ARRAY_LEN(test_forward),
@ -1728,6 +1808,7 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
/* Check container traversal directions */
switch (type) {
case TEST_CONTAINER_RBTREE:
case TEST_CONTAINER_LIST:
res = test_ao2_callback_traversal(res, c1, OBJ_ORDER_ASCENDING, NULL, NULL,
test_forward, ARRAY_LEN(test_forward),
@ -1750,6 +1831,7 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
partial = 6;
partial_key_match_range = 1;
switch (type) {
case TEST_CONTAINER_RBTREE:
case TEST_CONTAINER_LIST:
res = test_ao2_callback_traversal(res, c1, OBJ_PARTIAL_KEY | OBJ_ORDER_ASCENDING,
test_cmp_cb, &partial,
@ -1782,6 +1864,13 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
goto test_cleanup;
}
#if defined(TEST_CONTAINER_DEBUG_DUMP)
ao2_container_dump(c1, 0, "c1(DUPS_ALLOW) w/ dups", (void *) test, (ao2_prnt_fn *) ast_test_debug, test_prnt_obj);
ao2_container_stats(c1, 0, "c1(DUPS_ALLOW) w/ dups", (void *) test, (ao2_prnt_fn *) ast_test_debug);
ao2_container_dump(c2, 0, "c2(DUPS_ALLOW) w/ dups", (void *) test, (ao2_prnt_fn *) ast_test_debug, test_prnt_obj);
ao2_container_stats(c2, 0, "c2(DUPS_ALLOW) w/ dups", (void *) test, (ao2_prnt_fn *) ast_test_debug);
#endif /* defined(TEST_CONTAINER_DEBUG_DUMP) */
/* Check duplicates in containers that allow duplicates. */
res = test_expected_duplicates(res, c1, OBJ_ORDER_ASCENDING, duplicate_number,
test_dup_allow_forward, ARRAY_LEN(test_dup_allow_forward),
@ -1798,6 +1887,7 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
/* Create containers that reject duplicate keyed objects. */
c1 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT);
if (!c1) {
ast_test_status_update(test, "Container c1 creation failed.\n");
res = AST_TEST_FAIL;
goto test_cleanup;
}
@ -1811,6 +1901,7 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
}
c2 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN | AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT);
if (!c2) {
ast_test_status_update(test, "Container c2 creation failed.\n");
res = AST_TEST_FAIL;
goto test_cleanup;
}
@ -1839,6 +1930,7 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
/* Create containers that reject duplicate objects. */
c1 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT);
if (!c1) {
ast_test_status_update(test, "Container c1 creation failed.\n");
res = AST_TEST_FAIL;
goto test_cleanup;
}
@ -1852,6 +1944,7 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
}
c2 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN | AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT);
if (!c2) {
ast_test_status_update(test, "Container c2 creation failed.\n");
res = AST_TEST_FAIL;
goto test_cleanup;
}
@ -1880,6 +1973,7 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
/* Create container that replaces duplicate keyed objects. */
c1 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE);
if (!c1) {
ast_test_status_update(test, "Container c1 creation failed.\n");
res = AST_TEST_FAIL;
goto test_cleanup;
}
@ -1893,6 +1987,7 @@ static int test_traversal_sorted(int res, int tst_num, enum test_container_type
}
c2 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN | AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE);
if (!c2) {
ast_test_status_update(test, "Container c2 creation failed.\n");
res = AST_TEST_FAIL;
goto test_cleanup;
}
@ -1959,6 +2054,7 @@ AST_TEST_DEFINE(astobj2_test_4)
res = test_traversal_sorted(res, 3, TEST_CONTAINER_LIST, test);
res = test_traversal_sorted(res, 4, TEST_CONTAINER_HASH, test);
res = test_traversal_sorted(res, 5, TEST_CONTAINER_RBTREE, test);
return res;
}

Loading…
Cancel
Save