예제 #1
0
static enum ast_test_result_state test_chan_variable(struct ast_test *test,
		struct ast_channel *c, const char *varname)
{
	const char *values[] = { "one", "three", "reallylongdinosaursoundingthingwithwordsinit" };
	int i, okay = 1;
	char workspace[4096];
	struct ast_str *str = ast_str_create(16);
	struct ast_str *var = ast_str_create(16);

	ast_str_set(&var, 0, "${%s}", varname);
	for (i = 0; i < ARRAY_LEN(values); i++) {
		pbx_builtin_setvar_helper(c, varname, values[i]);
		ast_str_substitute_variables(&str, 0, c, ast_str_buffer(var));
		pbx_substitute_variables_helper(c, ast_str_buffer(var), workspace, sizeof(workspace));
		ast_test_status_update(test, "Testing '%s' . . . . . %s\n",
				ast_str_buffer(var), okay ? "passed" : "FAILED");
		if (strcmp(values[i], ast_str_buffer(str)) != 0 || strcmp(values[i], workspace) != 0) {
			ast_test_status_update(test, "%s != %s != %s\n",
					values[i], ast_str_buffer(str), workspace);
			okay = 0;
		}
	}

	ast_free(str);
	ast_free(var);

	return okay ? AST_TEST_PASS : AST_TEST_FAIL;
}
예제 #2
0
static int test_exten(const struct pbx_test_pattern *test_pattern, struct ast_test *test)
{
	struct pbx_find_info pfi = { { 0 }, };
	struct ast_exten *exten;
	if (!(exten = pbx_find_extension(NULL, NULL, &pfi, test_pattern->context,
					test_pattern->test_exten, test_pattern->priority, NULL,
					test_pattern->test_cid, E_MATCH))) {
		ast_test_status_update(test, "Cannot find extension %s in context %s."
				"Test failed.\n", test_pattern->test_exten, test_pattern->context);
		return -1;
	}
	if (strcmp(ast_get_extension_name(exten), test_pattern->exten->exten)) {
		ast_test_status_update(test, "Expected extension %s but got extension %s instead."
				"Test failed.\n", test_pattern->exten->exten, ast_get_extension_name(exten));
		return -1;
	}
	if (test_pattern->test_cid && strcmp(ast_get_extension_cidmatch(exten), test_pattern->test_cid)) {
		ast_test_status_update(test, "Expected CID match %s but got CID match %s instead."
				"Test failed.\n", test_pattern->exten->cid, ast_get_extension_cidmatch(exten));
		return -1;
	}
	ast_test_status_update(test, "Successfully matched %s to exten %s in context %s\n",
			test_pattern->test_exten, test_pattern->exten->exten, test_pattern->context);
	return 0;
}
예제 #3
0
static enum ast_test_result_state test_chan_string(struct ast_test *test,
		struct ast_channel *c, char *cfield, size_t cfieldsize,
		const char *expression)
{
	const char *values[] = { "one", "three", "reallylongdinosaursoundingthingwithwordsinit" };
	int i, okay = 1;
	char workspace[4096];
	struct ast_str *str = ast_str_create(16);

	for (i = 0; i < ARRAY_LEN(values); i++) {
		ast_copy_string(cfield, values[i], cfieldsize);
		ast_str_substitute_variables(&str, 0, c, expression);
		pbx_substitute_variables_helper(c, expression, workspace, sizeof(workspace));
		ast_test_status_update(test, "Testing '%s' . . . . . %s\n",
				expression, okay ? "passed" : "FAILED");
		if (strcmp(cfield, ast_str_buffer(str)) != 0 || strcmp(cfield, workspace) != 0) {
			ast_test_status_update(test, "%s != %s != %s\n", cfield, ast_str_buffer(str), workspace);
			okay = 0;
		}
	}

	ast_free(str);

	return okay ? AST_TEST_PASS : AST_TEST_FAIL;
}
예제 #4
0
static int test_exten(const struct pbx_test_pattern *test_pattern, struct ast_test *test, int new_engine)
{
    struct pbx_find_info pfi = { { 0 }, };
    struct ast_exten *exten;
    if (!(exten = pbx_find_extension(NULL, NULL, &pfi, test_pattern->context,
                                     test_pattern->test_exten, test_pattern->priority, NULL,
                                     test_pattern->test_cid, E_MATCH))) {
        ast_test_status_update(test, "Cannot find extension %s in context %s with the %s pattern match engine. "
                               "Test failed.\n", test_pattern->test_exten, test_pattern->context, (new_engine ? "new" : "old"));
        return -1;
    }
    if (strcmp(ast_get_extension_name(exten), test_pattern->exten->exten)) {
        ast_test_status_update(test, "Expected extension %s but got extension %s instead with the %s pattern match engine. "
                               "Test failed.\n", test_pattern->exten->exten, ast_get_extension_name(exten), (new_engine ? "new" : "old"));
        return -1;
    }
    if (test_pattern->test_cid && strcmp(ast_get_extension_cidmatch(exten), test_pattern->test_cid)) {
        ast_test_status_update(test, "Expected CID match %s but got CID match %s instead with the %s pattern match engine. "
                               "Test failed.\n", test_pattern->exten->cid, ast_get_extension_cidmatch(exten), (new_engine ? "new" : "old"));
        return -1;
    }
    if (!ast_canmatch_extension(NULL, test_pattern->context, test_pattern->test_exten,
                                test_pattern->priority, test_pattern->test_cid)) {
        ast_test_status_update(test, "Partial match failed for extension %s in context %s with the %s pattern match engine. "
                               "Test failed.\n", test_pattern->test_exten, test_pattern->context, (new_engine ? "new" : "old"));
        return -1;
    }
    ast_test_status_update(test, "Successfully matched %s to exten %s in context %s with the %s pattern match engine\n",
                           test_pattern->test_exten, test_pattern->exten->exten, test_pattern->context, (new_engine ? "new" : "old"));
    return 0;
}
예제 #5
0
static enum ast_test_result_state test_2way_function(struct ast_test *test,
		struct ast_channel *c, const char *encode1, const char *encode2,
		const char *decode1, const char *decode2)
{
	struct ast_str *str = ast_str_create(16), *expression = ast_str_alloca(120);
	int okay;

	ast_str_set(&expression, 0, "%s%s%s", encode1, "foobarbaz", encode2);
	ast_str_substitute_variables(&str, 0, c, ast_str_buffer(expression));
	ast_str_set(&expression, 0, "%s%s%s", decode1, ast_str_buffer(str), decode2);
	ast_str_substitute_variables(&str, 0, c, ast_str_buffer(expression));

	okay = !strcmp(ast_str_buffer(str), "foobarbaz");

	ast_test_status_update(test, "Testing '%s%s' and '%s%s' . . . . . %s\n",
			encode1, encode2, decode1, decode2,
			okay ? "passed" : "FAILED");

	if (!okay) {
		ast_test_status_update(test, "  '%s' != 'foobarbaz'\n",
				ast_str_buffer(str));
	}

	ast_free(str);

	return okay ? AST_TEST_PASS : AST_TEST_FAIL;
}
예제 #6
0
/*!
 * \brief Wait for a successful resolution to complete
 *
 * This is called whenever a successful DNS resolution occurs. This function
 * serves to ensure that parameters are as we expect them to be.
 *
 * \param test The test being executed
 * \param rdata DNS query user data
 * \param expected_lapse The amount of time we expect to wait for the query to complete
 * \param num_resolves The number of DNS resolutions that have been executed
 * \param num_completed The number of DNS resolutions we expect to have completed successfully
 * \param canceled Whether the query is expected to have been canceled
 */
