Esempio n. 1
0
void ast_format_cap_from_old_bitfield(struct ast_format_cap *dst, uint64_t src)
{
	uint64_t tmp = 0;
	int x;
	struct ast_format tmp_format = { 0, };

	ast_format_cap_remove_all(dst);
	for (x = 0; x < 64; x++) {
		tmp = (1ULL << x);
		if (tmp & src) {
			ast_format_cap_add(dst, ast_format_from_old_bitfield(&tmp_format, tmp));
		}
	}
}
Esempio n. 2
0
int ast_format_cap_has_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
{
	struct ao2_iterator it;
	struct ast_format *tmp;
	struct find_joint_data data = {
		.joint_found = 0,
		.joint_cap = NULL,
	};

	it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0);
	while ((tmp = ao2_iterator_next(&it))) {
		data.format = tmp;
		ao2_callback(cap2->formats,
			OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock,
			find_joint_cb,
			&data);
		ao2_ref(tmp, -1);
	}
	ao2_iterator_destroy(&it);

	return data.joint_found ? 1 : 0;
}

int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
{
	struct ao2_iterator it;
	struct ast_format *tmp;

	if (ao2_container_count(cap1->formats) != ao2_container_count(cap2->formats)) {
		return 0; /* if they are not the same size, they are not identical */
	}

	it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0);
	while ((tmp = ao2_iterator_next(&it))) {
		if (!ast_format_cap_iscompatible(cap2, tmp)) {
			ao2_ref(tmp, -1);
			ao2_iterator_destroy(&it);
			return 0;
		}
		ao2_ref(tmp, -1);
	}
	ao2_iterator_destroy(&it);

	return 1;
}

struct ast_format_cap *ast_format_cap_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
{
	struct ao2_iterator it;
	struct ast_format_cap *result = ast_format_cap_alloc_nolock();
	struct ast_format *tmp;
	struct find_joint_data data = {
		.joint_found = 0,
		.joint_cap = result,
	};
	if (!result) {
		return NULL;
	}

	it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0);
	while ((tmp = ao2_iterator_next(&it))) {
		data.format = tmp;
		ao2_callback(cap2->formats,
			OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock,
			find_joint_cb,
			&data);
		ao2_ref(tmp, -1);
	}
	ao2_iterator_destroy(&it);

	if (ao2_container_count(result->formats)) {
		return result;
	}

	result = ast_format_cap_destroy(result);
	return NULL;
}

static int joint_copy_helper(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result, int append)
{
	struct ao2_iterator it;
	struct ast_format *tmp;
	struct find_joint_data data = {
		.joint_cap = result,
		.joint_found = 0,
	};
	if (!append) {
		ast_format_cap_remove_all(result);
	}
	it = ao2_iterator_init(cap1->formats, cap1->nolock ? AO2_ITERATOR_DONTLOCK : 0);
	while ((tmp = ao2_iterator_next(&it))) {
		data.format = tmp;
		ao2_callback(cap2->formats,
			OBJ_MULTIPLE | OBJ_NODATA | cap2->nolock,
			find_joint_cb,
			&data);
		ao2_ref(tmp, -1);
	}
	ao2_iterator_destroy(&it);

	return ao2_container_count(result->formats) ? 1 : 0;
}

int ast_format_cap_joint_append(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
{
	return joint_copy_helper(cap1, cap2, result, 1);
}

int ast_format_cap_joint_copy(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
{
	return joint_copy_helper(cap1, cap2, result, 0);
}

struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap, enum ast_format_type ftype)
{
	struct ao2_iterator it;
	struct ast_format_cap *result = ast_format_cap_alloc_nolock();
	struct ast_format *tmp;

	if (!result) {
		return NULL;
	}

	/* for each format in cap1, see if that format is
	 * compatible with cap2. If so copy it to the result */
	it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0);
	while ((tmp = ao2_iterator_next(&it))) {
		if (AST_FORMAT_GET_TYPE(tmp->id) == ftype) {
			/* copy format */
			ast_format_cap_add(result, tmp);
		}
		ao2_ref(tmp, -1);
	}
	ao2_iterator_destroy(&it);

	if (ao2_container_count(result->formats)) {
		return result;
	}
	result = ast_format_cap_destroy(result);

	return NULL;
}


int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_format_type type)
{
	struct ao2_iterator it;
	struct ast_format *tmp;

	it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0);
	while ((tmp = ao2_iterator_next(&it))) {
		if (AST_FORMAT_GET_TYPE(tmp->id) == type) {
			ao2_ref(tmp, -1);
			ao2_iterator_destroy(&it);
			return 1;
		}
		ao2_ref(tmp, -1);
	}
	ao2_iterator_destroy(&it);

	return 0;
}

void ast_format_cap_iter_start(struct ast_format_cap *cap)
{
	if (!cap->nolock) {
		ao2_lock(cap->formats);
	}
	cap->it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0);
}

void ast_format_cap_iter_end(struct ast_format_cap *cap)
{
	ao2_iterator_destroy(&cap->it);
	if (!cap->nolock) {
		ao2_unlock(cap->formats);
	}
}

int ast_format_cap_iter_next(struct ast_format_cap *cap, struct ast_format *format)
{
	struct ast_format *tmp = ao2_iterator_next(&cap->it);

	if (!tmp) {
		return -1;
	}
	ast_format_copy(format, tmp);
	ao2_ref(tmp, -1);

	return 0;
}

char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap)
{
	int x;
	unsigned len;
	char *start, *end = buf;
	struct ast_format tmp_fmt;
	size_t f_len;
	const struct ast_format_list *f_list = ast_format_list_get(&f_len);

	if (!size) {
		f_list = ast_format_list_destroy(f_list);
		return buf;
	}
	snprintf(end, size, "(");
	len = strlen(end);
	end += len;
	size -= len;
	start = end;
	for (x = 0; x < f_len; x++) {
		ast_format_copy(&tmp_fmt, &f_list[x].format);
		if (ast_format_cap_iscompatible(cap, &tmp_fmt)) {
			snprintf(end, size, "%s|", f_list[x].name);
			len = strlen(end);
			end += len;
			size -= len;
		}
	}
	if (start == end) {
		ast_copy_string(start, "nothing)", size);
	} else if (size > 1) {
		*(end - 1) = ')';
	}
	f_list = ast_format_list_destroy(f_list);
	return buf;
}

uint64_t ast_format_cap_to_old_bitfield(const struct ast_format_cap *cap)
{
	uint64_t res = 0;
	struct ao2_iterator it;
	struct ast_format *tmp;

	it = ao2_iterator_init(cap->formats, cap->nolock ? AO2_ITERATOR_DONTLOCK : 0);
	while ((tmp = ao2_iterator_next(&it))) {
		res |= ast_format_to_old_bitfield(tmp);
		ao2_ref(tmp, -1);
	}
	ao2_iterator_destroy(&it);
	return res;
}
Esempio n. 3
0
void ast_format_cap_copy(struct ast_format_cap *dst, const struct ast_format_cap *src)
{
	ast_format_cap_remove_all(dst);
	ao2_callback(src->formats, OBJ_NODATA | src->nolock, copy_cb, dst);
}
Esempio n. 4
0
void ast_format_cap_set(struct ast_format_cap *cap, struct ast_format *format)
{
	ast_format_cap_remove_all(cap);
	ast_format_cap_add(cap, format);
}
Esempio n. 5
0
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;
}