Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Macros | Enumerations | Functions | Variables
test_astobj2.c File Reference

astobj2 test module More...

#include "asterisk.h"
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/test.h"
#include "asterisk/astobj2.h"

Go to the source code of this file.

Data Structures

struct  test_obj
 

Macros

#define ITERATIONS   100000
 
#define OBJS   73
 

Enumerations

enum  test_container_type { TEST_CONTAINER_LIST, TEST_CONTAINER_HASH, TEST_CONTAINER_RBTREE }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int all_but_one_cb (void *obj, void *arg, int flag)
 
static AO2_GLOBAL_OBJ_STATIC (astobj2_holder)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (astobj2_test_1)
 
 AST_TEST_DEFINE (astobj2_test_2)
 
 AST_TEST_DEFINE (astobj2_test_3)
 
 AST_TEST_DEFINE (astobj2_test_4)
 
 AST_TEST_DEFINE (astobj2_test_perf)
 
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 increment_cb (void *obj, void *arg, int flag)
 
static int insert_test_duplicates (struct ao2_container *container, int *destroy_counter, int number, const char *prefix, 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 int load_module (void)
 
static int multiple_cb (void *obj, void *arg, int flag)
 
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 test_ao2_find_w_no_flags (int res, struct ao2_container *look_in, int limit, struct ast_test *test)
 
static int test_ao2_find_w_OBJ_KEY (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)
 
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_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 int test_cmp_cb (void *obj, void *arg, int flags)
 
static const char * test_container2str (enum test_container_type type)
 
static int test_container_clone (int res, struct ao2_container *orig, struct ast_test *test)
 
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_hash_cb (const void *obj, const int flags)
 
static struct ao2_containertest_make_nonsorted (enum test_container_type type, int options)
 
static struct ao2_containertest_make_sorted (enum test_container_type type, int options)
 
static void test_obj_destructor (void *v_obj)
 
static enum ast_test_result_state test_performance (struct ast_test *test, enum test_container_type type, unsigned int copt)
 
static int test_sort_cb (const void *obj_left, const void *obj_right, int flags)
 
static int test_traversal_nonsorted (int res, int tst_num, enum test_container_type type, struct ast_test *test)
 
static int test_traversal_sorted (int res, int tst_num, enum test_container_type type, struct ast_test *test)
 
static enum ast_test_result_state testloop (struct ast_test *test, enum test_container_type type, int copt, int iterations)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "ASTOBJ2 Unit Tests" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
int partial_key_match_range
 

Detailed Description

astobj2 test module

Author
David Vossel dvoss.nosp@m.el@d.nosp@m.igium.nosp@m..com

Definition in file test_astobj2.c.

Function Documentation

AST_TEST_DEFINE ( astobj2_test_perf  )

The number of iteration of testloop to be performed.

Note
In order to keep the elapsed time sane, if AO2_DEBUG is defined in menuselect, only 25000 iterations are performed. Otherwise 100000.

Definition at line 2011 of file test_astobj2.c.

2012 {
2013 /*!
2014  * \brief The number of iteration of testloop to be performed.
2015  * \note
2016  * In order to keep the elapsed time sane, if AO2_DEBUG is defined in menuselect,
2017  * only 25000 iterations are performed. Otherwise 100000.
2018  */
2019 #ifdef AO2_DEBUG
2020 #define ITERATIONS 25000
2021 #else
2022 #define ITERATIONS 100000
2023 #endif
2024 
2025  int res = AST_TEST_PASS;
2026 
2027  switch (cmd) {
2028  case TEST_INIT:
2029  info->name = "astobj2_test_perf";
2030  info->category = "/main/astobj2/perf/";
2031  info->summary = "Test container performance";
2032  info->description =
2033  "Runs container traversal tests.";
2034  return AST_TEST_NOT_RUN;
2035  case TEST_EXECUTE:
2036  break;
2037  }
2038 
2039  res = testloop(test, TEST_CONTAINER_LIST, 0, ITERATIONS);
2040  if (!res) {
2041  return res;
2042  }
2043  res = testloop(test, TEST_CONTAINER_HASH, 0, ITERATIONS);
2044  if (!res) {
2045  return res;
2046  }
2047  res = testloop(test, TEST_CONTAINER_RBTREE, 0, ITERATIONS);
2048 
2049  return res;
2050 }
static enum ast_test_result_state test_performance ( struct ast_test *  test,
enum test_container_type  type,
unsigned int  copt 
)
static

The number of objects inserted and searched for in the container under test.

Definition at line 1923 of file test_astobj2.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_container_alloc_list, ao2_container_alloc_rbtree, ao2_link, ao2_ref, and test_obj::i.

1925 {
1926 /*!
1927  * \brief The number of objects inserted and searched for in the container under test.
1928  */
1929 #define OBJS 73
1930  int res = AST_TEST_PASS;
1931  struct ao2_container *c1 = NULL;
1932  struct test_obj *tobj[OBJS];
1933  struct test_obj *tobj2;
1934  int i;
1935 
1936  switch (type) {
1937  case TEST_CONTAINER_HASH:
1939  test_hash_cb, test_sort_cb, test_cmp_cb);
1940  break;
1941  case TEST_CONTAINER_LIST:
1943  test_sort_cb, test_cmp_cb);
1944  break;
1945  case TEST_CONTAINER_RBTREE:
1947  test_sort_cb, test_cmp_cb);
1948  break;
1949  }
1950 
1951  for (i = 0; i < OBJS; i++) {
1952  tobj[i] = NULL;
1953  }
1954 
1955  if (!c1) {
1956  ast_test_status_update(test, "Container c1 creation failed.\n");
1957  res = AST_TEST_FAIL;
1958  goto test_cleanup;
1959  }
1960 
1961  for (i = 0; i < OBJS; i++) {
1962  tobj[i] = ao2_alloc(sizeof(struct test_obj), test_obj_destructor);
1963  if (!tobj[i]) {
1964  ast_test_status_update(test, "test object creation failed.\n");
1965  res = AST_TEST_FAIL;
1966  goto test_cleanup;
1967  }
1968  tobj[i]->i = i;
1969  ao2_link(c1, tobj[i]);
1970  }
1971 
1972  for (i = 0; i < OBJS; i++) {
1973  if ((!(tobj2 = ao2_find(c1, &i, OBJ_KEY)))) {
1974  ast_test_status_update(test, "Should have found object %d in container.\n", i);
1975  res = AST_TEST_FAIL;
1976  goto test_cleanup;
1977  }
1978  ao2_ref(tobj2, -1);
1979  tobj2 = NULL;
1980  }
1981 
1982 test_cleanup:
1983  for (i = 0; i < OBJS ; i++) {
1984  ao2_cleanup(tobj[i]);
1985  }
1986  ao2_cleanup(c1);
1987  return res;
1988 }
#define OBJ_KEY
Definition: astobj2.h:1151
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#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.
Definition: astobj2.h:1303
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a red-black tree container.
Definition: astobj2.h:1349
Generic container type.
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
static int test_traversal_nonsorted ( int  res,
int  tst_num,
enum test_container_type  type,
struct ast_test *  test 
)
static