static int wait_for_resolution(struct ast_test *test, struct recurring_data *rdata,
		int expected_lapse, int num_resolves, int num_completed, int canceled)
{
	struct timespec begin;
	struct timespec end;
	struct timespec timeout;
	int secdiff;

	clock_gettime(CLOCK_REALTIME, &begin);

	timeout.tv_sec = begin.tv_sec + 20;
	timeout.tv_nsec = begin.tv_nsec;

	ast_mutex_lock(&rdata->lock);
	while (!rdata->query_complete) {
		if (ast_cond_timedwait(&rdata->cond, &rdata->lock, &timeout) == ETIMEDOUT) {
			break;
		}
	}
	ast_mutex_unlock(&rdata->lock);

	if (!rdata->query_complete) {
		ast_test_status_update(test, "Query timed out\n");
		return -1;
	}

	rdata->query_complete = 0;
	clock_gettime(CLOCK_REALTIME, &end);

	secdiff = end.tv_sec - begin.tv_sec;

	/* Give ourselves some wiggle room */
	if (secdiff < expected_lapse - 2 || secdiff > expected_lapse + 2) {
		ast_test_status_update(test, "Query did not complete in expected time\n");
		return -1;
	}

	if (rdata->resolves != num_resolves || rdata->complete_resolutions != num_completed) {
		ast_test_status_update(test, "Query has not undergone expected number of resolutions\n");
		return -1;
	}

	if (rdata->canceled != canceled) {
		ast_test_status_update(test, "Query was canceled unexpectedly\n");
		return -1;
	}

	ast_test_status_update(test, "Query completed in expected time frame\n");

	return 0;
}
예제 #7
0
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;

}
예제 #8
0
/*!
 * \brief unref callback function
 *
 * Unrefs the object passed in. Only sets the unreffed flag if
 * the object is not locked. This allows us to ensure that
 * unreffing always occurs after unlocking.
 */
static void test_unref(struct test_struct *test)
{
    ast_test_status_update(current_test, "Unref is occurring\n");
    ao2_ref(test, -1);
    if (!test->locked) {
        test->reffed = 0;
    }
}
예제 #9
0
/*!
 * \brief unlock callback function
 *
 * Unlocks the object passed in. Only clears the locked
 * flag if the object is still reffed. This allows us to
 * ensure that unlocking is always occurring before unreffing.
 */
