diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_abstract_jb.c | 3 | ||||
-rw-r--r-- | tests/test_cel.c | 11 | ||||
-rw-r--r-- | tests/test_config.c | 35 | ||||
-rw-r--r-- | tests/test_core_codec.c | 369 | ||||
-rw-r--r-- | tests/test_core_format.c | 975 | ||||
-rw-r--r-- | tests/test_format_api.c | 859 | ||||
-rw-r--r-- | tests/test_format_cache.c | 281 | ||||
-rw-r--r-- | tests/test_format_cap.c | 1479 | ||||
-rw-r--r-- | tests/test_voicemail_api.c | 11 |
9 files changed, 3140 insertions, 883 deletions
diff --git a/tests/test_abstract_jb.c b/tests/test_abstract_jb.c index f48307a3a..f0c0315bf 100644 --- a/tests/test_abstract_jb.c +++ b/tests/test_abstract_jb.c @@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/test.h" #include "asterisk/abstract_jb.h" #include "asterisk/frame.h" +#include "asterisk/format_cache.h" #define DEFAULT_FRAME_MS 160 #define DEFAULT_CONFIG_FLAGS 0 @@ -85,7 +86,7 @@ static struct ast_frame *create_test_frame(long timestamp, { struct ast_frame f = {0}; - f.subclass.format.id = AST_FORMAT_SLINEAR; + f.subclass.format = ast_format_slin; f.frametype = AST_FRAME_VOICE; f.src = "TEST"; f.ts = timestamp; diff --git a/tests/test_cel.c b/tests/test_cel.c index ff0aaca24..010f19987 100644 --- a/tests/test_cel.c +++ b/tests/test_cel.c @@ -38,6 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/test.h" #include "asterisk/cel.h" #include "asterisk/channel.h" +#include "asterisk/format_cache.h" #include "asterisk/linkedlists.h" #include "asterisk/chanvars.h" #include "asterisk/utils.h" @@ -1317,7 +1318,10 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_swap) do_sleep(); /* Perform attended transfer */ - ast_bridge_transfer_attended(chan_alice, chan_david); + if (ast_bridge_transfer_attended(chan_alice, chan_david)) { + ast_test_status_update(test, "Attended transfer failed!\n"); + return AST_TEST_FAIL; + } do_sleep(); BRIDGE_ENTER_EVENT_PEER(chan_bob, bridge2, "CELTestChannel/David,CELTestChannel/Charlie"); @@ -1397,7 +1401,10 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_merge) BRIDGE_ENTER(chan_david, bridge2); /* Perform attended transfer */ - ast_bridge_transfer_attended(chan_alice, chan_david); + if (ast_bridge_transfer_attended(chan_alice, chan_david)) { + ast_test_status_update(test, "Attended transfer failed!\n"); + return AST_TEST_FAIL; + } do_sleep(); BRIDGE_EXIT_EVENT_PEER(chan_charlie, bridge2, "CELTestChannel/David"); BRIDGE_ENTER_EVENT_PEER(chan_charlie, bridge1, "CELTestChannel/Bob,CELTestChannel/Alice"); diff --git a/tests/test_config.c b/tests/test_config.c index f9e9a6f48..a8a83b2b0 100644 --- a/tests/test_config.c +++ b/tests/test_config.c @@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); #include "asterisk/frame.h" #include "asterisk/utils.h" #include "asterisk/logger.h" +#include "asterisk/format_cap.h" #define CONFIG_FILE "test_config.conf" @@ -627,7 +628,6 @@ struct test_item { struct ast_sockaddr sockaddropt; int boolopt; struct ast_ha *aclopt; - struct ast_codec_pref codecprefopt; struct ast_format_cap *codeccapopt; unsigned int customopt:1; }; @@ -653,9 +653,7 @@ static void test_item_destructor(void *obj) { struct test_item *item = obj; ast_string_field_free_memory(item); - if (item->codeccapopt) { - ast_format_cap_destroy(item->codeccapopt); - } + ao2_cleanup(item->codeccapopt); if (item->aclopt) { ast_free_ha(item->aclopt); } @@ -671,7 +669,7 @@ static void *test_item_alloc(const char *cat) ao2_ref(item, -1); return NULL; } - if (!(item->codeccapopt = ast_format_cap_alloc(0))) { + if (!(item->codeccapopt = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { ao2_ref(item, -1); return NULL; } @@ -821,7 +819,7 @@ AST_TEST_DEFINE(config_options_test) aco_option_register(&cfg_info, "boolflag3", ACO_EXACT, config_test_conf.types, BOOLFLAG3_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG3); aco_option_register(&cfg_info, "aclpermitopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 1, FLDSET(struct test_item, aclopt)); aco_option_register(&cfg_info, "acldenyopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 0, FLDSET(struct test_item, aclopt)); - aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codecprefopt, codeccapopt)); + aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codeccapopt)); aco_option_register(&cfg_info, "stropt", ACO_EXACT, config_test_conf.types, STR_DEFAULT, OPT_STRINGFIELD_T, 0, STRFLDSET(struct test_item, stropt)); aco_option_register_custom(&cfg_info, "customopt", ACO_EXACT, config_test_conf.types, CUSTOM_DEFAULT, customopt_handler, 0); aco_option_register_deprecated(&cfg_info, "permit", config_test_conf.types, "aclpermitopt"); @@ -855,11 +853,11 @@ AST_TEST_DEFINE(config_options_test) ast_sockaddr_parse(&acl_allow, "1.2.3.4", PARSE_PORT_FORBID); ast_sockaddr_parse(&acl_fail, "1.1.1.1", PARSE_PORT_FORBID); - defaults.codeccapopt = ast_format_cap_alloc(0); - ast_parse_allow_disallow(&defaults.codecprefopt, defaults.codeccapopt, CODEC_DEFAULT, 1); + defaults.codeccapopt = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + ast_format_cap_update_by_allow_disallow(defaults.codeccapopt, CODEC_DEFAULT, 1); - configs.codeccapopt = ast_format_cap_alloc(0); - ast_parse_allow_disallow(&configs.codecprefopt, configs.codeccapopt, CODEC_CONFIG, 1); + configs.codeccapopt = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + ast_format_cap_update_by_allow_disallow(configs.codeccapopt, CODEC_CONFIG, 1); ast_string_field_init(&defaults, 128); ast_string_field_init(&configs, 128); @@ -907,10 +905,13 @@ AST_TEST_DEFINE(config_options_test) res = AST_TEST_FAIL; } if (!ast_format_cap_identical(arr[x]->codeccapopt, control->codeccapopt)) { - char buf1[128], buf2[128]; - ast_getformatname_multiple(buf1, sizeof(buf1), arr[x]->codeccapopt); - ast_getformatname_multiple(buf2, sizeof(buf2), control->codeccapopt); - ast_test_status_update(test, "format did not match: '%s' vs '%s' on loop %d\n", buf1, buf2, x); + struct ast_str *codec_buf1 = ast_str_alloca(64); + struct ast_str *codec_buf2 = ast_str_alloca(64); + + ast_test_status_update(test, "format did not match: '%s' vs '%s' on loop %d\n", + ast_format_cap_get_names(arr[x]->codeccapopt, &codec_buf1), + ast_format_cap_get_names(control->codeccapopt, &codec_buf2), + x); res = AST_TEST_FAIL; } if (strcasecmp(arr[x]->stropt, control->stropt)) { @@ -925,8 +926,10 @@ AST_TEST_DEFINE(config_options_test) } ast_free_ha(configs.aclopt); - ast_format_cap_destroy(defaults.codeccapopt); - ast_format_cap_destroy(configs.codeccapopt); + ao2_cleanup(defaults.codeccapopt); + defaults.codeccapopt = NULL; + ao2_cleanup(configs.codeccapopt); + configs.codeccapopt = NULL; ast_string_field_free_memory(&defaults); ast_string_field_free_memory(&configs); return res; diff --git a/tests/test_core_codec.c b/tests/test_core_codec.c new file mode 100644 index 000000000..499e633df --- /dev/null +++ b/tests/test_core_codec.c @@ -0,0 +1,369 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2014, Digium, Inc. + * + * Joshua Colp <jcolp@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Core Codec API Unit Tests + * + * \author Joshua Colp <jcolp@digium.com> + * + */ + +/*** MODULEINFO + <depend>TEST_FRAMEWORK</depend> + <support_level>core</support_level> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/test.h" +#include "asterisk/module.h" +#include "asterisk/codec.h" + +static struct ast_codec known_unknown = { + .name = "unit_test", + .description = "Unit test codec", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + .minimum_ms = 10, + .maximum_ms = 150, + .default_ms = 20, +}; + +static struct ast_codec doubly = { + .name = "unit_test_double", + .description = "Unit test codec", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + .minimum_ms = 10, + .maximum_ms = 150, + .default_ms = 20, +}; + +static struct ast_codec unknown = { + .name = "unit_test_unknown", + .description = "Unit test codec", + .type = AST_MEDIA_TYPE_UNKNOWN, + .sample_rate = 8000, + .minimum_ms = 10, + .maximum_ms = 150, + .default_ms = 20, +}; + +static struct ast_codec audio_without_rate = { + .name = "unit_test_audio_without_rate", + .description = "Unit test codec", + .type = AST_MEDIA_TYPE_AUDIO, + .minimum_ms = 10, + .maximum_ms = 150, + .default_ms = 20, +}; + +static struct ast_codec audio_get = { + .name = "unit_test_audio_get", + .description = "Unit test codec", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + .minimum_ms = 10, + .maximum_ms = 150, + .default_ms = 20, +}; + +static struct ast_codec audio_get_unknown = { + .name = "unit_test_audio_get_unknown", + .description = "Unit test codec", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + .minimum_ms = 10, + .maximum_ms = 150, + .default_ms = 20, +}; + +static struct ast_codec audio_get_id = { + .name = "unit_test_audio_get_id", + .description = "Unit test codec", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + .minimum_ms = 10, + .maximum_ms = 150, + .default_ms = 20, +}; + +AST_TEST_DEFINE(codec_register) +{ + switch (cmd) { + case TEST_INIT: + info->name = "codec_register"; + info->category = "/main/core_codec/"; + info->summary = "codec registration unit test"; + info->description = + "Test registration of a core codec that is known to be unknown"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (ast_codec_register(&known_unknown)) { + ast_test_status_update(test, "Unsuccessfully registered a codec that is known to be unknown\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(codec_register_twice) +{ + switch (cmd) { + case TEST_INIT: + info->name = "codec_register_twice"; + info->category = "/main/core_codec/"; + info->summary = "codec registration unit test"; + info->description = + "Test double registration of a core codec to confirm it fails"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (ast_codec_register(&doubly)) { + ast_test_status_update(test, "Unsuccessfully registered a codec that is known to be unknown\n"); + return AST_TEST_FAIL; + } + + if (!ast_codec_register(&doubly)) { + ast_test_status_update(test, "Successfully registered a codec twice\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(codec_register_unknown) +{ + switch (cmd) { + case TEST_INIT: + info->name = "codec_register_unknown"; + info->category = "/main/core_codec/"; + info->summary = "codec registration unit test"; + info->description = + "Test that registration of an unknown codec type fails"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (!ast_codec_register(&unknown)) { + ast_test_status_update(test, "Successfully registered a codec with an unknown media type\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(codec_register_audio_no_sample_rate) +{ + switch (cmd) { + case TEST_INIT: + info->name = "codec_register_audio_no_sample_rate"; + info->category = "/main/core_codec/"; + info->summary = "codec registration unit test"; + info->description = + "Test that registration of an audio codec without sample rate fails"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (!ast_codec_register(&audio_without_rate)) { + ast_test_status_update(test, "Successfully registered an audio codec without a sample rate\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(codec_get) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "codec_get"; + info->category = "/main/core_codec/"; + info->summary = "codec get unit test"; + info->description = + "Test that getting of a known codec succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (ast_codec_register(&audio_get)) { + ast_test_status_update(test, "Unsucessfully registered a codec for getting\n"); + return AST_TEST_FAIL; + } + + codec = ast_codec_get("unit_test_audio_get", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Unsuccessfully retrieved a codec we just registered\n"); + return AST_TEST_FAIL; + } else if (strcmp(codec->name, audio_get.name)) { + ast_test_status_update(test, "Name of retrieved codec does not match registered codec\n"); + return AST_TEST_FAIL; + } else if (codec->type != audio_get.type) { + ast_test_status_update(test, "Type of retrieved codec does not match registered codec\n"); + return AST_TEST_FAIL; + } else if (codec->sample_rate != audio_get.sample_rate) { + ast_test_status_update(test, "Sample rate of retrieved codec does not match registered codec\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(codec_get_unregistered) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "codec_get_unregistered"; + info->category = "/main/core_codec/"; + info->summary = "codec get unit test"; + info->description = + "Test that getting of a codec that is not registered fails"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("goats", AST_MEDIA_TYPE_AUDIO, 8000); + if (codec) { + ast_test_status_update(test, "Successfully got a codec named '%s' when getting a codec named 'goats'\n", + codec->name); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(codec_get_unknown) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "codec_get_unknown"; + info->category = "/main/core_codec/"; + info->summary = "codec get unit test"; + info->description = + "Test that getting of a known codec using name and unknown type succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (ast_codec_register(&audio_get_unknown)) { + ast_test_status_update(test, "Unsucessfully registered a codec for getting\n"); + return AST_TEST_FAIL; + } + + codec = ast_codec_get("unit_test_audio_get_unknown", AST_MEDIA_TYPE_UNKNOWN, 8000); + if (!codec) { + ast_test_status_update(test, "Unsuccessfully retrieved a codec we just registered\n"); + return AST_TEST_FAIL; + } else if (strcmp(codec->name, audio_get_unknown.name)) { + ast_test_status_update(test, "Name of retrieved codec does not match registered codec\n"); + return AST_TEST_FAIL; + } else if (codec->type != audio_get_unknown.type) { + ast_test_status_update(test, "Type of retrieved codec does not match registered codec\n"); + return AST_TEST_FAIL; + } else if (codec->sample_rate != audio_get_unknown.sample_rate) { + ast_test_status_update(test, "Sample rate of retrieved codec does not match registered codec\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(codec_get_id) +{ + RAII_VAR(struct ast_codec *, named, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "codec_get_unknown"; + info->category = "/main/core_codec/"; + info->summary = "codec get unit test"; + info->description = + "Test that getting of a known codec using name and unknown type succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (ast_codec_register(&audio_get_id)) { + ast_test_status_update(test, "Unsucessfully registered a codec for getting\n"); + return AST_TEST_FAIL; + } + + named = ast_codec_get("unit_test_audio_get_id", AST_MEDIA_TYPE_AUDIO, 8000); + if (!named) { + ast_test_status_update(test, "Unsuccessfully retrieved a codec we just registered\n"); + return AST_TEST_FAIL; + } + + codec = ast_codec_get_by_id(named->id); + if (!codec) { + ast_test_status_update(test, "Unsuccessfully retrieved a codec using id of a named codec we just got\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +static int unload_module(void) +{ + AST_TEST_UNREGISTER(codec_register); + AST_TEST_UNREGISTER(codec_register_twice); + AST_TEST_UNREGISTER(codec_register_unknown); + AST_TEST_UNREGISTER(codec_register_audio_no_sample_rate); + AST_TEST_UNREGISTER(codec_get); + AST_TEST_UNREGISTER(codec_get_unregistered); + AST_TEST_UNREGISTER(codec_get_unknown); + AST_TEST_UNREGISTER(codec_get_id); + return 0; +} + +static int load_module(void) +{ + AST_TEST_REGISTER(codec_register); + AST_TEST_REGISTER(codec_register_twice); + AST_TEST_REGISTER(codec_register_unknown); + AST_TEST_REGISTER(codec_register_audio_no_sample_rate); + AST_TEST_REGISTER(codec_get); + AST_TEST_REGISTER(codec_get_unregistered); + AST_TEST_REGISTER(codec_get_unknown); + AST_TEST_REGISTER(codec_get_id); + return AST_MODULE_LOAD_SUCCESS; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Core codec API test module"); diff --git a/tests/test_core_format.c b/tests/test_core_format.c new file mode 100644 index 000000000..2ae944bb3 --- /dev/null +++ b/tests/test_core_format.c @@ -0,0 +1,975 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2014, Digium, Inc. + * + * Joshua Colp <jcolp@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Core Format API Unit Tests + * + * \author Joshua Colp <jcolp@digium.com> + * + */ + +/*** MODULEINFO + <depend>TEST_FRAMEWORK</depend> + <support_level>core</support_level> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/test.h" +#include "asterisk/module.h" +#include "asterisk/codec.h" +#include "asterisk/format.h" + +#define TEST_CATEGORY "/main/core_format/" + +static void test_core_format_destroy(struct ast_format *format); +static int test_core_format_clone(const struct ast_format *src, struct ast_format *dst); +static enum ast_format_cmp_res test_core_format_cmp(const struct ast_format *format1, const struct ast_format *format2); +static struct ast_format *test_core_format_get_joint(const struct ast_format *format1, const struct ast_format *format2); +static struct ast_format *test_core_format_attribute_set(const struct ast_format *format, const char *name, const char *value); +static struct ast_format *test_core_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes); +static void test_core_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str); + +/*! \brief A format attribute 'module' used by the unit tests */ +static struct ast_format_interface test_core_format_attr = { + .format_destroy = &test_core_format_destroy, + .format_clone = &test_core_format_clone, + .format_cmp = &test_core_format_cmp, + .format_get_joint = &test_core_format_get_joint, + .format_attribute_set = &test_core_format_attribute_set, + .format_parse_sdp_fmtp = &test_core_format_parse_sdp_fmtp, + .format_generate_sdp_fmtp = &test_core_format_generate_sdp_fmtp, +}; + +/*! \brief A test piece of data to associate with \ref test_core_format_attr */ +struct test_core_format_pvt { + /*! Some data field */ + int field_one; + /*! Another arbitrary data field */ + int field_two; +}; + +/*! \brief A test codec for these unit tests. Should be used with \c test_core_format */ +static struct ast_codec test_core_format_codec = { + .name = "test_core_format_codec", + .description = "Unit test codec used by test_core_format", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + .minimum_ms = 10, + .maximum_ms = 150, + .default_ms = 20, +}; + +/*! \brief Tracking object used to verify format attribute callbacks */ +struct callbacks_called { + /*! Number of times \ref test_core_format_destroy was called */ + int format_destroy; + /*! Number of times \ref test_core_format_clone was called */ + int format_clone; + /*! Number of times \ref test_core_format_cmp was called */ + int format_cmp; + /*! Number of times \ref test_core_format_get_joint was called */ + int format_get_joint; + /*! Number of times \ref test_core_format_attribute_set was called */ + int format_attribute_set; + /*! Number of times \ref test_core_format_parse_sdp_fmtp was called */ + int format_parse_sdp_fmtp; + /*! Number of times \ref test_core_format_generate_sdp_fmtp was called */ + int format_generate_sdp_fmtp; +}; + +/*! \brief A global tracking object. Cleared out by the test init cb */ +static struct callbacks_called test_callbacks_called; + +/*! \brief Format attribute callback for when format attributes are to be destroyed */ +static void test_core_format_destroy(struct ast_format *format) +{ + struct test_core_format_pvt *pvt = ast_format_get_attribute_data(format); + + ast_free(pvt); + ++test_callbacks_called.format_destroy; +} + +/*! \brief Format attribute callback called during format cloning */ +static int test_core_format_clone(const struct ast_format *src, struct ast_format *dst) +{ + struct test_core_format_pvt *pvt = ast_format_get_attribute_data(src); + struct test_core_format_pvt *new_pvt; + + new_pvt = ast_calloc(1, sizeof(*new_pvt)); + if (!new_pvt) { + return -1; + } + + if (pvt) { + *new_pvt = *pvt; + } + ast_format_set_attribute_data(dst, new_pvt); + + ++test_callbacks_called.format_clone; + + return 0; +} + +/*! \brief Format attribute callback called during format comparison */ +static enum ast_format_cmp_res test_core_format_cmp(const struct ast_format *format1, const struct ast_format *format2) +{ + struct test_core_format_pvt *pvt1 = ast_format_get_attribute_data(format1); + struct test_core_format_pvt *pvt2 = ast_format_get_attribute_data(format2); + + ++test_callbacks_called.format_cmp; + if (pvt1 == pvt2) { + return AST_FORMAT_CMP_EQUAL; + } + + if ((!pvt1 && pvt2 && (pvt2->field_one != 0 || pvt2->field_two != 0)) + || (pvt1 && !pvt2 && (pvt1->field_one != 0 || pvt1->field_two != 0))) { + return AST_FORMAT_CMP_NOT_EQUAL; + } + + if (pvt1 && pvt2) { + if (!memcmp(pvt1, pvt2, sizeof(*pvt1))) { + return AST_FORMAT_CMP_EQUAL; + } else { + return AST_FORMAT_CMP_NOT_EQUAL; + } + } + + return AST_FORMAT_CMP_EQUAL; +} + +/*! + * \brief Format attribute callback called during joint format capability + * \note Our test will assume the max of attributes \c field_one and \c field_two + */ +static struct ast_format *test_core_format_get_joint(const struct ast_format *format1, const struct ast_format *format2) +{ + struct test_core_format_pvt *pvt1 = ast_format_get_attribute_data(format1); + struct test_core_format_pvt *pvt2 = ast_format_get_attribute_data(format2); + struct ast_format *joint; + struct test_core_format_pvt *joint_pvt; + + joint = ast_format_clone(format1); + if (!joint) { + return NULL; + } + joint_pvt = ast_format_get_attribute_data(joint); + + joint_pvt->field_one = MAX(pvt1 ? pvt1->field_one : 0, pvt2 ? pvt2->field_one : 0); + joint_pvt->field_two = MAX(pvt2 ? pvt2->field_two : 0, pvt2 ? pvt2->field_two : 0); + + ++test_callbacks_called.format_get_joint; + + return joint; +} + +/*! \brief Format attribute callback for setting an attribute on a format */ +static struct ast_format *test_core_format_attribute_set(const struct ast_format *format, const char *name, const char *value) +{ + struct ast_format *clone = ast_format_clone(format); + struct test_core_format_pvt *clone_pvt; + + if (!clone) { + return NULL; + } + clone_pvt = ast_format_get_attribute_data(clone); + + if (!strcmp(name, "one")) { + clone_pvt->field_one = atoi(value); + } else if (!strcmp(name, "two")) { + clone_pvt->field_two = atoi(value); + } + ++test_callbacks_called.format_attribute_set; + + return clone; +} + +/*! \brief Format attribute callback to construct a format from an SDP fmtp line */ +static struct ast_format *test_core_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes) +{ + struct ast_format *clone = ast_format_clone(format); + struct test_core_format_pvt *pvt; + + if (!clone) { + return NULL; + } + + pvt = ast_format_get_attribute_data(clone); + + if (sscanf(attributes, "one=%d;two=%d", &pvt->field_one, &pvt->field_two) != 2) { + ao2_ref(clone, -1); + return NULL; + } + + ++test_callbacks_called.format_parse_sdp_fmtp; + return clone; +} + +/*! \brief Format attribute callback to generate an SDP fmtp line from a format */ +static void test_core_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str) +{ + struct test_core_format_pvt *pvt = ast_format_get_attribute_data(format); + + if (!pvt) { + return; + } + + ast_str_append(str, 0, "a=fmtp:%d one=%d;two=%d\r\n", payload, pvt->field_one, pvt->field_two); + + ++test_callbacks_called.format_generate_sdp_fmtp; +} + +AST_TEST_DEFINE(format_create) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Format creation unit test"; + info->description = + "Test creation of a format"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create(codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } else if (ast_format_get_codec_id(format) != codec->id) { + ast_test_status_update(test, "Created format does not contain provided codec\n"); + return AST_TEST_FAIL; + } + + ao2_ref(format, -1); + format = ast_format_create_named("super_ulaw", codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } else if (ast_format_get_codec_id(format) != codec->id) { + ast_test_status_update(test, "Created format does not contain provided codec\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_create_attr) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format_w_attr, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Format creation w/ attributes unit test"; + info->description = + "Test creation of a format with attributes"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create(codec); + if (!format) { + ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } else if (ast_format_get_codec_id(format) != codec->id) { + ast_test_status_update(test, "Created format does not contain provided codec\n"); + return AST_TEST_FAIL; + } + + format_w_attr = ast_format_attribute_set(format, "one", "1"); + if (!format_w_attr) { + ast_test_status_update(test, "Could not create format with attributes using test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } else if (ast_format_get_codec_id(format_w_attr) != codec->id) { + ast_test_status_update(test, "Created format does not contain provided codec\n"); + return AST_TEST_FAIL; + } else if (ast_format_cmp(format, format_w_attr) == AST_FORMAT_CMP_EQUAL) { + ast_test_status_update(test, "Format with attributes should not be equal to format without attributes\n"); + return AST_TEST_FAIL; + } + + ast_test_validate(test, test_callbacks_called.format_attribute_set == 1); + ast_test_validate(test, test_callbacks_called.format_cmp == 1); + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_clone) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format_w_attr, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, clone, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Format cloning unit test"; + info->description = + "Test cloning of a format"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create(codec); + if (!format) { + ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } else if (ast_format_get_codec_id(format) != codec->id) { + ast_test_status_update(test, "Created format does not contain provided codec\n"); + return AST_TEST_FAIL; + } + + format_w_attr = ast_format_attribute_set(format, "one", "1"); + if (!format_w_attr) { + ast_test_status_update(test, "Could not create format with attributes using test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } else if (ast_format_get_codec_id(format_w_attr) != codec->id) { + ast_test_status_update(test, "Created format does not contain provided codec\n"); + return AST_TEST_FAIL; + } + + /* Test cloning a format without attributes */ + clone = ast_format_clone(format); + if (!clone) { + ast_test_status_update(test, "Could not create cloned format\n"); + return AST_TEST_FAIL; + } else if (ast_format_get_codec_id(clone) != codec->id) { + ast_test_status_update(test, "Cloned format does not contain provided codec\n"); + return AST_TEST_FAIL; + } else if (clone == format) { + ast_test_status_update(test, "Cloned format pointer is the same as original format pointer\n"); + return AST_TEST_FAIL; + } else if (ast_format_cmp(clone, format) != AST_FORMAT_CMP_EQUAL) { + ast_test_status_update(test, "Cloned format is not the same as its original format\n"); + return AST_TEST_FAIL; + } + ao2_ref(clone, -1); + + /* Test cloning a format with attributes */ + clone = ast_format_clone(format_w_attr); + if (!clone) { + ast_test_status_update(test, "Could not create cloned format\n"); + return AST_TEST_FAIL; + } else if (ast_format_get_codec_id(clone) != codec->id) { + ast_test_status_update(test, "Cloned format does not contain provided codec\n"); + return AST_TEST_FAIL; + } else if (clone == format_w_attr) { + ast_test_status_update(test, "Cloned format pointer is the same as original format pointer\n"); + return AST_TEST_FAIL; + } else if (ast_format_cmp(clone, format_w_attr) != AST_FORMAT_CMP_EQUAL) { + ast_test_status_update(test, "Cloned format is not the same as its original format\n"); + return AST_TEST_FAIL; + } + ast_test_validate(test, test_callbacks_called.format_attribute_set == 1); + ast_test_validate(test, test_callbacks_called.format_clone == 3); + ast_test_validate(test, test_callbacks_called.format_cmp == 2); + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cmp_same_codec) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, named, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Format comparison unit test"; + info->description = + "Test comparison of two different formats with same codec"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + first = ast_format_create(codec); + if (!first) { + ast_test_status_update(test, "Could not create first format using built-in codec\n"); + return AST_TEST_FAIL; + } + + second = ast_format_create(codec); + if (!second) { + ast_test_status_update(test, "Could not create second format using built-in codec\n"); + return AST_TEST_FAIL; + } + + named = ast_format_create_named("super_ulaw", codec); + if (!named) { + ast_test_status_update(test, "Could not create named format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cmp(first, second) != AST_FORMAT_CMP_EQUAL) { + ast_test_status_update(test, "Two formats that are the same compared as not being equal\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cmp(first, named) != AST_FORMAT_CMP_EQUAL) { + ast_test_status_update(test, "Two formats that are the same compared as not being equal\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cmp_different_codec) +{ + RAII_VAR(struct ast_codec *, first_codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, second_codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Format comparison unit test"; + info->description = + "Test comparison of two different formats with different codec"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + first_codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!first_codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + first = ast_format_create(first_codec); + if (!first) { + ast_test_status_update(test, "Could not create first format using built-in codec\n"); + return AST_TEST_FAIL; + } + + second_codec = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!second_codec) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + second = ast_format_create(second_codec); + if (!second) { + ast_test_status_update(test, "Could not create second format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cmp(first, second) != AST_FORMAT_CMP_NOT_EQUAL) { + ast_test_status_update(test, "Two formats that have different codecs did not compare as being not equal\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_attr_cmp_same_codec) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, original, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Format with attributes comparison unit test"; + info->description = + "Test comparison of two different formats with attributes with same codec"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } + + original = ast_format_create(codec); + if (!original) { + ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } + + first = ast_format_attribute_set(original, "one", "1"); + if (!first) { + ast_test_status_update(test, "Could not create first format with attributes\n"); + return AST_TEST_FAIL; + } + + second = ast_format_attribute_set(original, "two", "1"); + if (!second) { + ast_test_status_update(test, "Could not create second format with attributes\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cmp(first, second) == AST_FORMAT_CMP_EQUAL) { + ast_test_status_update(test, "Formats with different attributes were compared to be equal when they should not\n"); + return AST_TEST_FAIL; + } + + ao2_ref(second, -1); + second = ast_format_attribute_set(original, "one", "1"); + + if (ast_format_cmp(first, second) != AST_FORMAT_CMP_EQUAL) { + ast_test_status_update(test, "Formats with the same attributes should be equal\n"); + return AST_TEST_FAIL; + } + + ast_test_validate(test, test_callbacks_called.format_attribute_set == 3); + ast_test_validate(test, test_callbacks_called.format_cmp == 2); + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_joint_same_codec) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Joint format unit test"; + info->description = + "Test joint format creation using two different formats with same codec"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + first = ast_format_create(codec); + if (!first) { + ast_test_status_update(test, "Could not create first format using built-in codec\n"); + return AST_TEST_FAIL; + } + + second = ast_format_create(codec); + if (!second) { + ast_test_status_update(test, "Could not create second format using built-in codec\n"); + return AST_TEST_FAIL; + } + + joint = ast_format_joint(first, second); + if (!joint) { + ast_test_status_update(test, "Failed to create a joint format using two formats of same codec\n"); + return AST_TEST_FAIL; + } else if (ast_format_get_codec_id(joint) != codec->id) { + ast_test_status_update(test, "Returned joint format does not contain expected codec\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_attr_joint_same_codec) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, original, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup); + struct ast_str *fmtp = ast_str_alloca(64); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Joint format attribute unit test"; + info->description = + "Test joint format creation using two different formats with attributes and with same codec"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } + + original = ast_format_create(codec); + if (!original) { + ast_test_status_update(test, "Could not create format from test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } + + first = ast_format_attribute_set(original, "one", "2"); + if (!first) { + ast_test_status_update(test, "Could not create first format using test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } + + second = ast_format_attribute_set(original, "one", "5"); + if (!second) { + ast_test_status_update(test, "Could not create second format using test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } + + joint = ast_format_joint(first, second); + if (!joint) { + ast_test_status_update(test, "Failed to create a joint format using two formats of same codec\n"); + return AST_TEST_FAIL; + } else if (ast_format_get_codec_id(joint) != codec->id) { + ast_test_status_update(test, "Returned joint format does not contain expected codec\n"); + return AST_TEST_FAIL; + } + + ast_format_generate_sdp_fmtp(joint, 100, &fmtp); + ast_test_validate(test, strcmp("a=fmtp:100 one=5;two=0\r\n", ast_str_buffer(fmtp)) == 0); + + ast_test_validate(test, test_callbacks_called.format_attribute_set == 2); + ast_test_validate(test, test_callbacks_called.format_get_joint == 1); + ast_test_validate(test, test_callbacks_called.format_generate_sdp_fmtp == 1); + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_joint_different_codec) +{ + RAII_VAR(struct ast_codec *, first_codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, second_codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, first, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, second, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, joint, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Joint format unit test"; + info->description = + "Test that there is no joint format between two different formats with different codec"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + first_codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!first_codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + first = ast_format_create(first_codec); + if (!first) { + ast_test_status_update(test, "Could not create first format using built-in codec\n"); + return AST_TEST_FAIL; + } + + second_codec = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!second_codec) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + second = ast_format_create(second_codec); + if (!second) { + ast_test_status_update(test, "Could not create second format using built-in codec\n"); + return AST_TEST_FAIL; + } + + joint = ast_format_joint(first, second); + if (joint) { + ast_test_status_update(test, "Got a joint format between two formats with different codecs\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_copy) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, copy, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Format copying unit test"; + info->description = + "Test copying of a format"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create(codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } + + copy = ao2_bump(format); + if (!copy) { + ast_test_status_update(test, "Copying of a just created format failed\n"); + return AST_TEST_FAIL; + } else if (copy != format) { + ast_test_status_update(test, "Copying of a format returned a new format instead of the same one\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_attribute_set_without_interface) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Format attribute setting unit test"; + info->description = + "Test that attribute setting on a format without an interface fails"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create(codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (!ast_format_attribute_set(format, "bees", "cool")) { + ast_test_status_update(test, "Successfully set an attribute on a format without an interface\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_parse_sdp_fmtp_without_interface) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, generated, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Format sdp parse unit test"; + info->description = + "Test that sdp parsing on a format without an interface fails"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create(codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } + + generated = ast_format_parse_sdp_fmtp(format, "tacos"); + if (generated != format) { + ast_test_status_update(test, "Successfully parsed SDP on a format without an interface\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_parse_and_generate_sdp_fmtp) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, generated, NULL, ao2_cleanup); + struct ast_str *fmtp = ast_str_alloca(64); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = TEST_CATEGORY; + info->summary = "Format sdp parse/generate unit test"; + info->description = + "Test that sdp parsing and generation on a format with an interface succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("test_core_format_codec", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create(codec); + if (!format) { + ast_test_status_update(test, "Could not create format using test_core_format_codec codec\n"); + return AST_TEST_FAIL; + } + + generated = ast_format_parse_sdp_fmtp(format, "one=1000;two=256"); + if (format == generated) { + ast_test_status_update(test, "Failed to parse SDP on a format without an interface\n"); + return AST_TEST_FAIL; + } + + ast_format_generate_sdp_fmtp(generated, 8, &fmtp); + + ast_test_validate(test, strcmp("a=fmtp:8 one=1000;two=256\r\n", ast_str_buffer(fmtp)) == 0); + ast_test_validate(test, test_callbacks_called.format_parse_sdp_fmtp == 1); + ast_test_validate(test, test_callbacks_called.format_generate_sdp_fmtp == 1); + + return AST_TEST_PASS; +} + +static int test_core_format_init(struct ast_test_info *info, struct ast_test *test) +{ + memset(&test_callbacks_called, 0, sizeof(test_callbacks_called)); + + return 0; +} + +static int unload_module(void) +{ + AST_TEST_UNREGISTER(format_create); + AST_TEST_UNREGISTER(format_create_attr); + AST_TEST_UNREGISTER(format_clone); + AST_TEST_UNREGISTER(format_cmp_same_codec); + AST_TEST_UNREGISTER(format_attr_cmp_same_codec); + AST_TEST_UNREGISTER(format_cmp_different_codec); + AST_TEST_UNREGISTER(format_joint_same_codec); + AST_TEST_UNREGISTER(format_attr_joint_same_codec); + AST_TEST_UNREGISTER(format_joint_different_codec); + AST_TEST_UNREGISTER(format_copy); + AST_TEST_UNREGISTER(format_attribute_set_without_interface); + AST_TEST_UNREGISTER(format_parse_sdp_fmtp_without_interface); + AST_TEST_UNREGISTER(format_parse_and_generate_sdp_fmtp); + + return 0; +} + +static int load_module(void) +{ + /* Test codec/format interface used by this module */ + if (ast_codec_register(&test_core_format_codec)) { + ast_log(AST_LOG_ERROR, "Failed to register test_core_format_codec\n"); + return AST_MODULE_LOAD_DECLINE; + } + + if (ast_format_interface_register("test_core_format_codec", &test_core_format_attr)) { + ast_log(AST_LOG_ERROR, "Failed to register format interface for test_core_format_codec\n"); + return AST_MODULE_LOAD_DECLINE; + } + + AST_TEST_REGISTER(format_create); + AST_TEST_REGISTER(format_create_attr); + AST_TEST_REGISTER(format_clone); + AST_TEST_REGISTER(format_cmp_same_codec); + AST_TEST_REGISTER(format_attr_cmp_same_codec); + AST_TEST_REGISTER(format_cmp_different_codec); + AST_TEST_REGISTER(format_joint_same_codec); + AST_TEST_REGISTER(format_attr_joint_same_codec); + AST_TEST_REGISTER(format_joint_different_codec); + AST_TEST_REGISTER(format_copy); + AST_TEST_REGISTER(format_attribute_set_without_interface); + AST_TEST_REGISTER(format_parse_sdp_fmtp_without_interface); + AST_TEST_REGISTER(format_parse_and_generate_sdp_fmtp); + + ast_test_register_init(TEST_CATEGORY, &test_core_format_init); + + return AST_MODULE_LOAD_SUCCESS; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Core format API test module"); diff --git a/tests/test_format_api.c b/tests/test_format_api.c deleted file mode 100644 index 6cc349570..000000000 --- a/tests/test_format_api.c +++ /dev/null @@ -1,859 +0,0 @@ -/* - * Asterisk -- An open source telephony toolkit. - * - * Copyright (C) 2010, Digium, Inc. - * - * David Vossel <dvossel@digium.com> - * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ - -/*! - * \file - * \brief Tests for the ast_event API - * - * \author David Vossel <dvossel@digium.com> - * - * \ingroup tests - * - */ - -/*** MODULEINFO - <depend>TEST_FRAMEWORK</depend> - <support_level>core</support_level> - ***/ - -#include "asterisk.h" - -ASTERISK_FILE_VERSION(__FILE__, "$Revision$") - -#include "asterisk/module.h" -#include "asterisk/test.h" -#include "asterisk/format.h" -#include "asterisk/format_cap.h" -#include "asterisk/strings.h" - -/*! These are the keys for accessing attributes */ -enum test_attr_keys { - TEST_ATTR_KEY_SAMP_RATE, - TEST_ATTR_KEY_STRING, -}; - -/*! These are the values for the TEST_ATTR_KEY_SAMP_RATE key */ -enum test_attr_vals_samp { - TEST_ATTR_VAL_SAMP_8KHZ = (1 << 0), - TEST_ATTR_VAL_SAMP_12KHZ = (1 << 1), - TEST_ATTR_VAL_SAMP_16KHZ = (1 << 2), - TEST_ATTR_VAL_SAMP_32KHZ = (1 << 3), - TEST_ATTR_VAL_SAMP_48KHZ = (1 << 4), -}; - -/*! This is the attribute structure used for our test interface. */ -struct test_attr { - enum test_attr_vals_samp samp_flags; - char string[32]; -}; - -static enum ast_format_cmp_res test_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2) -{ - struct test_attr *attr1 = (struct test_attr *) fattr1; - struct test_attr *attr2 = (struct test_attr *) fattr2; - - if ((attr1->samp_flags == attr2->samp_flags) && - !(strcmp(attr1->string, attr2->string))) { - return AST_FORMAT_CMP_EQUAL; - } - if ((attr1->samp_flags != (attr1->samp_flags & attr2->samp_flags)) || - (!ast_strlen_zero(attr1->string) && strcmp(attr1->string, attr2->string))) { - return AST_FORMAT_CMP_NOT_EQUAL; - } - return AST_FORMAT_CMP_SUBSET; -} - -static int test_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result) -{ - struct test_attr *attr1 = (struct test_attr *) fattr1; - struct test_attr *attr2 = (struct test_attr *) fattr2; - struct test_attr *attr_res = (struct test_attr *) result; - int joint = -1; - - attr_res->samp_flags = (attr1->samp_flags & attr2->samp_flags); - - if (attr_res->samp_flags) { - joint = 0; - } - - if (!strcmp(attr1->string, attr2->string)) { - ast_copy_string(attr_res->string, attr1->string, sizeof(attr_res->string)); - joint = 0; - } - - return joint; -} - -static void test_set(struct ast_format_attr *fattr, va_list ap) -{ - enum test_attr_keys key; - struct test_attr *attr = (struct test_attr *) fattr; - char *string; - - for (key = va_arg(ap, int); - key != AST_FORMAT_ATTR_END; - key = va_arg(ap, int)) - { - switch (key) { - case TEST_ATTR_KEY_SAMP_RATE: - attr->samp_flags = (va_arg(ap, int) | attr->samp_flags); - break; - case TEST_ATTR_KEY_STRING: - string = va_arg(ap, char *); - if (!ast_strlen_zero(string)) { - ast_copy_string(attr->string, string, sizeof(attr->string)); - } - break; - default: - ast_log(LOG_WARNING, "unknown attribute type %d\n", key); - } - } -} - -/*! uLaw does not actually have any attributes associated with it. - * This is just for the purpose of testing. We are guaranteed there - * will never exist a interface for uLaw already. */ -static struct ast_format_attr_interface test_interface = { - .id = AST_FORMAT_TESTLAW, - .format_attr_cmp = test_cmp, - .format_attr_get_joint = test_getjoint, - .format_attr_set = test_set -}; - -/*! - * \internal - */ -AST_TEST_DEFINE(format_test1) -{ - struct ast_format format1 = { 0, }; - struct ast_format format2 = { 0, }; - struct ast_format joint = { 0, }; - - switch (cmd) { - case TEST_INIT: - info->name = "ast_format_test1"; - info->category = "/main/format/"; - info->summary = "Test ast_format with attributes."; - info->description = - "This test exercises the Ast Format API by creating and registering " - "a custom ast_format_attr_interface and performing various function " - "calls on ast_formats using the interface. "; - return AST_TEST_NOT_RUN; - case TEST_EXECUTE: - break; - } - - if (ast_format_attr_reg_interface(&test_interface)) { - ast_test_status_update(test, "test_interface failed to register.\n"); - return AST_TEST_FAIL; - } - - /* set a format with a single attribute. */ - ast_format_set(&format1, AST_FORMAT_TESTLAW, 1, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, - AST_FORMAT_ATTR_END); - if (ast_format_isset(&format1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, AST_FORMAT_ATTR_END)) { - ast_test_status_update(test, "format1 did not set number attribute correctly.\n"); - return AST_TEST_FAIL; - } - if (!ast_format_isset(&format1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_12KHZ, AST_FORMAT_ATTR_END)) { - ast_test_status_update(test, "format1 did not determine isset on number correctly. \n"); - return AST_TEST_FAIL; - } - - /* append the string attribute to a format with previous attributes already set */ - ast_format_append(&format1, - TEST_ATTR_KEY_STRING,"String", - AST_FORMAT_ATTR_END); - if (ast_format_isset(&format1, TEST_ATTR_KEY_STRING, "String", AST_FORMAT_ATTR_END)) { - ast_test_status_update(test, "format1 did not set string attribute correctly.\n"); - return AST_TEST_FAIL; - } - if (!ast_format_isset(&format1, TEST_ATTR_KEY_STRING, "Not a string", AST_FORMAT_ATTR_END)) { - ast_test_status_update(test, "format1 did not determine isset on string correctly. \n"); - return AST_TEST_FAIL; - } - - /* set format2 with both STRING and NUMBER at the same time */ - ast_format_set(&format2, AST_FORMAT_TESTLAW, 1, - TEST_ATTR_KEY_STRING, "MOOOoo", - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, - AST_FORMAT_ATTR_END); - /* perform isset with multiple key value pairs. */ - - if (ast_format_isset(&format2, - TEST_ATTR_KEY_STRING, "MOOOoo", - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, - AST_FORMAT_ATTR_END)) { - - ast_test_status_update(test, "format2 did not set attributes correctly.\n"); - return AST_TEST_FAIL; - } - if (!ast_format_isset(&format2, - TEST_ATTR_KEY_STRING, "WRONG", - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, - AST_FORMAT_ATTR_END)) { - - ast_test_status_update(test, "format2 did not deterine isset correctly.\n"); - return AST_TEST_FAIL; - } - - /* get joint attributes between format1 and format2. */ - if (ast_format_joint(&format1, &format2, &joint)) { - ast_test_status_update(test, "failed to get joint attributes.\n"); - return AST_TEST_FAIL; - } - if (ast_format_isset(&joint, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, AST_FORMAT_ATTR_END)) { - ast_test_status_update(test, "joint attribute was not what we expected.\n"); - return AST_TEST_FAIL; - } - - /* exercise compare functions */ - if (ast_format_cmp(&format1, &format2) != AST_FORMAT_CMP_NOT_EQUAL) { - ast_test_status_update(test, "cmp 1 failed.\n"); - return AST_TEST_FAIL; - } - if (ast_format_cmp(&format1, &format1) != AST_FORMAT_CMP_EQUAL) { - ast_test_status_update(test, "cmp 2 failed.\n"); - return AST_TEST_FAIL; - } - if (ast_format_cmp(&joint, &format1) != AST_FORMAT_CMP_SUBSET) { - ast_test_status_update(test, "cmp 3 failed.\n"); - return AST_TEST_FAIL; - } - - /* unregister interface */ - if (ast_format_attr_unreg_interface(&test_interface)) { - ast_test_status_update(test, "test_interface failed to unregister.\n"); - return AST_TEST_FAIL; - } - - return AST_TEST_PASS; -} - -/*! - * \internal - */ -AST_TEST_DEFINE(format_test2) -{ - struct ast_format format = { 0, }; - - switch (cmd) { - case TEST_INIT: - info->name = "ast_format_test2"; - info->category = "/main/format/"; - info->summary = "Test ast_format unique id and category system"; - info->description = - "This test exercises the Ast Format unique id and category " - "system by creating formats of various types and verifying " - "their category matches what we expect."; - return AST_TEST_NOT_RUN; - case TEST_EXECUTE: - break; - } - - ast_format_set(&format, AST_FORMAT_ULAW, 0); - if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_AUDIO) { - ast_test_status_update(test, "audio type failed\n"); - return AST_TEST_FAIL; - } - - ast_format_set(&format, AST_FORMAT_H264, 0); - if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_VIDEO) { - ast_test_status_update(test, "video type failed\n"); - return AST_TEST_FAIL; - } - - ast_format_set(&format, AST_FORMAT_JPEG, 0); - if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_IMAGE) { - ast_test_status_update(test, "image type failed\n"); - return AST_TEST_FAIL; - } - - ast_format_set(&format, AST_FORMAT_T140, 0); - if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_TEXT) { - ast_test_status_update(test, "text type failed\n"); - return AST_TEST_FAIL; - } - - return AST_TEST_PASS; -} - -static int container_test1_helper(struct ast_format_cap *cap1, struct ast_format_cap *cap2, struct ast_test *test) -{ - - int res = AST_TEST_PASS; - struct ast_format_cap *cap_joint = NULL; - struct ast_format tmpformat; - - if (ast_format_attr_reg_interface(&test_interface)) { - ast_test_status_update(test, "test_interface failed to register.\n"); - ast_format_cap_destroy(cap1); - ast_format_cap_destroy(cap2); - return AST_TEST_FAIL; - } - - ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)); - ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)); - ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_G722, 0)); - ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)); - ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)); - ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H263, 0)); - ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)); - ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)); - ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, - TEST_ATTR_KEY_STRING, "testing caps hooray", - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ, - AST_FORMAT_ATTR_END)); - - /* Test is compatible */ - if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) || - !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || - !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || - !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) || - !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) || - !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { - ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 1.\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - - /* Test things that are not compatible */ - if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX, 0)) || - ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX16, 0)) || - ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H261, 0))) { - ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 2.\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - - /* Test compatiblity with format with attributes. */ - if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, - TEST_ATTR_KEY_STRING, "testing caps hooray", - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, - AST_FORMAT_ATTR_END))) { - - ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 3.\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, - AST_FORMAT_ATTR_END))) { - - ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 4.\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, /* 48khz was not compatible, so this should fail iscompatible check */ - AST_FORMAT_ATTR_END))) { - - ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 5.\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - - /* Lets start testing the functions that compare ast_format_cap objects. - * Genreate the cap2 object to contain some similar formats as cap1 - * and some different formats as well. */ - ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)); - ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)); - ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0)); - ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_H261, 0)); - ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)); - ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, - TEST_ATTR_KEY_STRING, "testing caps hooray", - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_12KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, - AST_FORMAT_ATTR_END)); - - - /* find joint formats between cap1 and cap2 */ - cap_joint = ast_format_cap_joint(cap1, cap2); - - if (!cap_joint) { - ast_test_status_update(test, "failed to create joint capabilities correctly.\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - /* determine if cap_joint is what we think it should be */ - if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || - !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || - !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)) || - !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, - TEST_ATTR_KEY_STRING, "testing caps hooray", - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, - AST_FORMAT_ATTR_END))) { - - ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - /* make sure joint cap does not have formats that should not be there */ - if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0)) || - ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, - TEST_ATTR_KEY_STRING, "testing caps hooray", - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, - TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, - AST_FORMAT_ATTR_END))) { - - ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - - /* Lets test removing a capability */ - if (ast_format_cap_remove(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { - ast_test_status_update(test, "ast_format_cap_remove failed. \n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - /* Lets make sure what we just removed does not still exist */ - if (ast_format_cap_iscompatible(cap_joint, &tmpformat)) { - ast_test_status_update(test, "ast_format_cap_remove failed 2. \n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - /* Lets test removing a capability by id.*/ - if (ast_format_cap_remove_byid(cap_joint, AST_FORMAT_GSM)) { - ast_test_status_update(test, "ast_format_cap_remove failed 3. \n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - /* Lets make sure what we just removed does not still exist */ - if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0))) { - ast_test_status_update(test, "ast_format_cap_remove failed 4. \n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - - /* lets test getting joint formats by type */ - ast_format_cap_destroy(cap_joint); - if (!(cap_joint = ast_format_cap_get_type(cap1, AST_FORMAT_TYPE_VIDEO))) { - ast_test_status_update(test, "ast_format_cap_get_type failed.\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - /* lets make sure our joint capability structure has what we expect */ - if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) || - !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H263, 0))) { - ast_test_status_update(test, "get_type failed 2.\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - /* now make sure joint does not have anything but video */ - if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) || - ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || - ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || - ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) || - ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { - ast_test_status_update(test, "get_type failed 3.\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - - /* now lets remove everythign from cap_joint */ - ast_format_cap_remove_all(cap_joint); - if (!ast_format_cap_is_empty(cap_joint)) { - ast_test_status_update(test, "failed to remove all\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - - /* now lets add all by type */ - ast_format_cap_add_all_by_type(cap_joint, AST_FORMAT_TYPE_AUDIO); - if (ast_format_cap_is_empty(cap_joint)) { - ast_test_status_update(test, "failed to add all by type AUDIO\n"); - res = AST_TEST_FAIL; - } - ast_format_cap_iter_start(cap_joint); - while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { - if (AST_FORMAT_GET_TYPE(tmpformat.id) != AST_FORMAT_TYPE_AUDIO) { - ast_test_status_update(test, "failed to add all by type AUDIO\n"); - res = AST_TEST_FAIL; - ast_format_cap_iter_end(cap_joint); - goto test3_cleanup; - } - } - ast_format_cap_iter_end(cap_joint); - - /* test append */ - ast_format_cap_append(cap_joint, cap1); - ast_format_cap_iter_start(cap1); - while (!(ast_format_cap_iter_next(cap1, &tmpformat))) { - if (!ast_format_cap_iscompatible(cap_joint, &tmpformat)) { - ast_test_status_update(test, "failed to append format capabilities.\n"); - res = AST_TEST_FAIL; - ast_format_cap_iter_end(cap1); - goto test3_cleanup; - } - } - ast_format_cap_iter_end(cap1); - - /* test copy */ - cap1 = ast_format_cap_destroy(cap1); - cap1 = ast_format_cap_dup(cap_joint); - if (!ast_format_cap_identical(cap_joint, cap1)) { - ast_test_status_update(test, "failed to copy capabilities\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - - /* test remove by type */ - ast_format_cap_remove_bytype(cap_joint, AST_FORMAT_TYPE_AUDIO); - if (ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_AUDIO)) { - ast_test_status_update(test, "failed to remove all by type audio\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - if (!ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_TEXT)) { /* it should still have text */ - ast_test_status_update(test, "failed to remove all by type audio\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - ast_format_cap_iter_start(cap_joint); - while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { - if (AST_FORMAT_GET_TYPE(tmpformat.id) == AST_FORMAT_TYPE_AUDIO) { - ast_test_status_update(test, "failed to remove all by type audio\n"); - res = AST_TEST_FAIL; - ast_format_cap_iter_end(cap_joint); - goto test3_cleanup; - } - } - ast_format_cap_iter_end(cap_joint); - - /* test add all */ - ast_format_cap_remove_all(cap_joint); - ast_format_cap_add_all(cap_joint); - { - int video = 0, audio = 0, text = 0, image = 0; - ast_format_cap_iter_start(cap_joint); - while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { - switch (AST_FORMAT_GET_TYPE(tmpformat.id)) { - case AST_FORMAT_TYPE_AUDIO: - audio++; - break; - case AST_FORMAT_TYPE_VIDEO: - video++; - break; - case AST_FORMAT_TYPE_TEXT: - text++; - break; - case AST_FORMAT_TYPE_IMAGE: - image++; - break; - } - } - ast_format_cap_iter_end(cap_joint); - if (!video || !audio || !text || !image) { - ast_test_status_update(test, "failed to add all\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - } - - /* test copy2 */ - ast_format_cap_copy(cap2, cap_joint); - if (!ast_format_cap_identical(cap2, cap_joint)) { - ast_test_status_update(test, "ast_format_cap_copy failed\n"); - res = AST_TEST_FAIL; - goto test3_cleanup; - } - -test3_cleanup: - ast_format_cap_destroy(cap1); - ast_format_cap_destroy(cap2); - ast_format_cap_destroy(cap_joint); - - /* unregister interface */ - if (ast_format_attr_unreg_interface(&test_interface)) { - ast_test_status_update(test, "test_interface failed to unregister.\n"); - res = AST_TEST_FAIL; - } - - return res; -} - -/*! - * \internal - */ -AST_TEST_DEFINE(container_test1_nolock) -{ - struct ast_format_cap *cap1; - struct ast_format_cap *cap2; - - switch (cmd) { - case TEST_INIT: - info->name = "container_test_1_no_locking"; - info->category = "/main/format/"; - info->summary = "Test ast_format and ast_format_cap structures, no locking"; - info->description = - "This test exercises the Ast Format Capability API by creating " - "capability structures and performing various API calls on them."; - return AST_TEST_NOT_RUN; - case TEST_EXECUTE: - break; - } - - cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - cap2 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - - if (!cap1 || !cap2) { - ast_test_status_update(test, "cap alloc failed.\n"); - return AST_TEST_FAIL; - } - return container_test1_helper(cap1, cap2, test); -} - - -/*! - * \internal - */ -AST_TEST_DEFINE(container_test1_withlock) -{ - struct ast_format_cap *cap1; - struct ast_format_cap *cap2; - - switch (cmd) { - case TEST_INIT: - info->name = "container_test1_with_locking"; - info->category = "/main/format/"; - info->summary = "Test ast_format and ast_format_cap structures, with locking"; - info->description = - "This test exercises the Ast Format Capability API by creating " - "capability structures and performing various API calls on them."; - return AST_TEST_NOT_RUN; - case TEST_EXECUTE: - break; - } - - cap1 = ast_format_cap_alloc(0); - cap2 = ast_format_cap_alloc(0); - - if (!cap1 || !cap2) { - ast_test_status_update(test, "cap alloc failed.\n"); - return AST_TEST_FAIL; - } - return container_test1_helper(cap1, cap2, test); -} - -static int container_test2_no_locking_helper(struct ast_format_cap *cap, struct ast_test *test) -{ - int num = 0; - struct ast_format tmpformat = { 0, }; - - ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)); - ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)); - ast_format_cap_add(cap, ast_format_set(&tmpformat, AST_FORMAT_G722, 0)); - - ast_format_cap_iter_start(cap); - while (!ast_format_cap_iter_next(cap, &tmpformat)) { - num++; - } - ast_format_cap_iter_end(cap); - - ast_format_cap_iter_start(cap); - while (!ast_format_cap_iter_next(cap, &tmpformat)) { - num++; - } - ast_format_cap_iter_end(cap); - - ast_format_cap_destroy(cap); - ast_test_status_update(test, "%d items iterated over\n", num); - return (num == 6) ? AST_TEST_PASS : AST_TEST_FAIL; - -} - -/*! - * \internal - */ -AST_TEST_DEFINE(container_test2_no_locking) -{ - struct ast_format_cap *cap; - - switch (cmd) { - case TEST_INIT: - info->name = "container_test2_no_locking"; - info->category = "/main/format/"; - info->summary = "Test ast_format_cap iterator, no locking"; - info->description = - "This test exercises the Ast Capability API iterators."; - return AST_TEST_NOT_RUN; - case TEST_EXECUTE: - break; - } - - cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - if (!cap) { - ast_test_status_update(test, "alloc failed\n"); - return AST_TEST_FAIL; - } - return container_test2_no_locking_helper(cap, test); -} - -/*! - * \internal - */ -AST_TEST_DEFINE(container_test2_with_locking) -{ - struct ast_format_cap *cap; - - switch (cmd) { - case TEST_INIT: - info->name = "container_test2_with_locking"; - info->category = "/main/format/"; - info->summary = "Test ast_format_cap iterator, with locking"; - info->description = - "This test exercises the Ast Capability API iterators."; - return AST_TEST_NOT_RUN; - case TEST_EXECUTE: - break; - } - - cap = ast_format_cap_alloc(0); - if (!cap) { - ast_test_status_update(test, "alloc failed\n"); - return AST_TEST_FAIL; - } - return container_test2_no_locking_helper(cap, test); -} - - -static int container_test3_helper(int nolocking, struct ast_test *test) -{ - int x; - int res = AST_TEST_PASS; - struct ast_format_cap *cap1; - struct ast_format_cap *cap2; - struct ast_format_cap *joint; - - for (x = 0; x < 2000; x++) { - if (nolocking) { - cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - cap2 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); - } else { - cap1 = ast_format_cap_alloc(0); - cap2 = ast_format_cap_alloc(0); - joint = ast_format_cap_alloc(0); - } - if (!cap1 || !cap2 || !joint) { - ast_test_status_update(test, "cap alloc fail\n"); - return AST_TEST_FAIL; - } - ast_format_cap_add_all(cap1); - ast_format_cap_add_all_by_type(cap2, AST_FORMAT_TYPE_AUDIO); - ast_format_cap_joint_copy(cap1, cap2, joint); - if (!(ast_format_cap_identical(cap2, joint))) { - ast_test_status_update(test, "failed identical test\n"); - res = AST_TEST_FAIL; - cap1 = ast_format_cap_destroy(cap1); - cap2 = ast_format_cap_destroy(cap2); - joint = ast_format_cap_destroy(joint); - break; - } - cap1 = ast_format_cap_destroy(cap1); - cap2 = ast_format_cap_destroy(cap2); - joint = ast_format_cap_destroy(joint); - } - return res; -} - -/*! - * \internal - */ -AST_TEST_DEFINE(container_test3_nolock) -{ - switch (cmd) { - case TEST_INIT: - info->name = "container_test3_no_locking"; - info->category = "/main/format/"; - info->summary = "Load Test ast_format_cap no locking."; - info->description = - "This test exercises the Ast Capability API and its iterators for the purpose " - "of measuring performance."; - return AST_TEST_NOT_RUN; - case TEST_EXECUTE: - break; - } - - return container_test3_helper(1, test); -} - -/*! - * \internal - */ -AST_TEST_DEFINE(container_test3_withlock) -{ - switch (cmd) { - case TEST_INIT: - info->name = "container_test3_with_locking"; - info->category = "/main/format/"; - info->summary = "Load Test ast_format_cap with locking."; - info->description = - "This test exercises the Ast Capability API and its iterators for the purpose " - "of measuring performance."; - return AST_TEST_NOT_RUN; - case TEST_EXECUTE: - break; - } - - return container_test3_helper(0, test); -} - -static int unload_module(void) -{ - AST_TEST_UNREGISTER(format_test1); - AST_TEST_UNREGISTER(format_test2); - AST_TEST_UNREGISTER(container_test1_nolock); - AST_TEST_UNREGISTER(container_test1_withlock); - AST_TEST_UNREGISTER(container_test2_no_locking); - AST_TEST_UNREGISTER(container_test2_with_locking); - AST_TEST_UNREGISTER(container_test3_nolock); - AST_TEST_UNREGISTER(container_test3_withlock); - - return 0; -} - -static int load_module(void) -{ - AST_TEST_REGISTER(format_test1); - AST_TEST_REGISTER(format_test2); - AST_TEST_REGISTER(container_test1_nolock); - AST_TEST_REGISTER(container_test1_withlock); - AST_TEST_REGISTER(container_test2_no_locking); - AST_TEST_REGISTER(container_test2_with_locking); - AST_TEST_REGISTER(container_test3_nolock); - AST_TEST_REGISTER(container_test3_withlock); - - return AST_MODULE_LOAD_SUCCESS; -} - -AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ast_format API Tests"); diff --git a/tests/test_format_cache.c b/tests/test_format_cache.c new file mode 100644 index 000000000..cc1696b70 --- /dev/null +++ b/tests/test_format_cache.c @@ -0,0 +1,281 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2014, Digium, Inc. + * + * Joshua Colp <jcolp@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Format Cache API Unit Tests + * + * \author Joshua Colp <jcolp@digium.com> + * + */ + +/*** MODULEINFO + <depend>TEST_FRAMEWORK</depend> + <support_level>core</support_level> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/test.h" +#include "asterisk/module.h" +#include "asterisk/codec.h" +#include "asterisk/format.h" +#include "asterisk/format_cache.h" + +AST_TEST_DEFINE(format_cache_set) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cache_set"; + info->category = "/main/format_cache/"; + info->summary = "format cache add unit test"; + info->description = + "Test that adding of a cached format succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create_named("ulaw@20_1", codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cache_set(format)) { + ast_test_status_update(test, "Could not add just created format to cache\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cache_set_duplicate) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cache_set_duplicate"; + info->category = "/main/format_cache/"; + info->summary = "format cache add unit test"; + info->description = + "Test that adding of a cached format multiple times succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create_named("ulaw@20_2", codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cache_set(format)) { + ast_test_status_update(test, "Could not add just created format to cache\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cache_set(format)) { + ast_test_status_update(test, "Failed to update cached format\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cache_set_null) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cache_set_null"; + info->category = "/main/format_cache/"; + info->summary = "format cache add unit test"; + info->description = + "Test that adding a NULL or empty format to the cache does not succeed"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create_named("", codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (!ast_format_cache_set(format)) { + ast_test_status_update(test, "Successfully cached a format with an empty name\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cache_get) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, cached, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cache_get"; + info->category = "/main/format_cache/"; + info->summary = "format cache get unit test"; + info->description = + "Test that getting of a cached format succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create_named("ulaw@20", codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cache_set(format)) { + ast_test_status_update(test, "Could not add just created format to cache\n"); + return AST_TEST_FAIL; + } + + cached = ast_format_cache_get("ulaw@20"); + if (!cached) { + ast_test_status_update(test, "Failed to retrieve a format we just cached\n"); + return AST_TEST_FAIL; + } else if (cached != format) { + ast_test_status_update(test, "Returned cached format does not match format we just added\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cache_get_nonexistent) +{ + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, cached, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cache_get_nonxistent"; + info->category = "/main/format_cache/"; + info->summary = "format cache get unit test"; + info->description = + "Test that getting of a non-existent cached format does not succeed"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create_named("ulaw@40", codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cache_set(format)) { + ast_test_status_update(test, "Could not add just created format to cache\n"); + return AST_TEST_FAIL; + } + + cached = ast_format_cache_get("ulaw@60"); + if (cached) { + ast_test_status_update(test, "Retrieved a cached format when one should not have existed\n"); + return AST_TEST_FAIL; + } + + cached = ast_format_cache_get(""); + if (cached) { + ast_test_status_update(test, "Retrieved a cached format when we provided an empty name\n"); + return AST_TEST_FAIL; + } + + cached = ast_format_cache_get(NULL); + if (cached) { + ast_test_status_update(test, "Retrieved a cached format when we provided a NULL name\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +static int unload_module(void) +{ + AST_TEST_UNREGISTER(format_cache_set); + AST_TEST_UNREGISTER(format_cache_set_duplicate); + AST_TEST_UNREGISTER(format_cache_set_null); + AST_TEST_UNREGISTER(format_cache_get); + AST_TEST_UNREGISTER(format_cache_get_nonexistent); + return 0; +} + +static int load_module(void) +{ + AST_TEST_REGISTER(format_cache_set); + AST_TEST_REGISTER(format_cache_set_duplicate); + AST_TEST_REGISTER(format_cache_set_null); + AST_TEST_REGISTER(format_cache_get); + AST_TEST_REGISTER(format_cache_get_nonexistent); + return AST_MODULE_LOAD_SUCCESS; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Format cache API test module"); diff --git a/tests/test_format_cap.c b/tests/test_format_cap.c new file mode 100644 index 000000000..38320e635 --- /dev/null +++ b/tests/test_format_cap.c @@ -0,0 +1,1479 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2014, Digium, Inc. + * + * Joshua Colp <jcolp@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Format Capabilities API Unit Tests + * + * \author Joshua Colp <jcolp@digium.com> + * + */ + +/*** MODULEINFO + <depend>TEST_FRAMEWORK</depend> + <support_level>core</support_level> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/test.h" +#include "asterisk/module.h" +#include "asterisk/codec.h" +#include "asterisk/frame.h" +#include "asterisk/format.h" +#include "asterisk/format_cap.h" + +AST_TEST_DEFINE(format_cap_alloc) +{ + struct ast_format_cap *caps; + + switch (cmd) { + case TEST_INIT: + info->name = "format_cap_alloc"; + info->category = "/main/format_cap/"; + info->summary = "format capabilities allocation unit test"; + info->description = + "Test that allocation of a format capabilities structure succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + ao2_ref(caps, -1); + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_append_single) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = "/main/format_cap/"; + info->summary = "format capabilities adding unit test"; + info->description = + "Test that adding a single format to a format capabilities structure succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create(codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(caps, format, 42)) { + ast_test_status_update(test, "Could not add newly created format to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_count(caps) != 1) { + ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n", + ast_format_cap_count(caps)); + return AST_TEST_FAIL; + } + + retrieved = ast_format_cap_get_format(caps, 0); + if (!retrieved) { + ast_test_status_update(test, "Attempted to get single format from capabilities structure but got nothing\n"); + return AST_TEST_FAIL; + } else if (retrieved != format) { + ast_test_status_update(test, "Retrieved format is not the same as the one we added\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_get_format_framing(caps, retrieved) != 42) { + ast_test_status_update(test, "Framing for format in capabilities structure does not match what we provided\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_append_multiple) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = "/main/format_cap/"; + info->summary = "format capabilities adding unit test"; + info->description = + "Test that adding multiple formats to a format capabilities structure succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!ulaw) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + ulaw_format = ast_format_create(ulaw); + if (!ulaw_format) { + ast_test_status_update(test, "Could not create ulaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!alaw) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + alaw_format = ast_format_create(alaw); + if (!alaw_format) { + ast_test_status_update(test, "Could not create alaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(caps, ulaw_format, 42)) { + ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append(caps, alaw_format, 84)) { + ast_test_status_update(test, "Could not add newly created alaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_count(caps) != 2) { + ast_test_status_update(test, "Number of formats in capabilities structure should be 2 but is %zu\n", + ast_format_cap_count(caps)); + return AST_TEST_FAIL; + } + + retrieved = ast_format_cap_get_format(caps, 0); + if (!retrieved) { + ast_test_status_update(test, "Attempted to get first format from capabilities structure but got nothing\n"); + return AST_TEST_FAIL; + } else if (retrieved != ulaw_format) { + ast_test_status_update(test, "First retrieved format is not the ulaw one we added\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_get_format_framing(caps, retrieved) != 42) { + ast_test_status_update(test, "Framing for ulaw format in capabilities structure does not match what we provided\n"); + } + ao2_ref(retrieved, -1); + + retrieved = ast_format_cap_get_format(caps, 1); + if (!retrieved) { + ast_test_status_update(test, "Attempted to get second format from capabilities structure but got nothing\n"); + return AST_TEST_FAIL; + } else if (retrieved != alaw_format) { + ast_test_status_update(test, "First retrieved format is not the alaw one we added\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_get_format_framing(caps, retrieved) != 84) { + ast_test_status_update(test, "Framing for alaw format in capabilities structure does not match what we provided\n"); + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_append_all_unknown) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = "/main/format_cap/"; + info->summary = "format capabilities adding unit test"; + info->description = + "Test that adding of all formats to a format capabilities structure succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_UNKNOWN)) { + ast_test_status_update(test, "Failed to add all media formats of all types to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_AUDIO)) { + ast_test_status_update(test, "Added all media formats but no audio formats exist when they should\n"); + return AST_TEST_FAIL; + } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_VIDEO)) { + ast_test_status_update(test, "Added all media formats but no video formats exist when they should\n"); + return AST_TEST_FAIL; + } else if ((ast_format_cap_count(caps) + 1) != ast_codec_get_max()) { + ast_test_status_update(test, "The number of formats in the capabilities structure does not match known number\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_append_all_audio) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = "/main/format_cap/"; + info->summary = "format capabilities adding unit test"; + info->description = + "Test that adding of all audio formats to a format capabilities structure succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_AUDIO)) { + ast_test_status_update(test, "Failed to add all audio media formats to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_AUDIO)) { + ast_test_status_update(test, "Added audio media formats but no audio formats exist when they should\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_VIDEO)) { + ast_test_status_update(test, "Added only audio media formats but video formats exist when they should not\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_TEXT)) { + ast_test_status_update(test, "Added only audio media formats but text formats exist when they should not\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_IMAGE)) { + ast_test_status_update(test, "Added only audio media formats but image formats exist when they should not\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_append_duplicate) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format_named, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = "/main/format_cap/"; + info->summary = "format capabilities duplication unit test"; + info->description = + "Test that adding a single format multiple times to a capabilities structure results in only a single format"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create(codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } + + format_named = ast_format_create_named("ulaw@20", codec); + if (!format_named) { + ast_test_status_update(test, "Could not create named format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(caps, format, 42)) { + ast_test_status_update(test, "Could not add newly created format to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_count(caps) != 1) { + ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n", + ast_format_cap_count(caps)); + return AST_TEST_FAIL; + } + + /* Note: regardless of it being a duplicate, ast_format_cap_append should return success */ + if (ast_format_cap_append(caps, format, 0)) { + ast_test_status_update(test, "Adding of duplicate format to capabilities structure failed\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_count(caps) != 1) { + ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n", + ast_format_cap_count(caps)); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(caps, format_named, 0)) { + ast_test_status_update(test, "Adding of duplicate named format to capabilities structure failed\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_count(caps) != 1) { + ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n", + ast_format_cap_count(caps)); + return AST_TEST_FAIL; + } + + retrieved = ast_format_cap_get_format(caps, 0); + if (!retrieved) { + ast_test_status_update(test, "Attempted to get single format from capabilities structure but got nothing\n"); + return AST_TEST_FAIL; + } else if (retrieved != format) { + ast_test_status_update(test, "Retrieved format is not the same as the one we added\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_get_format_framing(caps, retrieved) != 42) { + ast_test_status_update(test, "Framing for format in capabilities structure does not match what we provided\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_append_from_cap) +{ + RAII_VAR(struct ast_format_cap *, dst_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_format_cap *, src_caps, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = "/main/format_cap/"; + info->summary = "format capabilities append unit test"; + info->description = + "Test that appending video formats from one capabilities structure to another succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + dst_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!dst_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append_by_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) { + ast_test_status_update(test, "Failed to add all audio media formats to capabilities structure\n"); + return AST_TEST_FAIL; + } + + src_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!src_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append_by_type(src_caps, AST_MEDIA_TYPE_VIDEO)) { + ast_test_status_update(test, "Failed to add all video media formats to capabilities structure\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append_from_cap(dst_caps, src_caps, AST_MEDIA_TYPE_UNKNOWN)) { + ast_test_status_update(test, "Failed to append formats to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) { + ast_test_status_update(test, "Successfully appended video formats to destination capabilities but it no longer contains audio formats\n"); + return AST_TEST_FAIL; + } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_VIDEO)) { + ast_test_status_update(test, "Successfully appended formats but video formats do not exist in destination capabilities\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_append_from_cap_duplicate) +{ + RAII_VAR(struct ast_format_cap *, dst_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_format_cap *, src_caps, NULL, ao2_cleanup); + unsigned int count; + unsigned int total_count; + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = "/main/format_cap/"; + info->summary = "format capabilities append duplicate unit test"; + info->description = + "Test that appending capabilities structures multiple times does not result in duplicate formats"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + dst_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!dst_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append_by_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) { + ast_test_status_update(test, "Failed to add all audio media formats to capabilities structure\n"); + return AST_TEST_FAIL; + } + + src_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!src_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append_by_type(src_caps, AST_MEDIA_TYPE_VIDEO)) { + ast_test_status_update(test, "Failed to add all video media formats to capabilities structure\n"); + return AST_TEST_FAIL; + } + + total_count = ast_format_cap_count(src_caps) + ast_format_cap_count(dst_caps); + + if (ast_format_cap_append_from_cap(dst_caps, src_caps, AST_MEDIA_TYPE_UNKNOWN)) { + ast_test_status_update(test, "Failed to append formats to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_AUDIO)) { + ast_test_status_update(test, "Successfully appended video formats to destination capabilities but it no longer contains audio formats\n"); + return AST_TEST_FAIL; + } else if (!ast_format_cap_has_type(dst_caps, AST_MEDIA_TYPE_VIDEO)) { + ast_test_status_update(test, "Successfully appended formats but video formats do not exist in destination capabilities\n"); + return AST_TEST_FAIL; + } + + count = ast_format_cap_count(dst_caps); + + if (ast_format_cap_append_from_cap(dst_caps, src_caps, AST_MEDIA_TYPE_UNKNOWN)) { + ast_test_status_update(test, "Failed to append duplicate formats to capabilities structure\n"); + return AST_TEST_FAIL; + } + + ast_test_validate(test, count == ast_format_cap_count(dst_caps)); + ast_test_validate(test, count == total_count); + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_set_framing) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cap_set_framing"; + info->category = "/main/format_cap/"; + info->summary = "format capabilities framing unit test"; + info->description = + "Test that global framing on a format capabilities structure is used when it should be"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ast_format_cap_set_framing(caps, 160); + + ast_test_validate(test, ast_format_cap_get_framing(caps) == 160); + + ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!ulaw) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + ulaw_format = ast_format_create(ulaw); + if (!ulaw_format) { + ast_test_status_update(test, "Could not create ulaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!alaw) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + alaw_format = ast_format_create(alaw); + if (!alaw_format) { + ast_test_status_update(test, "Could not create alaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(caps, ulaw_format, 42)) { + ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append(caps, alaw_format, 0)) { + ast_test_status_update(test, "Could not add newly created alaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_get_format_framing(caps, ulaw_format) != 42) { + ast_test_status_update(test, "Added ulaw format to capabilities structure with explicit framing but did not get it back\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_get_format_framing(caps, alaw_format) != ast_format_get_default_ms(alaw_format)) { + ast_test_status_update(test, "Added alaw format to capabilities structure with no explicit framing but did not get global back\n"); + return AST_TEST_FAIL; + } + ast_test_validate(test, ast_format_cap_get_framing(caps) == ast_format_get_default_ms(alaw_format)); + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_remove_single) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, codec, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cap_remove_single"; + info->category = "/main/format_cap/"; + info->summary = "format capabilities removal unit test"; + info->description = + "Test that removing a single format from a format capabilities structure succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + codec = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!codec) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + format = ast_format_create(codec); + if (!format) { + ast_test_status_update(test, "Could not create format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(caps, format, 42)) { + ast_test_status_update(test, "Could not add newly created format to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_remove(caps, format)) { + ast_test_status_update(test, "Could not remove format that was just added to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (!ast_format_cap_remove(caps, format)) { + ast_test_status_update(test, "Successfully removed a format twice from the capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_count(caps)) { + ast_test_status_update(test, "Capabilities structure should be empty but instead it contains '%zu' formats\n", + ast_format_cap_count(caps)); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_remove_multiple) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, retrieved, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cap_remove_multiple"; + info->category = "/main/format_cap/"; + info->summary = "format capabilities removal unit test"; + info->description = + "Test that removing a format from a format capabilities structure containing multiple formats succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!ulaw) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + ulaw_format = ast_format_create(ulaw); + if (!ulaw_format) { + ast_test_status_update(test, "Could not create ulaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!alaw) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + alaw_format = ast_format_create(alaw); + if (!alaw_format) { + ast_test_status_update(test, "Could not create alaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(caps, ulaw_format, 42)) { + ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append(caps, alaw_format, 84)) { + ast_test_status_update(test, "Could not add newly created alaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_remove(caps, ulaw_format)) { + ast_test_status_update(test, "Could not remove the ulaw format we just added to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_count(caps) != 1) { + ast_test_status_update(test, "Capabilities structure should contain 1 format but it contains '%zu'\n", + ast_format_cap_count(caps)); + return AST_TEST_FAIL; + } + + retrieved = ast_format_cap_get_format(caps, 0); + if (!retrieved) { + ast_test_status_update(test, "Attempted to get first format from capabilities structure but got nothing\n"); + return AST_TEST_FAIL; + } else if (retrieved != alaw_format) { + ast_test_status_update(test, "First retrieved format is not the alaw one we added\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_remove_bytype) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cap_remove_bytype"; + info->category = "/main/format_cap/"; + info->summary = "format capabilities removal unit test"; + info->description = + "Test that removal of a specific type of format from a format capabilities structure succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_UNKNOWN)) { + ast_test_status_update(test, "Failed to add all media formats of all types to capabilities structure\n"); + return AST_TEST_FAIL; + } + + ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO); + if (ast_format_cap_has_type(caps, AST_MEDIA_TYPE_AUDIO)) { + ast_test_status_update(test, "Removed all audio type formats from capabilities structure but some remain\n"); + return AST_TEST_FAIL; + } else if (!ast_format_cap_has_type(caps, AST_MEDIA_TYPE_VIDEO)) { + ast_test_status_update(test, "Removed audio type formats from capabilities structure but video are gone as well\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_remove_all) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cap_remove_all"; + info->category = "/main/format_cap/"; + info->summary = "format capabilities removal unit test"; + info->description = + "Test that removal of all formats from a format capabilities structure succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append_by_type(caps, AST_MEDIA_TYPE_UNKNOWN)) { + ast_test_status_update(test, "Failed to add all media formats of all types to capabilities structure\n"); + return AST_TEST_FAIL; + } + + ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_UNKNOWN); + + if (ast_format_cap_count(caps)) { + ast_test_status_update(test, "Removed all formats from capabilities structure but some remain\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_get_compatible_format) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, compatible, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cap_get_compatible_format"; + info->category = "/main/format_cap/"; + info->summary = "format capabilities negotiation unit test"; + info->description = + "Test that getting a compatible format from a capabilities structure succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!ulaw) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + ulaw_format = ast_format_create(ulaw); + if (!ulaw_format) { + ast_test_status_update(test, "Could not create ulaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!alaw) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + alaw_format = ast_format_create(alaw); + if (!alaw_format) { + ast_test_status_update(test, "Could not create alaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(caps, ulaw_format, 42)) { + ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } + + compatible = ast_format_cap_get_compatible_format(caps, alaw_format); + if (compatible) { + ast_test_status_update(test, "Retrieved a compatible format from capabilities structure when none should exist\n"); + return AST_TEST_FAIL; + } + + compatible = ast_format_cap_get_compatible_format(caps, ulaw_format); + if (!compatible) { + ast_test_status_update(test, "Did not retrieve a compatible format from capabilities structure when there should be one\n"); + return AST_TEST_FAIL; + } else if (compatible != ulaw_format) { + ast_test_status_update(test, "Compatible format is not the format we added to the capabilities structure\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_iscompatible_format) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cap_iscompatible_format"; + info->category = "/main/format_cap/"; + info->summary = "format capabilities negotiation unit test"; + info->description = + "Test that checking whether a format is compatible with a capabilities structure succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!ulaw) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + ulaw_format = ast_format_create(ulaw); + if (!ulaw_format) { + ast_test_status_update(test, "Could not create ulaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!alaw) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + alaw_format = ast_format_create(alaw); + if (!alaw_format) { + ast_test_status_update(test, "Could not create alaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(caps, ulaw_format, 42)) { + ast_test_status_update(test, "Could not add newly created ulaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_iscompatible_format(caps, alaw_format) != AST_FORMAT_CMP_NOT_EQUAL) { + ast_test_status_update(test, "Alaw format is compatible with capabilities structure when it only contains ulaw\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_iscompatible_format(caps, ulaw_format) == AST_FORMAT_CMP_NOT_EQUAL) { + ast_test_status_update(test, "Ulaw format is not compatible with capabilities structure when it should be\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_get_compatible) +{ + RAII_VAR(struct ast_format_cap *, alaw_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_format_cap *, ulaw_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_format_cap *, compatible_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cap_get_compatible"; + info->category = "/main/format_cap/"; + info->summary = "format capabilities negotiation unit test"; + info->description = + "Test that getting the compatible formats between two capabilities structures succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + alaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!alaw_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!ulaw_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + compatible_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!compatible_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!ulaw) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + ulaw_format = ast_format_create(ulaw); + if (!ulaw_format) { + ast_test_status_update(test, "Could not create ulaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!alaw) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + alaw_format = ast_format_create(alaw); + if (!alaw_format) { + ast_test_status_update(test, "Could not create alaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(ulaw_caps, ulaw_format, 0)) { + ast_test_status_update(test, "Could not add ulaw format to ulaw capabilities\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append(alaw_caps, alaw_format, 0)) { + ast_test_status_update(test, "Could not add alaw format to alaw capabilities\n"); + return AST_TEST_FAIL; + } + + ast_format_cap_get_compatible(ulaw_caps, alaw_caps, compatible_caps); + if (ast_format_cap_count(compatible_caps)) { + ast_test_status_update(test, "A compatible format exists when none should\n"); + return AST_TEST_FAIL; + } + + ast_format_cap_get_compatible(ulaw_caps, ulaw_caps, compatible_caps); + if (!ast_format_cap_count(compatible_caps)) { + ast_test_status_update(test, "No compatible formats exist when 1 should\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_iscompatible) +{ + RAII_VAR(struct ast_format_cap *, alaw_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_format_cap *, ulaw_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cap_iscompatible"; + info->category = "/main/format_cap/"; + info->summary = "format capabilities negotiation unit test"; + info->description = + "Test that checking if there are compatible formats between two capabilities structures succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + alaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!alaw_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!ulaw_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!ulaw) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + ulaw_format = ast_format_create(ulaw); + if (!ulaw_format) { + ast_test_status_update(test, "Could not create ulaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!alaw) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + alaw_format = ast_format_create(alaw); + if (!alaw_format) { + ast_test_status_update(test, "Could not create alaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(ulaw_caps, ulaw_format, 0)) { + ast_test_status_update(test, "Could not add ulaw format to ulaw capabilities\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append(alaw_caps, alaw_format, 0)) { + ast_test_status_update(test, "Could not add alaw format to alaw capabilities\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_iscompatible(ulaw_caps, alaw_caps)) { + ast_test_status_update(test, "Two capability structures that should not be compatible are\n"); + return AST_TEST_FAIL; + } else if (!ast_format_cap_iscompatible(ulaw_caps, ulaw_caps)) { + ast_test_status_update(test, "Capability structure is not compatible with itself\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_get_names) +{ + RAII_VAR(struct ast_format_cap *, empty_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_format_cap *, multi_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_format_cap *, alaw_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_format_cap *, ulaw_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup); + struct ast_str *buffer = ast_str_alloca(128); + + switch (cmd) { + case TEST_INIT: + info->name = "format_cap_get_names"; + info->category = "/main/format_cap/"; + info->summary = "Test getting the names of formats"; + info->description = + "Test that obtaining the names from a format capabilities structure\n" + "produces the expected output.\n"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + empty_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!empty_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + multi_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!multi_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + alaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!alaw_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!ulaw_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!ulaw) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + ulaw_format = ast_format_create(ulaw); + if (!ulaw_format) { + ast_test_status_update(test, "Could not create ulaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!alaw) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + alaw_format = ast_format_create(alaw); + if (!alaw_format) { + ast_test_status_update(test, "Could not create alaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(ulaw_caps, ulaw_format, 0)) { + ast_test_status_update(test, "Could not add ulaw format to ulaw capabilities\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append(alaw_caps, alaw_format, 0)) { + ast_test_status_update(test, "Could not add alaw format to alaw capabilities\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append(multi_caps, ulaw_format, 0)) { + ast_test_status_update(test, "Could not add ulaw format to multi capabilities\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append(multi_caps, alaw_format, 0)) { + ast_test_status_update(test, "Could not add alaw format to multi capabilities\n"); + return AST_TEST_FAIL; + } + + ast_format_cap_get_names(empty_caps, &buffer); + ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(nothing)")); + ast_format_cap_get_names(ulaw_caps, &buffer); + ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(ulaw)")); + ast_format_cap_get_names(alaw_caps, &buffer); + ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(alaw)")); + ast_format_cap_get_names(multi_caps, &buffer); + ast_test_validate(test, !strcmp(ast_str_buffer(buffer), "(ulaw|alaw)")); + + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(format_cap_best_by_type) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, h263, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, h263_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, best_format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = "/main/format_cap/"; + info->summary = "format capabilities best by type unit test"; + info->description = + "Test that we can get the best format type out of a capabilities structure"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw = ast_codec_get("ulaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!ulaw) { + ast_test_status_update(test, "Could not retrieve built-in ulaw codec\n"); + return AST_TEST_FAIL; + } + + ulaw_format = ast_format_create(ulaw); + if (!ulaw_format) { + ast_test_status_update(test, "Could not create ulaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!alaw) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + alaw_format = ast_format_create(alaw); + if (!alaw_format) { + ast_test_status_update(test, "Could not create alaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + h263 = ast_codec_get("h263", AST_MEDIA_TYPE_VIDEO, 0); + if (!h263) { + ast_test_status_update(test, "Could not retrieve built-in h263 codec\n"); + return AST_TEST_FAIL; + } + + h263_format = ast_format_create(h263); + if (!alaw_format) { + ast_test_status_update(test, "Could not create h263 format using built-in codec\n"); + return AST_TEST_FAIL; + } + + if (ast_format_cap_append(caps, ulaw_format, 0)) { + ast_test_status_update(test, "Could not add ulaw format to capabilities\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append(caps, alaw_format, 0)) { + ast_test_status_update(test, "Could not add alaw format to capabilities\n"); + return AST_TEST_FAIL; + } else if (ast_format_cap_append(caps, h263_format, 0)) { + ast_test_status_update(test, "Could not add h263 format to capabilities\n"); + return AST_TEST_FAIL; + } + + best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_UNKNOWN); + ast_test_validate(test, ast_format_cmp(best_format, ulaw_format) == AST_FORMAT_CMP_EQUAL); + ao2_ref(best_format, -1); + + best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_AUDIO); + ast_test_validate(test, ast_format_cmp(best_format, ulaw_format) == AST_FORMAT_CMP_EQUAL); + ao2_ref(best_format, -1); + + best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_VIDEO); + ast_test_validate(test, ast_format_cmp(best_format, h263_format) == AST_FORMAT_CMP_EQUAL); + ao2_ref(best_format, -1); + + best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_IMAGE); + ast_test_validate(test, best_format == NULL); + + best_format = ast_format_cap_get_best_by_type(caps, AST_MEDIA_TYPE_TEXT); + ast_test_validate(test, best_format == NULL); + + return AST_TEST_PASS; +} + +static int test_law_samples(struct ast_frame *frame) +{ + return frame->datalen; +} + +static int test_law_length(unsigned int samples) +{ + return samples; +} + +static struct ast_codec test_law = { + .name = "test_law", + .description = "format cap unit test codec", + .type = AST_MEDIA_TYPE_AUDIO, + .sample_rate = 8000, + .minimum_ms = 10, + .maximum_ms = 150, + .default_ms = 20, + .samples_count = test_law_samples, + .get_length = test_law_length, + .smooth = 1, +}; + +static enum ast_format_cmp_res test_law_cmp(const struct ast_format *format1, const struct ast_format *format2) +{ + ast_log(LOG_ERROR, "Comparing format1 %p and format2 %p\n", format1, format2); + return format1 == format2 ? AST_FORMAT_CMP_EQUAL : AST_FORMAT_CMP_NOT_EQUAL; +} + +static void test_law_destroy(struct ast_format *format) +{ +} + +static int test_law_clone(const struct ast_format *src, struct ast_format *dst) +{ + return 0; +} + +static struct ast_format_interface test_law_interface = { + .format_cmp = test_law_cmp, + .format_clone = test_law_clone, + .format_destroy = test_law_destroy, +}; + +AST_TEST_DEFINE(format_cap_replace_from_cap) +{ + RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_format_cap *, replace_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_format_cap *, result_caps, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, ulaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, ulaw_format, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, ulaw_format_variant, NULL, ao2_cleanup); + RAII_VAR(struct ast_codec *, alaw, NULL, ao2_cleanup); + RAII_VAR(struct ast_format *, alaw_format, NULL, ao2_cleanup); + + switch (cmd) { + case TEST_INIT: + info->name = __PRETTY_FUNCTION__; + info->category = "/main/format_cap/"; + info->summary = "format capabilities adding unit test"; + info->description = + "Test that adding multiple formats to a format capabilities structure succeeds"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + replace_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + result_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!caps || !replace_caps || !result_caps) { + ast_test_status_update(test, "Could not allocate an empty format capabilities structure\n"); + return AST_TEST_FAIL; + } + + ulaw = ast_codec_get("test_law", AST_MEDIA_TYPE_AUDIO, 8000); + if (!ulaw) { + ast_test_status_update(test, "Could not retrieve test_law codec\n"); + return AST_TEST_FAIL; + } + + ulaw_format = ast_format_create(ulaw); + if (!ulaw_format) { + ast_test_status_update(test, "Could not create ulaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + ulaw_format_variant = ast_format_create(ulaw); + if (!ulaw_format_variant) { + ast_test_status_update(test, "Could not create ulaw format variant using built-in codec\n"); + return AST_TEST_FAIL; + } + + alaw = ast_codec_get("alaw", AST_MEDIA_TYPE_AUDIO, 8000); + if (!alaw) { + ast_test_status_update(test, "Could not retrieve built-in alaw codec\n"); + return AST_TEST_FAIL; + } + + alaw_format = ast_format_create(alaw); + if (!alaw_format) { + ast_test_status_update(test, "Could not create alaw format using built-in codec\n"); + return AST_TEST_FAIL; + } + + /* fill caps with ulaw and alaw */ + if (ast_format_cap_append(caps, ulaw_format, 42)) { + ast_test_status_update(test, "Could not add ulaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } + if (ast_format_cap_append(caps, alaw_format, 84)) { + ast_test_status_update(test, "Could not add alaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } + if (ast_format_cap_count(caps) != 2) { + ast_test_status_update(test, "Number of formats in capabilities structure should be 2 but is %zu\n", + ast_format_cap_count(caps)); + return AST_TEST_FAIL; + } + + /* fill replace_caps with the ulaw variant */ + if (ast_format_cap_append(replace_caps, ulaw_format_variant, 42)) { + ast_test_status_update(test, "Could not add ulaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } + if (ast_format_cap_count(replace_caps) != 1) { + ast_test_status_update(test, "Number of formats in capabilities structure should be 1 but is %zu\n", + ast_format_cap_count(replace_caps)); + return AST_TEST_FAIL; + } + + /* fill result_caps with ulaw_variant and alaw */ + if (ast_format_cap_append(result_caps, ulaw_format_variant, 42)) { + ast_test_status_update(test, "Could not add ulaw variant to capabilities structure\n"); + return AST_TEST_FAIL; + } + if (ast_format_cap_append(result_caps, alaw_format, 84)) { + ast_test_status_update(test, "Could not add alaw format to capabilities structure\n"); + return AST_TEST_FAIL; + } + if (ast_format_cap_count(result_caps) != 2) { + ast_test_status_update(test, "Number of formats in capabilities structure should be 2 but is %zu\n", + ast_format_cap_count(result_caps)); + return AST_TEST_FAIL; + } + + /* replace caps formats from replace_caps */ + ast_format_cap_replace_from_cap(caps, replace_caps, AST_MEDIA_TYPE_UNKNOWN); + + /* compare result_caps with caps */ + if (!ast_format_cap_identical(caps, result_caps)) { + ast_test_status_update(test, "Actual and expected result caps differ\n"); + return AST_TEST_FAIL; + } + + return AST_TEST_PASS; +} + +static int unload_module(void) +{ + AST_TEST_UNREGISTER(format_cap_alloc); + AST_TEST_UNREGISTER(format_cap_append_single); + AST_TEST_UNREGISTER(format_cap_append_multiple); + AST_TEST_UNREGISTER(format_cap_append_all_unknown); + AST_TEST_UNREGISTER(format_cap_append_all_audio); + AST_TEST_UNREGISTER(format_cap_append_duplicate); + AST_TEST_UNREGISTER(format_cap_append_from_cap); + AST_TEST_UNREGISTER(format_cap_append_from_cap_duplicate); + AST_TEST_UNREGISTER(format_cap_set_framing); + AST_TEST_UNREGISTER(format_cap_remove_single); + AST_TEST_UNREGISTER(format_cap_remove_multiple); + AST_TEST_UNREGISTER(format_cap_remove_bytype); + AST_TEST_UNREGISTER(format_cap_remove_all); + AST_TEST_UNREGISTER(format_cap_get_names); + AST_TEST_UNREGISTER(format_cap_get_compatible_format); + AST_TEST_UNREGISTER(format_cap_iscompatible_format); + AST_TEST_UNREGISTER(format_cap_get_compatible); + AST_TEST_UNREGISTER(format_cap_iscompatible); + AST_TEST_UNREGISTER(format_cap_best_by_type); + AST_TEST_UNREGISTER(format_cap_replace_from_cap); + return 0; +} + +static int load_module(void) +{ + AST_TEST_REGISTER(format_cap_alloc); + AST_TEST_REGISTER(format_cap_append_single); + AST_TEST_REGISTER(format_cap_append_multiple); + AST_TEST_REGISTER(format_cap_append_all_unknown); + AST_TEST_REGISTER(format_cap_append_all_audio); + AST_TEST_REGISTER(format_cap_append_duplicate); + AST_TEST_REGISTER(format_cap_append_from_cap); + AST_TEST_REGISTER(format_cap_append_from_cap_duplicate); + AST_TEST_REGISTER(format_cap_set_framing); + AST_TEST_REGISTER(format_cap_remove_single); + AST_TEST_REGISTER(format_cap_remove_multiple); + AST_TEST_REGISTER(format_cap_remove_bytype); + AST_TEST_REGISTER(format_cap_remove_all); + AST_TEST_REGISTER(format_cap_get_names); + AST_TEST_REGISTER(format_cap_get_compatible_format); + AST_TEST_REGISTER(format_cap_iscompatible_format); + AST_TEST_REGISTER(format_cap_get_compatible); + AST_TEST_REGISTER(format_cap_iscompatible); + AST_TEST_REGISTER(format_cap_best_by_type); + AST_TEST_REGISTER(format_cap_replace_from_cap); + ast_codec_register(&test_law); + ast_format_interface_register("test_law", &test_law_interface); + return AST_MODULE_LOAD_SUCCESS; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Format capabilities API test module"); diff --git a/tests/test_voicemail_api.c b/tests/test_voicemail_api.c index 43293b0fc..ab1830298 100644 --- a/tests/test_voicemail_api.c +++ b/tests/test_voicemail_api.c @@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/paths.h" #include "asterisk/channel.h" #include "asterisk/app.h" +#include "asterisk/format_cache.h" /*! * \internal @@ -825,12 +826,12 @@ static struct ast_channel *test_vm_api_create_mock_channel(void) return NULL; } - ast_format_set(ast_channel_writeformat(mock_channel), AST_FORMAT_GSM, 0); + ast_channel_set_writeformat(mock_channel, ast_format_gsm); native_formats = ast_channel_nativeformats(mock_channel); - ast_format_cap_add(native_formats, ast_channel_writeformat(mock_channel)); - ast_format_set(ast_channel_rawwriteformat(mock_channel), AST_FORMAT_GSM, 0); - ast_format_set(ast_channel_readformat(mock_channel), AST_FORMAT_GSM, 0); - ast_format_set(ast_channel_rawreadformat(mock_channel), AST_FORMAT_GSM, 0); + ast_format_cap_append(native_formats, ast_channel_writeformat(mock_channel), 0); + ast_channel_set_rawwriteformat(mock_channel, ast_format_gsm); + ast_channel_set_readformat(mock_channel, ast_format_gsm); + ast_channel_set_rawreadformat(mock_channel, ast_format_gsm); ast_channel_tech_set(mock_channel, &mock_channel_tech); ast_channel_unlock(mock_channel); |