Container object insertion vector.

Container object insertion vector reversed.

Definition at line 1346 of file test_astobj2.c.

References AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN, AO2_ITERATOR_DESCENDING, OBJ_ORDER_ASCENDING, and OBJ_ORDER_DESCENDING.

1347 {
1348  struct ao2_container *c1;
1349  struct ao2_container *c2 = NULL;
1350  int partial;
1351  int destructor_count = 0;
1352 
1353  /*! Container object insertion vector. */
1354  static const int test_initial[] = {
1355  1, 0, 2, 6, 4, 7, 5, 3, 9, 8
1356  };
1357 
1358  /*! Container object insertion vector reversed. */
1359  static const int test_reverse[] = {
1360  8, 9, 3, 5, 7, 4, 6, 2, 0, 1
1361  };
1362  static const int test_list_partial_forward[] = {
1363  6, 7, 5
1364  };
1365  static const int test_list_partial_backward[] = {
1366  5, 7, 6
1367  };
1368 
1369  /* The hash orders assume that there are 5 buckets. */
1370  static const int test_hash_end_forward[] = {
1371  0, 5, 1, 6, 2, 7, 3, 8, 4, 9
1372  };
1373  static const int test_hash_end_backward[] = {
1374  9, 4, 8, 3, 7, 2, 6, 1, 5, 0
1375  };
1376  static const int test_hash_begin_forward[] = {
1377  5, 0, 6, 1, 7, 2, 8, 3, 9, 4
1378  };
1379  static const int test_hash_begin_backward[] = {
1380  4, 9, 3, 8, 2, 7, 1, 6, 0, 5
1381  };
1382  static const int test_hash_partial_forward[] = {
1383  5, 6, 7
1384  };
1385  static const int test_hash_partial_backward[] = {
1386  7, 6, 5
1387  };
1388 
1389  ast_test_status_update(test, "Test %d, %s containers.\n",
1390  tst_num, test_container2str(type));
1391 
1392  /* Create container that inserts objects at the end. */
1393  c1 = test_make_nonsorted(type, 0);
1394  if (!c1) {
1395  ast_test_status_update(test, "Container c1 creation failed.\n");
1396  res = AST_TEST_FAIL;
1397  goto test_cleanup;
1398  }
1399  if (insert_test_vector(c1, &destructor_count, test_initial, ARRAY_LEN(test_initial), "c1", test)) {
1400  res = AST_TEST_FAIL;
1401  goto test_cleanup;
1402  }
1403 
1404  /* Create container that inserts objects at the beginning. */
1405  c2 = test_make_nonsorted(type, AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN);
1406  if (!c2) {
1407  ast_test_status_update(test, "Container c2 creation failed.\n");
1408  res = AST_TEST_FAIL;
1409  goto test_cleanup;
1410  }
1411  if (insert_test_vector(c2, &destructor_count, test_initial, ARRAY_LEN(test_initial), "c2", test)) {
1412  res = AST_TEST_FAIL;
1413  goto test_cleanup;
1414  }
1415 
1416  /* Check container iteration directions */
1417  switch (type) {
1418  case TEST_CONTAINER_LIST:
1419  res = test_ao2_iteration(res, c1, 0,
1420  test_initial, ARRAY_LEN(test_initial),
1421  "Iteration (ascending, insert end)", test);
1422  res = test_ao2_iteration(res, c1, AO2_ITERATOR_DESCENDING,
1423  test_reverse, ARRAY_LEN(test_reverse),
1424  "Iteration (descending, insert end)", test);
1425 
1426  res = test_ao2_iteration(res, c2, 0,
1427  test_reverse, ARRAY_LEN(test_reverse),
1428  "Iteration (ascending, insert begin)", test);
1429  res = test_ao2_iteration(res, c2, AO2_ITERATOR_DESCENDING,
1430  test_initial, ARRAY_LEN(test_initial),
1431  "Iteration (descending, insert begin)", test);
1432  break;
1433  case TEST_CONTAINER_HASH:
1434  res = test_ao2_iteration(res, c1, 0,
1435  test_hash_end_forward, ARRAY_LEN(test_hash_end_forward),
1436  "Iteration (ascending, insert end)", test);
1437  res = test_ao2_iteration(res, c1, AO2_ITERATOR_DESCENDING,
1438  test_hash_end_backward, ARRAY_LEN(test_hash_end_backward),
1439  "Iteration (descending, insert end)", test);
1440 
1441  res = test_ao2_iteration(res, c2, 0,
1442  test_hash_begin_forward, ARRAY_LEN(test_hash_begin_forward),
1443  "Iteration (ascending, insert begin)", test);
1444  res = test_ao2_iteration(res, c2, AO2_ITERATOR_DESCENDING,
1445  test_hash_begin_backward, ARRAY_LEN(test_hash_begin_backward),
1446  "Iteration (descending, insert begin)", test);
1447  break;
1448  case TEST_CONTAINER_RBTREE:
1449  break;
1450  }
1451 
1452  /* Check container traversal directions */
1453  switch (type) {
1454  case TEST_CONTAINER_LIST:
1455  res = test_ao2_callback_traversal(res, c1, OBJ_ORDER_ASCENDING, NULL, NULL,
1456  test_initial, ARRAY_LEN(test_initial),
1457  "Traversal (ascending, insert end)", test);
1458  res = test_ao2_callback_traversal(res, c1, OBJ_ORDER_DESCENDING, NULL, NULL,
1459  test_reverse, ARRAY_LEN(test_reverse),
1460  "Traversal (descending, insert end)", test);
1461 
1462  res = test_ao2_callback_traversal(res, c2, OBJ_ORDER_ASCENDING, NULL, NULL,
1463  test_reverse, ARRAY_LEN(test_reverse),
1464  "Traversal (ascending, insert begin)", test);
1465  res = test_ao2_callback_traversal(res, c2, OBJ_ORDER_DESCENDING, NULL, NULL,
1466  test_initial, ARRAY_LEN(test_initial),
1467  "Traversal (descending, insert begin)", test);
1468  break;
1469  case TEST_CONTAINER_HASH:
1470  res = test_ao2_callback_traversal(res, c1, OBJ_ORDER_ASCENDING, NULL, NULL,
1471  test_hash_end_forward, ARRAY_LEN(test_hash_end_forward),
1472  "Traversal (ascending, insert end)", test);
1473  res = test_ao2_callback_traversal(res, c1, OBJ_ORDER_DESCENDING, NULL, NULL,
1474  test_hash_end_backward, ARRAY_LEN(test_hash_end_backward),
1475  "Traversal (descending, insert end)", test);
1476 
1477  res = test_ao2_callback_traversal(res, c2, OBJ_ORDER_ASCENDING, NULL, NULL,
1478  test_hash_begin_forward, ARRAY_LEN(test_hash_begin_forward),
1479  "Traversal (ascending, insert begin)", test);
1480  res = test_ao2_callback_traversal(res, c2, OBJ_ORDER_DESCENDING, NULL, NULL,
1481  test_hash_begin_backward, ARRAY_LEN(test_hash_begin_backward),
1482  "Traversal (descending, insert begin)", test);
1483  break;
1484  case TEST_CONTAINER_RBTREE:
1485  break;
1486  }
1487 
1488  /* Check traversal with OBJ_PARTIAL_KEY search range. */
1489  partial = 6;
1491  switch (type) {
1492  case TEST_CONTAINER_LIST:
1493  res = test_ao2_callback_traversal(res, c1, OBJ_PARTIAL_KEY | OBJ_ORDER_ASCENDING,
1494  test_cmp_cb, &partial,
1495  test_list_partial_forward, ARRAY_LEN(test_list_partial_forward),
1496  "Traversal OBJ_PARTIAL_KEY (ascending)", test);
1497  res = test_ao2_callback_traversal(res, c1, OBJ_PARTIAL_KEY | OBJ_ORDER_DESCENDING,
1498  test_cmp_cb, &partial,
1499  test_list_partial_backward, ARRAY_LEN(test_list_partial_backward),
1500  "Traversal OBJ_PARTIAL_KEY (descending)", test);
1501  break;
1502  case TEST_CONTAINER_HASH:
1503  res = test_ao2_callback_traversal(res, c1, OBJ_PARTIAL_KEY | OBJ_ORDER_ASCENDING,
1504  test_cmp_cb, &partial,
1505  test_hash_partial_forward, ARRAY_LEN(test_hash_partial_forward),
1506  "Traversal OBJ_PARTIAL_KEY (ascending)", test);
1507  res = test_ao2_callback_traversal(res, c1, OBJ_PARTIAL_KEY | OBJ_ORDER_DESCENDING,
1508  test_cmp_cb, &partial,
1509  test_hash_partial_backward, ARRAY_LEN(test_hash_partial_backward),
1510  "Traversal OBJ_PARTIAL_KEY (descending)", test);
1511  break;
1512  case TEST_CONTAINER_RBTREE:
1513  break;
1514  }
1515 
1516 test_cleanup:
1517  /* destroy containers */
1518  if (c1) {
1519  ao2_t_ref(c1, -1, "bye c1");
1520  }
1521  if (c2) {
1522  ao2_t_ref(c2, -1, "bye c2");
1523  }
1524 
1525  if (destructor_count > 0) {
1526  ast_test_status_update(test,
1527  "all destructors were not called, destructor count is %d\n",
1528  destructor_count);
1529  res = AST_TEST_FAIL;
1530  } else if (destructor_count < 0) {
1531  ast_test_status_update(test,
1532  "Destructor was called too many times, destructor count is %d\n",
1533  destructor_count);
1534  res = AST_TEST_FAIL;
1535  }
1536 
1537  return res;
1538 }
int partial_key_match_range
Definition: test_astobj2.c:85
Insert objects at the beginning of the container. (Otherwise it is the opposite; insert at the end...
Definition: astobj2.h:1172
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1152
Traverse in ascending order (First to last container object)
Definition: astobj2.h:1121
Traverse in descending order (Last to first container object)
Definition: astobj2.h:1123
Generic container type.
static int test_traversal_sorted ( int  res,
int  tst_num,
enum test_container_type  type,
struct ast_test *  test 
)
static

Container object insertion vector.

Container forward traversal/iteration.

Container backward traversal/iteration.

Definition at line 1552 of file test_astobj2.c.

References AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW, AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN, ao2_container_dump(), ao2_container_stats(), AO2_ITERATOR_DESCENDING, OBJ_ORDER_ASCENDING, and OBJ_ORDER_DESCENDING.

1553 {
1554  struct ao2_container *c1;
1555  struct ao2_container *c2 = NULL;
1556  int partial;
1557  int destructor_count = 0;
1558  int duplicate_number = 100;
1559 
1560  /*! Container object insertion vector. */
1561  static const int test_initial[] = {
1562  1, 0, 2, 6, 4, 7, 5, 3, 9, 8
1563  };
1564 
1565  /*! Container forward traversal/iteration. */
1566  static const int test_forward[] = {
1567  0, 1, 2, 3, 4, 5, 6, 7, 8, 9
1568  };
1569  /*! Container backward traversal/iteration. */
1570  static const int test_backward[] = {
1571  9, 8, 7, 6, 5, 4, 3, 2, 1, 0
1572  };
1573 
1574  static const int test_partial_forward[] = {
1575  5, 6, 7
1576  };
1577  static const int test_partial_backward[] = {
1578  7, 6, 5
1579  };
1580 
1581  /* The hash orders assume that there are 5 buckets. */
1582  static const int test_hash_forward[] = {
1583  0, 5, 1, 6, 2, 7, 3, 8, 4, 9
1584  };
1585  static const int test_hash_backward[] = {
1586  9, 4, 8, 3, 7, 2, 6, 1, 5, 0
1587  };
1588  static const int test_hash_partial_forward[] = {
1589  5, 6, 7
1590  };
1591  static const int test_hash_partial_backward[] = {
1592  7, 6, 5
1593  };
1594 
1595  /* Duplicate identifier order */
1596  static const int test_dup_allow_forward[] = {
1597  0, 1, 2, 3, 2
1598  };
1599  static const int test_dup_allow_backward[] = {
1600  2, 3, 2, 1, 0
1601  };
1602  static const int test_dup_reject[] = {
1603  0
1604  };
1605  static const int test_dup_obj_reject_forward[] = {
1606  0, 1, 2, 3
1607  };
1608  static const int test_dup_obj_reject_backward[] = {
1609  3, 2, 1, 0
1610  };
1611  static const int test_dup_replace[] = {
1612  2
1613  };
1614 
1615  ast_test_status_update(test, "Test %d, %s containers.\n",
1616  tst_num, test_container2str(type));
1617 
1618  /* Create container that inserts duplicate objects after matching objects. */
1619  c1 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW);
1620  if (!c1) {
1621  ast_test_status_update(test, "Container c1 creation failed.\n");
1622  res = AST_TEST_FAIL;
1623  goto test_cleanup;
1624  }
1625  if (insert_test_vector(c1, &destructor_count, test_initial, ARRAY_LEN(test_initial), "c1(DUPS_ALLOW)", test)) {
1626  res = AST_TEST_FAIL;
1627  goto test_cleanup;
1628  }
1629 
1630  /* Create container that inserts duplicate objects before matching objects. */
1632  if (!c2) {
1633  ast_test_status_update(test, "Container c2 creation failed.\n");
1634  res = AST_TEST_FAIL;
1635  goto test_cleanup;
1636  }
1637  if (insert_test_vector(c2, &destructor_count, test_initial, ARRAY_LEN(test_initial), "c2(DUPS_ALLOW)", test)) {
1638  res = AST_TEST_FAIL;
1639  goto test_cleanup;
1640  }
1641 
1642 #if defined(TEST_CONTAINER_DEBUG_DUMP)
1643  ao2_container_dump(c1, 0, "c1(DUPS_ALLOW)", (void *) test, (ao2_prnt_fn *) ast_test_debug, test_prnt_obj);
1644  ao2_container_stats(c1, 0, "c1(DUPS_ALLOW)", (void *) test, (ao2_prnt_fn *) ast_test_debug);
1645  ao2_container_dump(c2, 0, "c2(DUPS_ALLOW)", (void *) test, (ao2_prnt_fn *) ast_test_debug, test_prnt_obj);
1646  ao2_container_stats(c2, 0, "c2(DUPS_ALLOW)", (void *) test, (ao2_prnt_fn *) ast_test_debug);
1647 #endif /* defined(TEST_CONTAINER_DEBUG_DUMP) */
1648 
1649  /* Check container iteration directions */
1650  switch (type) {
1651  case TEST_CONTAINER_RBTREE:
1652  case TEST_CONTAINER_LIST:
1653  res = test_ao2_iteration(res, c1, 0,
1654  test_forward, ARRAY_LEN(test_forward),
1655  "Iteration (ascending)", test);
1656  res = test_ao2_iteration(res, c1, AO2_ITERATOR_DESCENDING,
1657  test_backward, ARRAY_LEN(test_backward),
1658  "Iteration (descending)", test);
1659  break;
1660  case TEST_CONTAINER_HASH:
1661  res = test_ao2_iteration(res, c1, 0,
1662  test_hash_forward, ARRAY_LEN(test_hash_forward),
1663  "Iteration (ascending)", test);
1664  res = test_ao2_iteration(res, c1, AO2_ITERATOR_DESCENDING,
1665  test_hash_backward, ARRAY_LEN(test_hash_backward),
1666  "Iteration (descending)", test);
1667  break;
1668  }
1669 
1670  /* Check container traversal directions */
1671  switch (type) {
1672  case TEST_CONTAINER_RBTREE:
1673  case TEST_CONTAINER_LIST:
1674  res = test_ao2_callback_traversal(res, c1, OBJ_ORDER_ASCENDING, NULL, NULL,
1675  test_forward, ARRAY_LEN(test_forward),
1676  "Traversal (ascending)", test);
1677  res = test_ao2_callback_traversal(res, c1, OBJ_ORDER_DESCENDING, NULL, NULL,
1678  test_backward, ARRAY_LEN(test_backward),
1679  "Traversal (descending)", test);
1680  break;
1681  case TEST_CONTAINER_HASH:
1682  res = test_ao2_callback_traversal(res, c1, OBJ_ORDER_ASCENDING, NULL, NULL,
1683  test_hash_forward, ARRAY_LEN(test_hash_forward),
1684  "Traversal (ascending, insert end)", test);
1685  res = test_ao2_callback_traversal(res, c1, OBJ_ORDER_DESCENDING, NULL, NULL,
1686  test_hash_backward, ARRAY_LEN(test_hash_backward),
1687  "Traversal (descending)", test);
1688  break;
1689  }
1690 
1691  /* Check traversal with OBJ_PARTIAL_KEY search range. */
1692  partial = 6;
1694  switch (type) {
1695  case TEST_CONTAINER_RBTREE:
1696  case TEST_CONTAINER_LIST:
1697  res = test_ao2_callback_traversal(res, c1, OBJ_PARTIAL_KEY | OBJ_ORDER_ASCENDING,
1698  test_cmp_cb, &partial,
1699  test_partial_forward, ARRAY_LEN(test_partial_forward),
1700  "Traversal OBJ_PARTIAL_KEY (ascending)", test);
1701  res = test_ao2_callback_traversal(res, c1, OBJ_PARTIAL_KEY | OBJ_ORDER_DESCENDING,
1702  test_cmp_cb, &partial,
1703  test_partial_backward, ARRAY_LEN(test_partial_backward),
1704  "Traversal OBJ_PARTIAL_KEY (descending)", test);
1705  break;
1706  case TEST_CONTAINER_HASH:
1707  res = test_ao2_callback_traversal(res, c1, OBJ_PARTIAL_KEY | OBJ_ORDER_ASCENDING,
1708  test_cmp_cb, &partial,
1709  test_hash_partial_forward, ARRAY_LEN(test_hash_partial_forward),
1710  "Traversal OBJ_PARTIAL_KEY (ascending)", test);
1711  res = test_ao2_callback_traversal(res, c1, OBJ_PARTIAL_KEY | OBJ_ORDER_DESCENDING,
1712  test_cmp_cb, &partial,
1713  test_hash_partial_backward, ARRAY_LEN(test_hash_partial_backward),
1714  "Traversal OBJ_PARTIAL_KEY (descending)", test);
1715  break;
1716  }
1717 
1718  /* Add duplicates to initial containers that allow duplicates */
1719  if (insert_test_duplicates(c1, &destructor_count, duplicate_number, "c1(DUPS_ALLOW)", test)) {
1720  res = AST_TEST_FAIL;
1721  goto test_cleanup;
1722  }
1723  if (insert_test_duplicates(c2, &destructor_count, duplicate_number, "c2(DUPS_ALLOW)", test)) {
1724  res = AST_TEST_FAIL;
1725  goto test_cleanup;
1726  }
1727 
1728 #if defined(TEST_CONTAINER_DEBUG_DUMP)
1729  ao2_container_dump(c1, 0, "c1(DUPS_ALLOW) w/ dups", (void *) test, (ao2_prnt_fn *) ast_test_debug, test_prnt_obj);
1730  ao2_container_stats(c1, 0, "c1(DUPS_ALLOW) w/ dups", (void *) test, (ao2_prnt_fn *) ast_test_debug);
1731  ao2_container_dump(c2, 0, "c2(DUPS_ALLOW) w/ dups", (void *) test, (ao2_prnt_fn *) ast_test_debug, test_prnt_obj);
1732  ao2_container_stats(c2, 0, "c2(DUPS_ALLOW) w/ dups", (void *) test, (ao2_prnt_fn *) ast_test_debug);
1733 #endif /* defined(TEST_CONTAINER_DEBUG_DUMP) */
1734 
1735  /* Check duplicates in containers that allow duplicates. */
1736  res = test_expected_duplicates(res, c1, OBJ_ORDER_ASCENDING, duplicate_number,
1737  test_dup_allow_forward, ARRAY_LEN(test_dup_allow_forward),
1738  "Duplicates (ascending, DUPS_ALLOW)", test);
1739  res = test_expected_duplicates(res, c1, OBJ_ORDER_DESCENDING, duplicate_number,
1740  test_dup_allow_backward, ARRAY_LEN(test_dup_allow_backward),
1741  "Duplicates (descending, DUPS_ALLOW)", test);
1742 
1743  ao2_t_ref(c1, -1, "bye c1");
1744  c1 = NULL;
1745  ao2_t_ref(c2, -1, "bye c2");
1746  c2 = NULL;
1747 
1748  /* Create containers that reject duplicate keyed objects. */
1749  c1 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT);
1750  if (!c1) {
1751  ast_test_status_update(test, "Container c1 creation failed.\n");
1752  res = AST_TEST_FAIL;
1753  goto test_cleanup;
1754  }
1755  if (insert_test_vector(c1, &destructor_count, test_initial, ARRAY_LEN(test_initial), "c1(DUPS_REJECT)", test)) {
1756  res = AST_TEST_FAIL;
1757  goto test_cleanup;
1758  }
1759  if (insert_test_duplicates(c1, &destructor_count, duplicate_number, "c1(DUPS_REJECT)", test)) {
1760  res = AST_TEST_FAIL;
1761  goto test_cleanup;
1762  }
1764  if (!c2) {
1765  ast_test_status_update(test, "Container c2 creation failed.\n");
1766  res = AST_TEST_FAIL;
1767  goto test_cleanup;
1768  }
1769  if (insert_test_vector(c2, &destructor_count, test_initial, ARRAY_LEN(test_initial), "c2(DUPS_REJECT)", test)) {
1770  res = AST_TEST_FAIL;
1771  goto test_cleanup;
1772  }
1773  if (insert_test_duplicates(c2, &destructor_count, duplicate_number, "c2(DUPS_REJECT)", test)) {
1774  res = AST_TEST_FAIL;
1775  goto test_cleanup;
1776  }
1777 
1778  /* Check duplicates in containers that reject duplicate keyed objects. */
1779  res = test_expected_duplicates(res, c1, OBJ_ORDER_ASCENDING, duplicate_number,
1780  test_dup_reject, ARRAY_LEN(test_dup_reject),
1781  "Duplicates (ascending, DUPS_REJECT)", test);
1782  res = test_expected_duplicates(res, c1, OBJ_ORDER_DESCENDING, duplicate_number,
1783  test_dup_reject, ARRAY_LEN(test_dup_reject),
1784  "Duplicates (descending, DUPS_REJECT)", test);
1785 
1786  ao2_t_ref(c1, -1, "bye c1");
1787  c1 = NULL;
1788  ao2_t_ref(c2, -1, "bye c2");
1789  c2 = NULL;
1790 
1791  /* Create containers that reject duplicate objects. */
1792  c1 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT);
1793  if (!c1) {
1794  ast_test_status_update(test, "Container c1 creation failed.\n");
1795  res = AST_TEST_FAIL;
1796  goto test_cleanup;
1797  }
1798  if (insert_test_vector(c1, &destructor_count, test_initial, ARRAY_LEN(test_initial), "c1(DUPS_OBJ_REJECT)", test)) {
1799  res = AST_TEST_FAIL;
1800  goto test_cleanup;
1801  }
1802  if (insert_test_duplicates(c1, &destructor_count, duplicate_number, "c1(DUPS_OBJ_REJECT)", test)) {
1803  res = AST_TEST_FAIL;
1804  goto test_cleanup;
1805  }
1807  if (!c2) {
1808  ast_test_status_update(test, "Container c2 creation failed.\n");
1809  res = AST_TEST_FAIL;
1810  goto test_cleanup;
1811  }
1812  if (insert_test_vector(c2, &destructor_count, test_initial, ARRAY_LEN(test_initial), "c2(DUPS_OBJ_REJECT)", test)) {
1813  res = AST_TEST_FAIL;
1814  goto test_cleanup;
1815  }
1816  if (insert_test_duplicates(c2, &destructor_count, duplicate_number, "c2(DUPS_OBJ_REJECT)", test)) {
1817  res = AST_TEST_FAIL;
1818  goto test_cleanup;
1819  }
1820 
1821  /* Check duplicates in containers that reject duplicate objects. */
1822  res = test_expected_duplicates(res, c1, OBJ_ORDER_ASCENDING, duplicate_number,
1823  test_dup_obj_reject_forward, ARRAY_LEN(test_dup_obj_reject_forward),
1824  "Duplicates (ascending, DUPS_OBJ_REJECT)", test);
1825  res = test_expected_duplicates(res, c1, OBJ_ORDER_DESCENDING, duplicate_number,
1826  test_dup_obj_reject_backward, ARRAY_LEN(test_dup_obj_reject_backward),
1827  "Duplicates (descending, DUPS_OBJ_REJECT)", test);
1828 
1829  ao2_t_ref(c1, -1, "bye c1");
1830  c1 = NULL;
1831  ao2_t_ref(c2, -1, "bye c2");
1832  c2 = NULL;
1833 
1834  /* Create container that replaces duplicate keyed objects. */
1835  c1 = test_make_sorted(type, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE);
1836  if (!c1) {
1837  ast_test_status_update(test, "Container c1 creation failed.\n");
1838  res = AST_TEST_FAIL;
1839  goto test_cleanup;
1840  }
1841  if (insert_test_vector(c1, &destructor_count, test_initial, ARRAY_LEN(test_initial), "c1(DUPS_REJECT)", test)) {
1842  res = AST_TEST_FAIL;
1843  goto test_cleanup;
1844  }
1845  if (insert_test_duplicates(c1, &destructor_count, duplicate_number, "c1(DUPS_REJECT)", test)) {
1846  res = AST_TEST_FAIL;
1847  goto test_cleanup;
1848  }
1850  if (!c2) {
1851  ast_test_status_update(test, "Container c2 creation failed.\n");
1852  res = AST_TEST_FAIL;
1853  goto test_cleanup;
1854  }
1855  if (insert_test_vector(c2, &destructor_count, test_initial, ARRAY_LEN(test_initial), "c2(DUPS_REPLACE)", test)) {
1856  res = AST_TEST_FAIL;
1857  goto test_cleanup;
1858  }
1859  if (insert_test_duplicates(c2, &destructor_count, duplicate_number, "c2(DUPS_REPLACE)", test)) {
1860  res = AST_TEST_FAIL;
1861  goto test_cleanup;
1862  }
1863 
1864  /* Check duplicates in containers that replaces duplicate keyed objects. */
1865  res = test_expected_duplicates(res, c1, OBJ_ORDER_ASCENDING, duplicate_number,
1866  test_dup_replace, ARRAY_LEN(test_dup_replace),
1867  "Duplicates (ascending, DUPS_REPLACE)", test);
1868  res = test_expected_duplicates(res, c1, OBJ_ORDER_DESCENDING, duplicate_number,
1869  test_dup_replace, ARRAY_LEN(test_dup_replace),
1870  "Duplicates (descending, DUPS_REPLACE)", test);
1871 
1872 test_cleanup:
1873  /* destroy containers */
1874  if (c1) {
1875  ao2_t_ref(c1, -1, "bye c1");
1876  }
1877  if (c2) {
1878  ao2_t_ref(c2, -1, "bye c2");
1879  }
1880 
1881  if (destructor_count > 0) {
1882  ast_test_status_update(test,
1883  "all destructors were not called, destructor count is %d\n",
1884  destructor_count);
1885  res = AST_TEST_FAIL;
1886  } else if (destructor_count < 0) {
1887  ast_test_status_update(test,
1888  "Destructor was called too many times, destructor count is %d\n",
1889  destructor_count);
1890  res = AST_TEST_FAIL;
1891  }
1892 
1893  return res;
1894 }
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_prnt_fn)(void *where, const char *fmt,...)
Print output.
Definition: astobj2.h:1435
int partial_key_match_range
Definition: test_astobj2.c:85
Allow objects with duplicate keys in container.
Definition: astobj2.h:1181
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.
Insert objects at the beginning of the container. (Otherwise it is the opposite; insert at the end...
Definition: astobj2.h:1172
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1152
Traverse in ascending order (First to last container object)
Definition: astobj2.h:1121
Traverse in descending order (Last to first container object)
Definition: astobj2.h:1123
Replace objects with duplicate keys in container.
Definition: astobj2.h:1211
Reject objects with duplicate keys in container.
Definition: astobj2.h:1188
Generic container type.
Reject duplicate objects in container.
Definition: astobj2.h:1201

Variable Documentation

int partial_key_match_range

Partial search key +/- matching range.

Definition at line 85 of file test_astobj2.c.