static void test_unlock(struct test_struct *test)
{
    ast_test_status_update(current_test, "Unlock is occurring\n");
    ao2_unlock(test);
    if (test->reffed) {
        test->locked = 0;
    }
}
예제 #10
0
/*!
 * \brief ref callback function
 *
 * Refs the object passed in. Only sets the reffed flag if
 * the object is not locked. This allows us to ensure that
 * reffing always occurs before locking.
 */
static struct test_struct *test_ref(struct test_struct *test)
{
    ast_test_status_update(current_test, "Ref is occurring\n");
    ao2_ref(test, +1);
    if (!test->locked) {
        test->reffed = 1;
    }
    return test;
}
예제 #11
0
static int is_timed_out(struct hash_test const *data) {
	struct timeval now = ast_tvnow();
	int val = ast_tvdiff_us(data->deadline, now) < 0;
	if (val) {
		/* tv_usec is suseconds_t, which could be int or long */
		ast_test_status_update(data->test, "Now: %ld.%06ld Deadline: %ld.%06ld\n",
			now.tv_sec, (long)now.tv_usec,
			data->deadline.tv_sec, (long)data->deadline.tv_usec);
	}
	return val;
}
예제 #12
0
static void test_xml(struct ast_test *test, const char *input, const char *expected, int max_len, int expected_res)
{
	char actual[256] = "";
	int res;

	if (max_len == -1) {
		max_len = sizeof(actual);
	}

	res = ast_xml_escape(input, actual, max_len);
	if (res != expected_res) {
		ast_test_status_update(test, "Expected result '%d', got '%d'\n", expected_res, res);
		test_res = AST_TEST_FAIL;
	}

	if (strcmp(expected, actual) != 0) {
		ast_test_status_update(test, "Expected output '%s', got '%s'\n", expected, actual);
		test_res = AST_TEST_FAIL;
	}
}
예제 #13
0
static enum ast_test_result_state invalid_record_test(struct ast_test *test, struct srv_record *records,
	int num_records)
{
	RAII_VAR(struct ast_dns_result *, result, NULL, ast_dns_result_free);
	const struct ast_dns_record *record;
	enum ast_test_result_state res = AST_TEST_PASS;

	test_records = records;
	num_test_records = num_records;
	memset(ans_buffer, 0, sizeof(ans_buffer));

	ast_dns_resolver_register(&srv_resolver);

	if (ast_dns_resolve("goose.feathers", ns_t_srv, ns_c_in, &result)) {
		ast_test_status_update(test, "DNS resolution failed\n");
		res = AST_TEST_FAIL;
		goto cleanup;
	}

	if (!result) {
		ast_test_status_update(test, "DNS resolution returned no result\n");
		res = AST_TEST_FAIL;
		goto cleanup;
	}

	record = ast_dns_result_get_records(result);
	if (record) {
		ast_test_status_update(test, "Unexpected record returned from SRV query\n");
		res = AST_TEST_FAIL;
	}

cleanup:

	ast_dns_resolver_unregister(&srv_resolver);

	test_records = NULL;
	num_test_records = 0;
	memset(ans_buffer, 0, sizeof(ans_buffer));

	return res;
}
예제 #14
0
static enum ast_test_result_state test_chan_function(struct ast_test *test,
		struct ast_channel *c, const char *expression)
{
	int okay = 1;
	char workspace[4096];
	struct ast_str *str = ast_str_create(16);

	ast_str_substitute_variables(&str, 0, c, expression);
	pbx_substitute_variables_helper(c, expression, workspace, sizeof(workspace));
	ast_test_status_update(test, "Testing '%s' . . . . . %s\n",
			expression, okay ? "passed" : "FAILED");
	if (strcmp(workspace, ast_str_buffer(str)) != 0) {
		ast_test_status_update(test, "test_chan_function, expr: '%s' ... %s != %s\n",
				expression, ast_str_buffer(str), workspace);
		okay = 0;
	}

	ast_free(str);

	return okay ? AST_TEST_PASS : AST_TEST_FAIL;
}
예제 #15
0
static enum ast_test_result_state off_nominal_test(struct ast_test *test, struct naptr_record *records, int num_records)
{
	RAII_VAR(struct ast_dns_result *, result, NULL, ast_dns_result_free);
	enum ast_test_result_state res = AST_TEST_PASS;
	const struct ast_dns_record *record;

	test_records = records;
	num_test_records = num_records;
	memset(ans_buffer, 0, sizeof(ans_buffer));

	ast_dns_resolver_register(&naptr_resolver);

	if (ast_dns_resolve("goose.feathers", ns_t_naptr, ns_c_in, &result)) {
		ast_test_status_update(test, "Failed to perform DNS resolution, despite using valid inputs\n");
		res = AST_TEST_FAIL;
		goto cleanup;
	}

