diff options
| author | Neels Hofmeyr <neels@hofmeyr.de> | 2017-12-16 05:38:37 +0100 | 
|---|---|---|
| committer | Harald Welte <laforge@gnumonks.org> | 2017-12-18 23:05:50 +0000 | 
| commit | 83aee83ec6a9d3d5e4f9251221c9639028d3da89 (patch) | |
| tree | b157a2e53a363347611b64c016624be2131481e3 /tests/ctrl | |
| parent | d53d2169442fd43ed1538c3970c6e7cb6096f20a (diff) | |
ctrl_test: expand to test message handling and detect mem leaks
Subsequent patches that tighten CTRL input validation will make the results
more interesting.
Change-Id: Idd4cc7d193db1a7d761f72ed33ed46eea450a78f
Diffstat (limited to 'tests/ctrl')
| -rw-r--r-- | tests/ctrl/ctrl_test.c | 169 | ||||
| -rw-r--r-- | tests/ctrl/ctrl_test.ok | 85 | 
2 files changed, 197 insertions, 57 deletions
diff --git a/tests/ctrl/ctrl_test.c b/tests/ctrl/ctrl_test.c index 2bc31285..b3fa05ee 100644 --- a/tests/ctrl/ctrl_test.c +++ b/tests/ctrl/ctrl_test.c @@ -9,6 +9,8 @@  #include <osmocom/core/logging.h>  #include <osmocom/core/msgb.h>  #include <osmocom/core/application.h> +#include <osmocom/gsm/protocol/ipaccess.h> +#include <osmocom/ctrl/control_if.h>  static void check_type(enum ctrl_type c)  { @@ -24,19 +26,35 @@ static void check_type(enum ctrl_type c)  struct msgb *msgb_from_string(const char *str)  { -	char *rc; +	struct ipaccess_head *iph; +	struct ipaccess_head_ext *ipx; +	char *str_msg;  	size_t len = strlen(str) + 1; -	/* ctrl_cmd_parse() appends a '\0' to the msgb, allow one more byte. */ -	struct msgb *msg = msgb_alloc(len + 1, str); -	msg->l2h = msg->head; -	rc = (char*)msgb_put(msg, len); -	OSMO_ASSERT(rc == (char*)msg->l2h); -	strcpy(rc, str); + +	struct msgb *msg = msgb_alloc(1024, str); + +	iph = (void*)msgb_put(msg, sizeof(*iph)); +	iph->proto = IPAC_PROTO_OSMO; + +	ipx = (void*)msgb_put(msg, sizeof(*ipx)); +	ipx->proto = IPAC_PROTO_EXT_CTRL; + +	str_msg = (char*)msgb_put(msg, len); +	msg->l2h = (void*)str_msg; +	osmo_strlcpy(str_msg, str, len); + +	iph->len = msgb_length(msg);  	return msg;  }  static void *ctx = NULL; +struct one_test { +	const char *cmd_str; +	struct ctrl_cmd expect_parsed; +	const char *reply_str; +}; +  void assert_same_str(const char *label, const char *expect, const char *got)  {  	if ((expect == got) || (expect && got && (strcmp(expect, got) == 0))) { @@ -49,20 +67,22 @@ void assert_same_str(const char *label, const char *expect, const char *got)  	OSMO_ASSERT(expect == got);  } -static void assert_parsing(const char *str, const struct ctrl_cmd *expect) +static void assert_test(struct ctrl_handle *ctrl, struct ctrl_connection *ccon, const struct one_test *t)  {  	struct ctrl_cmd *cmd; -	struct msgb *msg = msgb_from_string(str); +	struct msgb *msg = msgb_from_string(t->cmd_str); +	int ctx_size_was; -	printf("test parsing: '%s'\n", osmo_escape_str(str, -1)); +	printf("test: '%s'\n", osmo_escape_str(t->cmd_str, -1)); +	printf("parsing:\n");  	cmd = ctrl_cmd_parse(ctx, msg);  	OSMO_ASSERT(cmd); -	OSMO_ASSERT(expect->type == cmd->type); +	OSMO_ASSERT(t->expect_parsed.type == cmd->type);  #define ASSERT_SAME_STR(field) \ -	assert_same_str(#field, expect->field, cmd->field) +	assert_same_str(#field, t->expect_parsed.field, cmd->field)  	ASSERT_SAME_STR(id);  	ASSERT_SAME_STR(variable); @@ -72,35 +92,67 @@ static void assert_parsing(const char *str, const struct ctrl_cmd *expect)  	talloc_free(cmd);  	msgb_free(msg); +	printf("handling:\n"); + +	ctx_size_was = talloc_total_size(ctx); + +	msg = msgb_from_string(t->cmd_str); +	ctrl_handle_msg(ctrl, ccon, msg); + +	if (llist_empty(&ccon->write_queue.msg_queue)) { +		if (t->reply_str) { +			printf("Got no reply, but expected \"%s\"\n", osmo_escape_str(t->reply_str, -1)); +			OSMO_ASSERT(!t->reply_str); +		} +	} else { +		struct msgb *sent_msg = msgb_dequeue(&ccon->write_queue.msg_queue); +		OSMO_ASSERT(sent_msg); +		msgb_put_u8(sent_msg, 0); + +		printf("replied: '%s'\n", osmo_escape_str((char*)msgb_l2(sent_msg), -1)); +		OSMO_ASSERT(t->reply_str); +		OSMO_ASSERT(!strcmp(t->reply_str, (char*)msgb_l2(sent_msg))) +		msgb_free(sent_msg); +	} +	osmo_wqueue_clear(&ccon->write_queue); + +	msgb_free(msg); + +	if (talloc_total_size(ctx) != ctx_size_was) { +		printf("mem leak!\n"); +		talloc_report_full(ctx, stdout); +		OSMO_ASSERT(false); +	} +  	printf("ok\n");  } -struct one_parsing_test { -	const char *cmd_str; -	struct ctrl_cmd expect; -}; - -static const struct one_parsing_test test_parsing_list[] = { +static const struct one_test test_messages_list[] = {  	{ "GET 1 variable",  		{  			.type = CTRL_TYPE_GET,  			.id = "1",  			.variable = "variable", -		} +		}, +		"ERROR 1 Command not found",  	},  	{ "GET 1 variable\n",  		{  			.type = CTRL_TYPE_GET,  			.id = "1",  			.variable = "variable\n", /* current bug */ -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "GET 1 var\ni\nable",  		{  			.type = CTRL_TYPE_GET,  			.id = "1",  			.variable = "var\ni\nable", /* current bug */ -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "GET 1 variable value",  		{ @@ -108,7 +160,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "1",  			.variable = "variable",  			.value = NULL, -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "GET 1 variable value\n",  		{ @@ -116,7 +170,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "1",  			.variable = "variable",  			.value = NULL, -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "GET 1 variable multiple value tokens",  		{ @@ -124,7 +180,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "1",  			.variable = "variable",  			.value = NULL, -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "GET 1 variable multiple value tokens\n",  		{ @@ -132,7 +190,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "1",  			.variable = "variable",  			.value = NULL, -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "SET 1 variable value",  		{ @@ -140,7 +200,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "1",  			.variable = "variable",  			.value = "value", -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "SET 1 variable value\n",  		{ @@ -148,7 +210,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "1",  			.variable = "variable",  			.value = "value", -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "SET weird_id variable value",  		{ @@ -156,7 +220,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "weird_id",  			.variable = "variable",  			.value = "value", -		} +		}, +		"ERROR weird_id Command not found", +  	},  	{ "SET weird_id variable value\n",  		{ @@ -164,7 +230,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "weird_id",  			.variable = "variable",  			.value = "value", -		} +		}, +		"ERROR weird_id Command not found", +  	},  	{ "SET 1 variable multiple value tokens",  		{ @@ -172,7 +240,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "1",  			.variable = "variable",  			.value = "multiple value tokens", -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "SET 1 variable multiple value tokens\n",  		{ @@ -180,7 +250,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "1",  			.variable = "variable",  			.value = "multiple value tokens", -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "SET 1 variable value_with_trailing_spaces  ",  		{ @@ -188,7 +260,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "1",  			.variable = "variable",  			.value = "value_with_trailing_spaces  ", -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "SET 1 variable value_with_trailing_spaces  \n",  		{ @@ -196,7 +270,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "1",  			.variable = "variable",  			.value = "value_with_trailing_spaces  ", -		} +		}, +		"ERROR 1 Command not found", +  	},  	{ "SET \n special_char_id value",  		{ @@ -204,7 +280,9 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "\n",  			.variable = "special_char_id",  			.value = "value", -		} +		}, +		"ERROR \n Command not found", +  	},  	{ "SET \t special_char_id value",  		{ @@ -212,17 +290,28 @@ static const struct one_parsing_test test_parsing_list[] = {  			.id = "\t",  			.variable = "special_char_id",  			.value = "value", -		} +		}, +		"ERROR \t Command not found", +  	},  }; -static void test_parsing() +static void test_messages()  { +	struct ctrl_handle *ctrl; +	struct ctrl_connection *ccon;  	int i; -	for (i = 0; i < ARRAY_SIZE(test_parsing_list); i++) -		assert_parsing(test_parsing_list[i].cmd_str, -			       &test_parsing_list[i].expect); +	ctrl = ctrl_handle_alloc2(ctx, NULL, NULL, 0); +	ccon = talloc_zero(ctx, struct ctrl_connection); + +	osmo_wqueue_init(&ccon->write_queue, 1); + +	for (i = 0; i < ARRAY_SIZE(test_messages_list); i++) +		assert_test(ctrl, ccon, &test_messages_list[i]); + +	talloc_free(ccon); +	talloc_free(ctrl);  }  static struct log_info_cat test_categories[] = { @@ -249,7 +338,7 @@ int main(int argc, char **argv)  	check_type(CTRL_TYPE_ERROR);  	check_type(64); -	test_parsing(); +	test_messages();  	return 0;  } diff --git a/tests/ctrl/ctrl_test.ok b/tests/ctrl/ctrl_test.ok index 5775eb22..edf97ead 100644 --- a/tests/ctrl/ctrl_test.ok +++ b/tests/ctrl/ctrl_test.ok @@ -7,105 +7,156 @@ ctrl type 4 is SET_REPLY -> 4 OK  ctrl type 5 is TRAP -> 5 OK  ctrl type 6 is ERROR -> 6 OK  ctrl type 64 is unknown 0x40 [PARSE FAILED] -test parsing: 'GET 1 variable' +test: 'GET 1 variable' +parsing:  id = '1'  variable = 'variable'  value = '(null)'  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'GET 1 variable\n' +test: 'GET 1 variable\n' +parsing:  id = '1'  variable = 'variable\n'  value = '(null)'  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'GET 1 var\ni\nable' +test: 'GET 1 var\ni\nable' +parsing:  id = '1'  variable = 'var\ni\nable'  value = '(null)'  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'GET 1 variable value' +test: 'GET 1 variable value' +parsing:  id = '1'  variable = 'variable'  value = '(null)'  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'GET 1 variable value\n' +test: 'GET 1 variable value\n' +parsing:  id = '1'  variable = 'variable'  value = '(null)'  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'GET 1 variable multiple value tokens' +test: 'GET 1 variable multiple value tokens' +parsing:  id = '1'  variable = 'variable'  value = '(null)'  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'GET 1 variable multiple value tokens\n' +test: 'GET 1 variable multiple value tokens\n' +parsing:  id = '1'  variable = 'variable'  value = '(null)'  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'SET 1 variable value' +test: 'SET 1 variable value' +parsing:  id = '1'  variable = 'variable'  value = 'value'  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'SET 1 variable value\n' +test: 'SET 1 variable value\n' +parsing:  id = '1'  variable = 'variable'  value = 'value'  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'SET weird_id variable value' +test: 'SET weird_id variable value' +parsing:  id = 'weird_id'  variable = 'variable'  value = 'value'  reply = '(null)' +handling: +replied: 'ERROR weird_id Command not found'  ok -test parsing: 'SET weird_id variable value\n' +test: 'SET weird_id variable value\n' +parsing:  id = 'weird_id'  variable = 'variable'  value = 'value'  reply = '(null)' +handling: +replied: 'ERROR weird_id Command not found'  ok -test parsing: 'SET 1 variable multiple value tokens' +test: 'SET 1 variable multiple value tokens' +parsing:  id = '1'  variable = 'variable'  value = 'multiple value tokens'  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'SET 1 variable multiple value tokens\n' +test: 'SET 1 variable multiple value tokens\n' +parsing:  id = '1'  variable = 'variable'  value = 'multiple value tokens'  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'SET 1 variable value_with_trailing_spaces  ' +test: 'SET 1 variable value_with_trailing_spaces  ' +parsing:  id = '1'  variable = 'variable'  value = 'value_with_trailing_spaces  '  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'SET 1 variable value_with_trailing_spaces  \n' +test: 'SET 1 variable value_with_trailing_spaces  \n' +parsing:  id = '1'  variable = 'variable'  value = 'value_with_trailing_spaces  '  reply = '(null)' +handling: +replied: 'ERROR 1 Command not found'  ok -test parsing: 'SET \n special_char_id value' +test: 'SET \n special_char_id value' +parsing:  id = '\n'  variable = 'special_char_id'  value = 'value'  reply = '(null)' +handling: +replied: 'ERROR \n Command not found'  ok -test parsing: 'SET \t special_char_id value' +test: 'SET \t special_char_id value' +parsing:  id = '\t'  variable = 'special_char_id'  value = 'value'  reply = '(null)' +handling: +replied: 'ERROR \t Command not found'  ok  | 
