113    int *
i = (
int *) arg;
 
 
  124        int *
i = (
int *) arg;
 
  128        int *
i = (
int *) arg;
 
  130        return (*
i - partial_key_match_range <= cmp_obj->
i 
 
  152        const struct test_obj *hash_obj = obj;
 
 
  158static int test_sort_cb(
const void *obj_left, 
const void *obj_right, 
int flags)
 
  160    const struct test_obj *test_left = obj_left;
 
  163        const int *
i = obj_right;
 
  165        return test_left->
i - *
i;
 
  167        int *
i = (
int *) obj_right;
 
  169        if (*
i - partial_key_match_range <= test_left->
i 
  174        return test_left->
i - *
i;
 
  176        const struct test_obj *test_right = obj_right;
 
  178        return test_left->
i - test_right->
i;
 
 
  182#if defined(TEST_CONTAINER_DEBUG_DUMP) 
  192static void test_prnt_obj(
void *v_obj, 
void *where, 
ao2_prnt_fn *prnt)
 
  246                "Orig container has an object %p not in the clone container.\n", obj);
 
 
  283    for (num = 100; num--;) {
 
  287        obj = 
ao2_find(look_in, &tmp_obj, 0);
 
 
  322    for (num = 75; num--;) {
 
 
  360    for (num = 75; num--;) {
 
 
  400    for (num = 100; num--;) {
 
 
  435        tst_num, c_type, use_sort ? 
"sorted" : 
"non-sorted");
 
  446        n_buckets = (
ast_random() % ((lim / 4) + 1)) + 1;
 
  466    for (num = 0; num < lim; ++num) {
 
  489        c_type, n_buckets, lim);
 
  509    if (increment != lim) {
 
  517    if (increment != lim) {
 
  523    num = lim < 25 ? lim : 25;
 
  621#if defined(TEST_CONTAINER_DEBUG_DUMP) 
 
  652        info->name = 
"astobj2_test1";
 
  653        info->category = 
"/main/astobj2/";
 
  654        info->summary = 
"Test ao2 objects, containers, callbacks, and iterators";
 
  656            "Builds ao2_containers with various item numbers, bucket sizes, cmp and hash " 
  657            "functions. Runs a series of tests to manipulate the container using callbacks " 
  658            "and iterators.  Verifies expected behavior.";
 
 
  695    static const int NUM_OBJS = 5;
 
  701        info->name = 
"astobj2_test2";
 
  702        info->category = 
"/main/astobj2/";
 
  703        info->summary = 
"Test a certain scenario using ao2 iterators";
 
  705            "This test is aimed at testing for a specific regression that occurred. " 
  706            "Add some objects into a container.  Mix finds and iteration and make " 
  707            "sure that the iterator still sees all objects.";
 
  720    for (num = 1; num <= NUM_OBJS; num++) {
 
  752    if (num != NUM_OBJS) {
 
  762    tmp_obj.
i = NUM_OBJS;
 
  779    if (num != NUM_OBJS) {
 
  794            tmp_obj.
i = NUM_OBJS - 1;
 
  808    if (num != NUM_OBJS) {
 
 
  836        info->name = 
"astobj2_test3";
 
  837        info->category = 
"/main/astobj2/";
 
  838        info->summary = 
"Test global ao2 holder";
 
  840            "This test is to see if the global ao2 holder works as intended.";
 
  854    obj->
i = ++num_objects;
 
  872    obj->
i = ++num_objects;
 
  898    obj->
i = ++num_objects;
 
  929            "all destructors were not called, destructor count is %d\n",
 
  934            "Destructor was called too many times, destructor count is %d\n",
 
  941        ao2_t_ref(obj, -1, 
"Test cleanup external object 1");
 
  944        ao2_t_ref(obj2, -1, 
"Test cleanup external object 2");
 
  947        ao2_t_ref(obj3, -1, 
"Test cleanup external object 3");
 
 
 1043    for (idx = 0; idx < count; ++idx) {
 
 1049        if (destroy_counter) {
 
 1054        obj->
i = vector[idx];
 
 1059                prefix, idx, vector[idx]);
 
 1065                "%s: Unexpected container count.  Expected:%d Got:%d\n",
 
 
 1106    for (count = 0; count < 4; ++count) {
 
 1115        if (destroy_counter) {
 
 
 1171    const int *vector, 
int count, 
const char *
prefix, 
struct ast_test *
test)
 
 1186    for (idx = 0; idx < count; ++idx) {
 
 1193        if (vector[idx] != obj->
i) {
 
 1195                prefix, obj->
i, idx, vector[idx]);
 
 
 1232    const int *vector, 
int count, 
const char *
prefix, 
struct ast_test *
test)
 
 1245    for (idx = 0; idx < count; ++idx) {
 
 1252        if (vector[idx] != obj->
i) {
 
 1254                prefix, obj->
i, idx, vector[idx]);
 
 
 1289    const int *vector, 
int count, 
const char *
prefix, 
struct ast_test *
test)
 
 1302    for (idx = 0; idx < count; ++idx) {
 
 1324            "%s: Too many objects found.  Object %d, dup id %d\n",
 
 
 1351    int destructor_count = 0;
 
 1354    static const int test_initial[] = {
 
 1355        1, 0, 2, 6, 4, 7, 5, 3, 9, 8
 
 1359    static const int test_reverse[] = {
 
 1360        8, 9, 3, 5, 7, 4, 6, 2, 0, 1
 
 1362    static const int test_list_partial_forward[] = {
 
 1365    static const int test_list_partial_backward[] = {
 
 1370    static const int test_hash_end_forward[] = {
 
 1371        0, 5, 1, 6, 2, 7, 3, 8, 4, 9
 
 1373    static const int test_hash_end_backward[] = {
 
 1374        9, 4, 8, 3, 7, 2, 6, 1, 5, 0
 
 1376    static const int test_hash_begin_forward[] = {
 
 1377        5, 0, 6, 1, 7, 2, 8, 3, 9, 4
 
 1379    static const int test_hash_begin_backward[] = {
 
 1380        4, 9, 3, 8, 2, 7, 1, 6, 0, 5
 
 1382    static const int test_hash_partial_forward[] = {
 
 1385    static const int test_hash_partial_backward[] = {
 
 1421            "Iteration (ascending, insert end)", 
test);
 
 1424            "Iteration (descending, insert end)", 
test);
 
 1428            "Iteration (ascending, insert begin)", 
test);
 
 1431            "Iteration (descending, insert begin)", 
test);
 
 1435            test_hash_end_forward, 
ARRAY_LEN(test_hash_end_forward),
 
 1436            "Iteration (ascending, insert end)", 
test);
 
 1438            test_hash_end_backward, 
ARRAY_LEN(test_hash_end_backward),
 
 1439            "Iteration (descending, insert end)", 
test);
 
 1442            test_hash_begin_forward, 
ARRAY_LEN(test_hash_begin_forward),
 
 1443            "Iteration (ascending, insert begin)", 
test);
 
 1445            test_hash_begin_backward, 
ARRAY_LEN(test_hash_begin_backward),
 
 1446            "Iteration (descending, insert begin)", 
test);
 
 1457            "Traversal (ascending, insert end)", 
test);
 
 1460            "Traversal (descending, insert end)", 
test);
 
 1464            "Traversal (ascending, insert begin)", 
test);
 
 1467            "Traversal (descending, insert begin)", 
test);
 
 1471            test_hash_end_forward, 
ARRAY_LEN(test_hash_end_forward),
 
 1472            "Traversal (ascending, insert end)", 
test);
 
 1474            test_hash_end_backward, 
ARRAY_LEN(test_hash_end_backward),
 
 1475            "Traversal (descending, insert end)", 
test);
 
 1478            test_hash_begin_forward, 
ARRAY_LEN(test_hash_begin_forward),
 
 1479            "Traversal (ascending, insert begin)", 
test);
 
 1481            test_hash_begin_backward, 
ARRAY_LEN(test_hash_begin_backward),
 
 1482            "Traversal (descending, insert begin)", 
test);
 
 1495            test_list_partial_forward, 
ARRAY_LEN(test_list_partial_forward),
 
 1496            "Traversal OBJ_PARTIAL_KEY (ascending)", 
test);
 
 1499            test_list_partial_backward, 
ARRAY_LEN(test_list_partial_backward),
 
 1500            "Traversal OBJ_PARTIAL_KEY (descending)", 
test);
 
 1505            test_hash_partial_forward, 
ARRAY_LEN(test_hash_partial_forward),
 
 1506            "Traversal OBJ_PARTIAL_KEY (ascending)", 
test);
 
 1509            test_hash_partial_backward, 
ARRAY_LEN(test_hash_partial_backward),
 
 1510            "Traversal OBJ_PARTIAL_KEY (descending)", 
test);
 
 1525    if (destructor_count > 0) {
 
 1527            "all destructors were not called, destructor count is %d\n",
 
 1530    } 
else if (destructor_count < 0) {
 
 1532            "Destructor was called too many times, destructor count is %d\n",
 
 
 1557    int destructor_count = 0;
 
 1558    int duplicate_number = 100;
 
 1561    static const int test_initial[] = {
 
 1562        1, 0, 2, 6, 4, 7, 5, 3, 9, 8
 
 1566    static const int test_forward[] = {
 
 1567        0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 
 1570    static const int test_backward[] = {
 
 1571        9, 8, 7, 6, 5, 4, 3, 2, 1, 0
 
 1574    static const int test_partial_forward[] = {
 
 1577    static const int test_partial_backward[] = {
 
 1582    static const int test_hash_forward[] = {
 
 1583        0, 5, 1, 6, 2, 7, 3, 8, 4, 9
 
 1585    static const int test_hash_backward[] = {
 
 1586        9, 4, 8, 3, 7, 2, 6, 1, 5, 0
 
 1588    static const int test_hash_partial_forward[] = {
 
 1591    static const int test_hash_partial_backward[] = {
 
 1596    static const int test_dup_allow_forward[] = {
 
 1599    static const int test_dup_allow_backward[] = {
 
 1602    static const int test_dup_reject[] = {
 
 1605    static const int test_dup_obj_reject_forward[] = {
 
 1608    static const int test_dup_obj_reject_backward[] = {
 
 1611    static const int test_dup_replace[] = {
 
 1642#if defined(TEST_CONTAINER_DEBUG_DUMP) 
 1655            "Iteration (ascending)", 
test);
 
 1657            test_backward, 
ARRAY_LEN(test_backward),
 
 1658            "Iteration (descending)", 
test);
 
 1662            test_hash_forward, 
ARRAY_LEN(test_hash_forward),
 
 1663            "Iteration (ascending)", 
test);
 
 1665            test_hash_backward, 
ARRAY_LEN(test_hash_backward),
 
 1666            "Iteration (descending)", 
test);
 
 1676            "Traversal (ascending)", 
test);
 
 1678            test_backward, 
ARRAY_LEN(test_backward),
 
 1679            "Traversal (descending)", 
test);
 
 1683            test_hash_forward, 
ARRAY_LEN(test_hash_forward),
 
 1684            "Traversal (ascending, insert end)", 
test);
 
 1686            test_hash_backward, 
ARRAY_LEN(test_hash_backward),
 
 1687            "Traversal (descending)", 
test);
 
 1699            test_partial_forward, 
ARRAY_LEN(test_partial_forward),
 
 1700            "Traversal OBJ_PARTIAL_KEY (ascending)", 
test);
 
 1703            test_partial_backward, 
ARRAY_LEN(test_partial_backward),
 
 1704            "Traversal OBJ_PARTIAL_KEY (descending)", 
test);
 
 1709            test_hash_partial_forward, 
ARRAY_LEN(test_hash_partial_forward),
 
 1710            "Traversal OBJ_PARTIAL_KEY (ascending)", 
test);
 
 1713            test_hash_partial_backward, 
ARRAY_LEN(test_hash_partial_backward),
 
 1714            "Traversal OBJ_PARTIAL_KEY (descending)", 
test);
 
 1728#if defined(TEST_CONTAINER_DEBUG_DUMP) 
 1737        test_dup_allow_forward, 
ARRAY_LEN(test_dup_allow_forward),
 
 1738        "Duplicates (ascending, DUPS_ALLOW)", 
test);
 
 1740        test_dup_allow_backward, 
ARRAY_LEN(test_dup_allow_backward),
 
 1741        "Duplicates (descending, DUPS_ALLOW)", 
test);
 
 1780        test_dup_reject, 
ARRAY_LEN(test_dup_reject),
 
 1781        "Duplicates (ascending, DUPS_REJECT)", 
test);
 
 1783        test_dup_reject, 
ARRAY_LEN(test_dup_reject),
 
 1784        "Duplicates (descending, DUPS_REJECT)", 
test);
 
 1823        test_dup_obj_reject_forward, 
ARRAY_LEN(test_dup_obj_reject_forward),
 
 1824        "Duplicates (ascending, DUPS_OBJ_REJECT)", 
test);
 
 1826        test_dup_obj_reject_backward, 
ARRAY_LEN(test_dup_obj_reject_backward),
 
 1827        "Duplicates (descending, DUPS_OBJ_REJECT)", 
test);
 
 1866        test_dup_replace, 
ARRAY_LEN(test_dup_replace),
 
 1867        "Duplicates (ascending, DUPS_REPLACE)", 
test);
 
 1869        test_dup_replace, 