	if (!result) {
		ast_test_status_update(test, "Synchronous DNS resolution failed to set a result\n");
		res = AST_TEST_FAIL;
		goto cleanup;
	}

	record = ast_dns_result_get_records(result);
	if (record) {
		ast_test_status_update(test, "DNS resolution returned records when it was not expected to\n");
		res = AST_TEST_FAIL;
		goto cleanup;
	}

cleanup:
	ast_dns_resolver_unregister(&naptr_resolver);

	test_records = NULL;
	num_test_records = 0;
	memset(ans_buffer, 0, sizeof(ans_buffer));

	return res;
}
예제 #16
0
static enum ast_test_result_state test_chan_integer(struct ast_test *test,
		struct ast_channel *c, int *ifield, const char *expression)
{
	int i, okay = 1, value1 = -1, value2 = -1;
	char workspace[4096];
	struct ast_str *str = ast_str_create(16);

	ast_test_status_update(test, "Testing '%s' . . . . . %s\n", expression, okay ? "passed" : "FAILED");
	for (i = 0; i < 256; i++) {
		*ifield = i;
		ast_str_substitute_variables(&str, 0, c, expression);
		pbx_substitute_variables_helper(c, expression, workspace, sizeof(workspace));
		if (sscanf(workspace, "%d", &value1) != 1 || value1 != i || sscanf(ast_str_buffer(str), "%d", &value2) != 1 || value2 != i) {
			ast_test_status_update(test, "%s != %s and/or %d != %d != %d\n", ast_str_buffer(str), workspace, value1, value2, i);
			okay = 0;
		}
	}

	ast_free(str);

	return okay ? AST_TEST_PASS : AST_TEST_FAIL;
}
예제 #17
0
/*!
 * \brief helper to ensure that statistics the listener is keeping are what we expect
 *
 * \param test The currently-running test
 * \param pvt The private data for the taskprocessor listener
 * \param num_pushed The expected current number of tasks pushed to the processor
 * \param num_emptied The expected current number of times the taskprocessor has become empty
 * \param num_was_empty The expected current number of times that tasks were pushed to an empty taskprocessor
 * \retval -1 Stats were not as expected
 * \retval 0 Stats were as expected
 */
static int check_stats(struct ast_test *test, const struct test_listener_pvt *pvt, int num_pushed, int num_emptied, int num_was_empty)
{
	if (pvt->num_pushed != num_pushed) {
		ast_test_status_update(test, "Unexpected number of tasks pushed. Expected %d but got %d\n",
				num_pushed, pvt->num_pushed);
		return -1;
	}

	if (pvt->num_emptied != num_emptied) {
		ast_test_status_update(test, "Unexpected number of empties. Expected %d but got %d\n",
				num_emptied, pvt->num_emptied);
		return -1;
	}

	if (pvt->num_was_empty != num_was_empty) {
		ast_test_status_update(test, "Unexpected number of empties. Expected %d but got %d\n",
				num_was_empty, pvt->num_emptied);
		return -1;
	}

	return 0;
}
예제 #18
0
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_nolock();
			cap2 = ast_format_cap_alloc_nolock();
			joint = ast_format_cap_alloc_nolock();
		} else {
			cap1 = ast_format_cap_alloc();
			cap2 = ast_format_cap_alloc();
			joint = ast_format_cap_alloc();
		}
		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;
}
예제 #19
0
static enum ast_test_result_state test_expected_result(struct ast_test *test,
		struct ast_channel *c, const char *expression, const char *result)
{
	struct ast_str *str = ast_str_create(16);
	int okay;

	ast_str_substitute_variables(&str, 0, c, expression);
	okay = !strcmp(ast_str_buffer(str), result);

	ast_test_status_update(test, "Testing '%s' ('%s') == '%s' . . . . . %s\n",
			ast_str_buffer(str), expression, result,
			okay ? "passed" : "FAILED");

	if (!okay) {
		ast_test_status_update(test, "test_expected_result: '%s' != '%s'\n",
				ast_str_buffer(str), result);
	}

	ast_free(str);

	return okay ? AST_TEST_PASS : AST_TEST_FAIL;
}
예제 #20
0
파일: test_acl.c 프로젝트: GGGO/asterisk
static int build_ha(const struct acl *acl, size_t len, struct ast_ha **ha, const char *acl_name, int *err, struct ast_test *test, enum ast_test_result_state *res) 
{
	size_t i;

	for (i = 0; i < len; ++i) {
		if (!(*ha = ast_append_ha(acl[i].access, acl[i].host, *ha, err))) {
			ast_test_status_update(test, "Failed to add rule %s with access %s to %s\n",
					       acl[i].host, acl[i].access, acl_name);
			*res = AST_TEST_FAIL;
			return -1;
		}
	}

	return 0;
}
예제 #21
0
static int check_event(struct ast_event *event, struct ast_test *test,
		enum ast_event_type expected_type, const char *type_name,
		const char *str, uint32_t uint)
{
	enum ast_event_type type;
	const void *foo;

	/* Check #1: Ensure event type is set properly. */
	type = ast_event_get_type(event);
	if (ast_event_get_type(event) != type) {
		ast_test_status_update(test, "Expected event type: '%u', got '%u'\n",
				expected_type, type);
		return -1;
	}

	/* Check #4: Check for the string IE */
	if (strcmp(str, ast_event_get_ie_str(event, AST_EVENT_IE_CEL_USEREVENT_NAME))) {
		ast_test_status_update(test, "Failed to get string IE.\n");
		return -1;
	}

	/* Check #5: Check for the uint IE */
	if (uint != ast_event_get_ie_uint(event, AST_EVENT_IE_CEL_AMAFLAGS)) {
		ast_test_status_update(test, "Failed to get uint IE.\n");
		return -1;
	}

	/* Check #6: Check if a check for a str IE that isn't there works */
	if ((foo = ast_event_get_ie_str(event, AST_EVENT_IE_CEL_CIDNAME))) {
		ast_test_status_update(test, "CEL_CIDNAME IE check returned non-NULL %p\n", foo);
		return -1;
	}

	/* Check #7: Check if a check for a uint IE that isn't there returns 0 */
	if (ast_event_get_ie_uint(event, AST_EVENT_IE_CEL_EVENT_TIME_USEC)) {
		ast_test_status_update(test, "UNIQUEID IE should be 0\n");
		return -1;
	}

	ast_test_status_update(test, "Event looks good.\n");

	return 0;
}
static int scheduler(struct ast_test *test, int serialized)
{
	RAII_VAR(struct ast_taskprocessor *, tp1, NULL, ast_taskprocessor_unreference);
	RAII_VAR(struct test_data *, test_data1, ao2_alloc(sizeof(*test_data1), data_cleanup), ao2_cleanup);
	RAII_VAR(struct test_data *, test_data2, ao2_alloc(sizeof(*test_data2), data_cleanup), ao2_cleanup);
	RAII_VAR(struct ast_sip_sched_task *, task1, NULL, ao2_cleanup);
	RAII_VAR(struct ast_sip_sched_task *, task2, NULL, ao2_cleanup);
	int duration;
	int delay;
	struct timeval task1_start;

	ast_test_validate(test, test_data1 != NULL);
	ast_test_validate(test, test_data2 != NULL);

	test_data1->test = test;
	test_data1->test_start = ast_tvnow();
	test_data1->interval = 2000;
	test_data1->sleep = 1000;
	ast_mutex_init(&test_data1->lock);
	ast_cond_init(&test_data1->cond, NULL);

	test_data2->test = test;
	test_data2->test_start = ast_tvnow();
	test_data2->interval = 2000;
	test_data2->sleep = 1000;
	ast_mutex_init(&test_data2->lock);
	ast_cond_init(&test_data2->cond, NULL);

	if (serialized) {
		ast_test_status_update(test, "This test will take about %3.1f seconds\n",
			(test_data1->interval + test_data1->sleep + (MAX(test_data1->interval - test_data2->interval, 0)) + test_data2->sleep) / 1000.0);
		tp1 = ast_sip_create_serializer("test-scheduler-serializer");
		ast_test_validate(test, (tp1 != NULL));
	} else {
		ast_test_status_update(test, "This test will take about %3.1f seconds\n",
			((MAX(test_data1->interval, test_data2->interval) + MAX(test_data1->sleep, test_data2->sleep)) / 1000.0));
	}

	task1 = ast_sip_schedule_task(tp1, test_data1->interval, task_1, NULL, test_data1, AST_SIP_SCHED_TASK_FIXED);
	ast_test_validate(test, task1 != NULL);

	task2 = ast_sip_schedule_task(tp1, test_data2->interval, task_1, NULL, test_data2, AST_SIP_SCHED_TASK_FIXED);
	ast_test_validate(test, task2 != NULL);

	waitfor(test_data1);
	ast_sip_sched_task_cancel(task1);
	ast_test_validate(test, test_data1->is_servant);

	duration = ast_tvdiff_ms(test_data1->task_end, test_data1->test_start);
	ast_test_validate(test, (duration > ((test_data1->interval + test_data1->sleep) * 0.9))
		&& (duration < ((test_data1->interval + test_data1->sleep) * 1.1)));

	ast_sip_sched_task_get_times(task1, NULL, &task1_start, NULL);
	delay = ast_tvdiff_ms(task1_start, test_data1->test_start);
	ast_test_validate(test, (delay > (test_data1->interval * 0.9)
		&& (delay < (test_data1->interval * 1.1))));

	waitfor(test_data2);
	ast_sip_sched_task_cancel(task2);
	ast_test_validate(test, test_data2->is_servant);

	if (serialized) {
		ast_test_validate(test, test_data1->tid == test_data2->tid);
		ast_test_validate(test, ast_tvdiff_ms(test_data2->task_start, test_data1->task_end) >= 0);
	} else {
		ast_test_validate(test, test_data1->tid != test_data2->tid);
	}

	return AST_TEST_PASS;
}
예제 #23
0
static enum ast_test_result_state nominal_test(struct ast_test *test, struct srv_record *records,
	int *srv_record_order, int num_records)
{
	RAII_VAR(struct ast_dns_result *, result, NULL, ast_dns_result_free);
	const struct ast_dns_record *record;
	enum ast_test_result_state res = AST_TEST_PASS;
	int i;

	test_records = records;
	num_test_records = num_records;
	memset(ans_buffer, 0, sizeof(ans_buffer));

	ast_dns_resolver_register(&srv_resolver);

	if (ast_dns_resolve("goose.feathers", ns_t_srv, ns_c_in, &result)) {
		ast_test_status_update(test, "DNS resolution failed\n");
		res = AST_TEST_FAIL;
		goto cleanup;
	}

	if (!result) {
		ast_test_status_update(test, "DNS resolution returned no result\n");
		res = AST_TEST_FAIL;
		goto cleanup;
	}

	i = 0;
	for (record = ast_dns_result_get_records(result); record; record = ast_dns_record_get_next(record)) {
		if (ast_dns_srv_get_priority(record) != records[srv_record_order[i]].priority) {
			ast_test_status_update(test, "Unexpected priority in returned SRV record\n");
			res = AST_TEST_FAIL;
		}
		if (ast_dns_srv_get_weight(record) != records[srv_record_order[i]].weight) {
			ast_test_status_update(test, "Unexpected weight in returned SRV record\n");
			res = AST_TEST_FAIL;
		}
		if (ast_dns_srv_get_port(record) != records[srv_record_order[i]].port) {
			ast_test_status_update(test, "Unexpected port in returned SRV record\n");
			res = AST_TEST_FAIL;
		}
		if (strcmp(ast_dns_srv_get_host(record), records[srv_record_order[i]].host)) {
			ast_test_status_update(test, "Unexpected host in returned SRV record\n");
			res = AST_TEST_FAIL;
		}
		++i;
	}

	if (i != num_records) {
		ast_test_status_update(test, "Unexpected number of records returned in SRV lookup\n");
		res = AST_TEST_FAIL;
	}

cleanup:

	ast_dns_resolver_unregister(&srv_resolver);

	test_records = NULL;
	num_test_records = 0;
	memset(ans_buffer, 0, sizeof(ans_buffer));

	return res;
}
예제 #24
0
/*! \brief Wait for the \ref test_msg_handler to receive the message */
static int handler_wait_for_message(struct ast_test *test)
{
	int error = 0;
	struct timeval wait_now = ast_tvnow();
	struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 1, .tv_nsec = wait_now.tv_usec * 1000 };

	ast_mutex_lock(&handler_lock);
	while (!handler_received_message) {
		error = ast_cond_timedwait(&handler_cond, &handler_lock, &wait_time);
		if (error == ETIMEDOUT) {
			ast_test_status_update(test, "Test timed out while waiting for handler to get message\n");
			ast_test_set_result(test, AST_TEST_FAIL);
			break;
		}
	}
	ast_mutex_unlock(&handler_lock);

	return (error != ETIMEDOUT);
}