ARRAY_LEN(test_dup_replace),
 
 1870        "Duplicates (descending, DUPS_REPLACE)", 
test);
 
 1881    if (destructor_count > 0) {
 
 1883            "all destructors were not called, destructor count is %d\n",
 
 1886    } 
else if (destructor_count < 0) {
 
 1888            "Destructor was called too many times, destructor count is %d\n",
 
 
 1902        info->name = 
"astobj2_test4";
 
 1903        info->category = 
"/main/astobj2/";
 
 1904        info->summary = 
"Test container traversal/iteration";
 
 1906            "This test is to see if the container traversal/iteration works " 
 1907            "as intended for each supported container type.";
 
 
 1995    int reportcount = iterations / 5;
 
 1996    struct timeval start;
 
 1999    for (i = 1 ; i <= iterations && res == 
AST_TEST_PASS ; i++) {
 
 2000        if (i % reportcount == 0 && i != iterations) {
 
 
 2020#define ITERATIONS 25000 
 2022#define ITERATIONS 100000 
 2029        info->name = 
"astobj2_test_perf";
 
 2030        info->category = 
"/main/astobj2/perf/";
 
 2031        info->summary = 
"Test container performance";
 
 2033            "Runs container traversal tests.";
 
 
Asterisk main include file. File version handling, generic pbx functions.
#define ao2_t_ref(o, delta, tag)
#define ao2_iterator_next(iter)
#define AO2_GLOBAL_OBJ_STATIC(name)
Define a global object holder to be used to hold an ao2 object, statically initialized.
#define ao2_link(container, obj)
Add an object to a container.
@ AO2_ALLOC_OPT_LOCK_MUTEX
#define ao2_t_iterator_next(iter, tag)
int ao2_match_by_addr(void *obj, void *arg, int flags)
A common ao2_callback is one that matches by address.
int ao2_container_check(struct ao2_container *self, enum search_flags flags)
Perform an integrity check on the specified container.
#define ao2_t_global_obj_replace_unref(holder, obj, tag)
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag)
#define ao2_t_link(container, obj, tag)
void ao2_container_stats(struct ao2_container *self, enum search_flags flags, const char *name, void *where, ao2_prnt_fn *prnt)
Display statistics of the specified container.
int() ao2_callback_fn(void *obj, void *arg, int flags)
Type of a generic callback function.
@ AO2_ITERATOR_DESCENDING
#define ao2_find(container, arg, flags)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag)
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a red-black tree container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag)
#define ao2_t_unlink(container, obj, tag)
#define ao2_t_global_obj_replace(holder, obj, tag)
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)
Display contents of the specified container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
search_flags
Flags passed to ao2_callback_fn(), ao2_hash_fn(), and ao2_sort_fn() to modify behaviour.
@ OBJ_ORDER_DESCENDING
Traverse in descending order (Last to first container object)
@ OBJ_ORDER_ASCENDING
Traverse in ascending order (First to last container object)
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
#define ao2_alloc(data_size, destructor_fn)
#define ao2_t_global_obj_release(holder, tag)
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
#define ao2_t_global_obj_ref(holder, tag)
void() ao2_prnt_fn(void *where, const char *fmt,...)
Print output.
#define ao2_container_clone(orig, flags)
Create a clone/copy of the given container.
@ AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT
Reject duplicate objects in container.
@ AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN
Insert objects at the beginning of the container. (Otherwise it is the opposite; insert at the end....
@ AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW
Allow objects with duplicate keys in container.
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT
Reject objects with duplicate keys in container.
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE
Replace objects with duplicate keys in container.
static char prefix[MAX_PREFIX]
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
struct ao2_container * container
static void cleanup(void)
Clean up any old apps that we don't need any more.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
#define ast_test_debug(test, fmt,...)
#define AST_TEST_REGISTER(cb)
#define ast_test_status_update(a, b, c...)
#define AST_TEST_UNREGISTER(cb)
#define AST_TEST_DEFINE(hdr)
static enum ast_test_result_state test_performance(struct ast_test *test, enum test_container_type type, unsigned int copt)
static int insert_test_duplicates(struct ao2_container *container, int *destroy_counter, int number, const char *prefix, struct ast_test *test)
static int test_ao2_iteration(int res, struct ao2_container *container, enum ao2_iterator_flags flags, const int *vector, int count, const char *prefix, struct ast_test *test)
static void test_obj_destructor(void *v_obj)
static int test_traversal_sorted(int res, int tst_num, enum test_container_type type, struct ast_test *test)
static int multiple_cb(void *obj, void *arg, int flag)
static int test_ao2_find_w_OBJ_POINTER(int res, struct ao2_container *look_in, int limit, struct ast_test *test)
static int test_ao2_find_w_OBJ_PARTIAL_KEY(int res, struct ao2_container *look_in, int limit, struct ast_test *test)
int partial_key_match_range
static int test_expected_duplicates(int res, struct ao2_container *container, enum search_flags flags, int number, const int *vector, int count, const char *prefix, struct ast_test *test)
static int test_container_clone(int res, struct ao2_container *orig, struct ast_test *test)
static int test_ao2_find_w_no_flags(int res, struct ao2_container *look_in, int limit, struct ast_test *test)
static int test_hash_cb(const void *obj, const int flags)
static int test_ao2_find_w_OBJ_KEY(int res, struct ao2_container *look_in, int limit, struct ast_test *test)
static int test_cmp_cb(void *obj, void *arg, int flags)
static struct ao2_container * test_make_sorted(enum test_container_type type, int options)
static int all_but_one_cb(void *obj, void *arg, int flag)
static int test_traversal_nonsorted(int res, int tst_num, enum test_container_type type, struct ast_test *test)
static int test_ao2_callback_traversal(int res, struct ao2_container *container, enum search_flags flags, ao2_callback_fn *cmp_fn, void *arg, const int *vector, int count, const char *prefix, struct ast_test *test)
static int increment_cb(void *obj, void *arg, int flag)
static enum ast_test_result_state testloop(struct ast_test *test, enum test_container_type type, int copt, int iterations)
static int test_sort_cb(const void *obj_left, const void *obj_right, int flags)
static int load_module(void)
static int unload_module(void)
static const char * test_container2str(enum test_container_type type)
static int astobj2_test_1_helper(int tst_num, enum test_container_type type, int use_sort, unsigned int lim, struct ast_test *test)
static int insert_test_vector(struct ao2_container *container, int *destroy_counter, const int *vector, int count, const char *prefix, struct ast_test *test)
static struct ao2_container * test_make_nonsorted(enum test_container_type type, int options)
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
long int ast_random(void)