/*! \brief Wait for the expected number of user events to be received */
static int user_event_wait_for_events(struct ast_test *test, int expected_events)
{
	int error;
	struct timeval wait_now = ast_tvnow();
	struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 1, .tv_nsec = wait_now.tv_usec * 1000 };

	expected_user_events = expected_events;

	ast_mutex_lock(&user_event_lock);
	while (received_user_events != expected_user_events) {
		error = ast_cond_timedwait(&user_event_cond, &user_event_lock, &wait_time);
		if (error == ETIMEDOUT) {
			ast_test_status_update(test, "Test timed out while waiting for %d expected user events\n", expected_events);
			ast_test_set_result(test, AST_TEST_FAIL);
			break;
		}
	}
	ast_mutex_unlock(&user_event_lock);

	ast_test_status_update(test, "Received %d of %d user events\n", received_user_events, expected_events);
	return !(received_user_events == expected_events);
}

static int verify_bad_headers(struct ast_test *test)
{
	int res = 0;
	int i;

	for (i = 0; i < AST_VECTOR_SIZE(&bad_headers); i++) {
		struct ast_variable *headers;
		struct ast_variable *current;

		headers = AST_VECTOR_GET(&bad_headers, i);
		if (!headers) {
			continue;
		}

		res = -1;
		for (current = headers; current; current = current->next) {
			ast_test_status_update(test, "Expected UserEvent %d: Failed to match %s: %s\n",
				i, current->name, current->value);
			ast_test_set_result(test, AST_TEST_FAIL);
		}
	}

	return res;
}
예제 #25
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;
}
예제 #26
0
파일: test_event.c 프로젝트: mtulio/mtulio
static int check_event(struct ast_event *event, struct ast_test *test,
		enum ast_event_type expected_type, const char *type_name,
		const char *str, uint32_t uint, uint32_t bitflags)
{
	enum ast_event_type type;
	const void *foo;

	/* Check #1: Ensure event type is set properly. */
	type = ast_event_get_type(event);
	if (ast_event_get_type(event) != type) {
		ast_test_status_update(test, "Expected event type: '%d', got '%d'\n",
				expected_type, type);
		return -1;
	}

	/* Check #2: Check string representation of event type */
	if (strcmp(type_name, ast_event_get_type_name(event))) {
		ast_test_status_update(test, "Didn't get expected type name: '%s' != '%s'\n",
				type_name, ast_event_get_type_name(event));
		return -1;
	}

	/* Check #3: Check for automatically included EID */
	if (memcmp(&ast_eid_default, ast_event_get_ie_raw(event, AST_EVENT_IE_EID), sizeof(ast_eid_default))) {
		ast_test_status_update(test, "Failed to get EID\n");
		return -1;
	}

	/* Check #4: Check for the string IE */
	if (strcmp(str, ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX))) {
		ast_test_status_update(test, "Failed to get string IE.\n");
		return -1;
	}

	/* Check #5: Check for the uint IE */
	if (uint != ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS)) {
		ast_test_status_update(test, "Failed to get uint IE.\n");
		return -1;
	}

	/* Check #6: Check for the bitflags IE */
	if (bitflags != ast_event_get_ie_bitflags(event, AST_EVENT_IE_OLDMSGS)) {
		ast_test_status_update(test, "Failed to get bitflags IE.\n");
		return -1;
	}

	/* Check #7: Check if a check for a str IE that isn't there works */
	if ((foo = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE))) {
		ast_test_status_update(test, "DEVICE IE check returned non-NULL %p\n", foo);
		return -1;
	}

	/* Check #8: Check if a check for a uint IE that isn't there returns 0 */
	if (ast_event_get_ie_uint(event, AST_EVENT_IE_STATE)) {
		ast_test_status_update(test, "OLDMSGS IE should be 0\n");
		return -1;
	}

	ast_test_status_update(test, "Event looks good.\n");

	return 0;
}
static int astobj2_test_helper(int use_hash, int use_cmp, unsigned int lim, struct ast_test *test)
{
	struct ao2_container *c1;
	struct ao2_container *c2;
	struct ao2_iterator it;
	struct test_obj *obj;
	struct test_obj tmp_obj;
	int bucket_size;
	int increment = 0;
	int destructor_count = 0;
	int num;
	int  res = AST_TEST_PASS;

	/* This test needs at least 5 objects */
	if (lim < 5) {
		lim = 5;
	}

	bucket_size = (ast_random() % ((lim / 4) + 1)) + 1;
	c1 = ao2_container_alloc(bucket_size, use_hash ? test_hash_cb : NULL, use_cmp ? test_cmp_cb : NULL);
	c2 = ao2_container_alloc(bucket_size, test_hash_cb, test_cmp_cb);

	if (!c1 || !c2) {
		ast_test_status_update(test, "ao2_container_alloc failed.\n");
		res = AST_TEST_FAIL;
		goto cleanup;
	}

	/* Create objects and link into container */
	destructor_count = lim;
	for (num = 1; num <= lim; num++) {
		if (!(obj = ao2_alloc(sizeof(struct test_obj), test_obj_destructor))) {
			ast_test_status_update(test, "ao2_alloc failed.\n");
			res = AST_TEST_FAIL;
			goto cleanup;
		}
		snprintf(obj->c, sizeof(obj->c), "zombie #%d", num);
		obj->destructor_count = &destructor_count;
		obj->i = num;
		ao2_link(c1, obj);
		ao2_ref(obj, -1);
		if (ao2_container_count(c1) != num) {
			ast_test_status_update(test, "container did not link correctly\n");
			res = AST_TEST_FAIL;
		}
	}

	ast_test_status_update(test, "Container created: random bucket size %d: number of items: %d\n", bucket_size, lim);

	/* Testing ao2_find with no flags */
	num = 100;
	for (; num; num--) {
		int i = (ast_random() % ((lim / 2)) + 1); /* find a random object */
		tmp_obj.i = i;
		if (!(obj = ao2_find(c1, &tmp_obj, 0))) {
			res = AST_TEST_FAIL;
			ast_test_status_update(test, "COULD NOT FIND:%d, ao2_find() with no flags failed.\n", i);
		} else {
			/* a correct match will only take place when the custom cmp function is used */
			if (use_cmp && obj->i != i) {
				ast_test_status_update(test, "object %d does not match object %d\n", obj->i, tmp_obj.i);
				res = AST_TEST_FAIL;
			}
			ao2_ref(obj, -1);
		}
	}

	/* Testing ao2_find with OBJ_POINTER */
	num = 75;
	for (; num; num--) {
		int i = (ast_random() % ((lim / 2)) + 1); /* find a random object */
		snprintf(tmp_obj.c, sizeof(tmp_obj.c), "zombie #%d", i);
		tmp_obj.i = i;
		if (!(obj = ao2_find(c1, &tmp_obj, OBJ_POINTER))) {
			res = AST_TEST_FAIL;
			ast_test_status_update(test, "COULD NOT FIND:%d, ao2_find() with OBJ_POINTER flag failed.\n", i);
		} else {
			/* a correct match will only take place when the custom cmp function is used */
			if (use_cmp && obj->i != i) {
				ast_test_status_update(test, "object %d does not match object %d\n", obj->i, tmp_obj.i);
				res = AST_TEST_FAIL;
			}
			ao2_ref(obj, -1);
		}
	}

	/* Testing ao2_find with OBJ_POINTER | OBJ_UNLINK | OBJ_CONTINUE.
	 * In this test items are unlinked from c1 and placed in c2.  Then
	 * unlinked from c2 and placed back into c1.
	 *
	 * For this module and set of custom hash/cmp functions, an object
	 * should only be found if the astobj2 default cmp function is used.
	 * This test is designed to mimic the chan_iax.c call number use case. */
	num = lim < 25 ? lim : 25;
	for (; num; num--) {
		if (!(obj = ao2_find(c1, NULL, OBJ_POINTER | OBJ_UNLINK | OBJ_CONTINUE))) {
			if (!use_cmp) {
				ast_test_status_update(test, "ao2_find with OBJ_POINTER | OBJ_UNLINK | OBJ_CONTINUE failed with default hash function.\n");
				res = AST_TEST_FAIL;
			}
		} else {
			if (use_cmp) {
				ast_test_status_update(test, "ao2_find with OBJ_POINTER | OBJ_UNLINK | OBJ_CONTINUE failed with custom hash function.\n");
				res = AST_TEST_FAIL;
			}
			ao2_link(c2, obj);
			ao2_ref(obj, -1);
		}
	}
	it = ao2_iterator_init(c2, 0);
	while ((obj = ao2_iterator_next(&it))) {
		ao2_unlink(c2, obj);
		ao2_link(c1, obj);
		ao2_ref(obj, -1);
	}
	ao2_iterator_destroy(&it);

	/* Test Callback with no flags. */
	increment = 0;
	ao2_callback(c1, 0, increment_cb, &increment);
	if (increment != lim) {
		ast_test_status_update(test, "callback with no flags failed. Increment is %d\n", increment);
		res = AST_TEST_FAIL;
	}

	/* Test Callback with OBJ_NODATA. This should do nothing different than with no flags here. */
	increment = 0;
	ao2_callback(c1, OBJ_NODATA, increment_cb, &increment);
	if (increment != lim) {
		ast_test_status_update(test, "callback with OBJ_NODATA failed. Increment is %d\n", increment);
		res = AST_TEST_FAIL;
	}

	/* Is the container count what we expect after all the finds and unlinks?*/
	if (ao2_container_count(c1) != lim) {
		ast_test_status_update(test, "container count does not match what is expected after ao2_find tests.\n");
		res = AST_TEST_FAIL;
	}

	/* Testing iterator.  Unlink a single object and break. do not add item back */
	it = ao2_iterator_init(c1, 0);
	num = (lim / 4) + 1;
	while ((obj = ao2_iterator_next(&it))) {
		if (obj->i == num) {
			ao2_ref(obj, -1);
			ao2_unlink(c1, obj);
			break;
		}
		ao2_ref(obj, -1);
	}
	ao2_iterator_destroy(&it);

	/* Is the container count what we expect after removing a single item? */
	if (ao2_container_count(c1) != (lim - 1)) {
		ast_test_status_update(test, "unlink during iterator failed. Number %d was not removed.\n", num);
		res = AST_TEST_FAIL;
	}

	/* Test unlink all with OBJ_MULTIPLE, leave a single object for the container to destroy */
	ao2_callback(c1, OBJ_MULTIPLE | OBJ_UNLINK | OBJ_NODATA, all_but_one_cb, NULL);
	/* check to make sure all test_obj destructors were called except for 1 */
	if (destructor_count != 1) {
		ast_test_status_update(test, "OBJ_MULTIPLE | OBJ_UNLINK | OBJ_NODATA failed. destructor count %d\n", destructor_count);
		res = AST_TEST_FAIL;
	}

cleanup:
	/* destroy containers */
	if (c1) {
		ao2_ref(c1, -1);
	}
	if (c2) {
		ao2_ref(c2, -1);
	}

	if (destructor_count > 0) {
		ast_test_status_update(test, "all destructors were not called, destructor count is %d\n", destructor_count);
		res = AST_TEST_FAIL;
	} else if (destructor_count < 0) {
		ast_test_status_update(test, "Destructor was called too many times, destructor count is %d\n", destructor_count);
		res = AST_TEST_FAIL;
	}

	return res;
}