aboutsummaryrefslogtreecommitdiffstats
path: root/tests/ctrl/ctrl_test.c
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2017-09-26 15:24:58 +0200
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-09-27 14:04:23 +0000
commit505c965e3655b8ae94880a23baf8ecc2092163c4 (patch)
tree65a8b27941e41f306d205fb2e5cace6d095966aa /tests/ctrl/ctrl_test.c
parentf4f23bd6829f78741cfd586f0ca9a290f221242e (diff)
CTRL: add unit tests for CTRL command parsing
This uncovers some interesting behavior of the CTRL interface which we may want to guard against in subsequent patches: trailing whitespace, ignored tokens, special characters as cmd->id. Change-Id: If7af06d50ca71fd528b08cd70310774d5a53f0f7
Diffstat (limited to 'tests/ctrl/ctrl_test.c')
-rw-r--r--tests/ctrl/ctrl_test.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/tests/ctrl/ctrl_test.c b/tests/ctrl/ctrl_test.c
index 08be15f6..b8425c7e 100644
--- a/tests/ctrl/ctrl_test.c
+++ b/tests/ctrl/ctrl_test.c
@@ -6,6 +6,9 @@
#include <osmocom/core/utils.h>
#include <osmocom/ctrl/control_cmd.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/application.h>
static void check_type(enum ctrl_type c)
{
@@ -19,8 +22,254 @@ static void check_type(enum ctrl_type c)
printf("-> %d %s\n", v, c != v ? "FAIL" : "OK");
}
+struct msgb *msgb_from_string(const char *str)
+{
+ char *rc;
+ 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);
+ return msg;
+}
+
+static void *ctx = NULL;
+
+void print_escaped(const char *str)
+{
+ if (!str) {
+ printf("NULL");
+ return;
+ }
+
+ printf("'");
+ for (;*str; str++) {
+ switch (*str) {
+ case '\n':
+ printf("\\n");
+ break;
+ case '\r':
+ printf("\\r");
+ break;
+ case '\t':
+ printf("\\t");
+ break;
+ default:
+ printf("%c", *str);
+ break;
+ }
+ }
+ printf("'");
+}
+
+void assert_same_str(const char *label, const char *expect, const char *got)
+{
+ if ((expect == got) || (expect && got && (strcmp(expect, got) == 0))) {
+ printf("%s = ", label);
+ print_escaped(got);
+ printf("\n");
+ return;
+ }
+
+ printf("MISMATCH for '%s':\ngot: ", label); print_escaped(got);
+ printf("\nexpected: "); print_escaped(expect);
+ printf("\n");
+ OSMO_ASSERT(expect == got);
+}
+
+static void assert_parsing(const char *str, const struct ctrl_cmd *expect)
+{
+ struct ctrl_cmd *cmd;
+ struct msgb *msg = msgb_from_string(str);
+
+ printf("test parsing: ");
+ print_escaped(str);
+ printf("\n");
+
+ cmd = ctrl_cmd_parse(ctx, msg);
+ OSMO_ASSERT(cmd);
+
+ OSMO_ASSERT(expect->type == cmd->type);
+
+#define ASSERT_SAME_STR(field) \
+ assert_same_str(#field, expect->field, cmd->field)
+
+ ASSERT_SAME_STR(id);
+ ASSERT_SAME_STR(variable);
+ ASSERT_SAME_STR(value);
+ ASSERT_SAME_STR(reply);
+
+ talloc_free(cmd);
+ msgb_free(msg);
+
+ printf("ok\n");
+}
+
+struct one_parsing_test {
+ const char *cmd_str;
+ struct ctrl_cmd expect;
+};
+
+static const struct one_parsing_test test_parsing_list[] = {
+ { "GET 1 variable",
+ {
+ .type = CTRL_TYPE_GET,
+ .id = "1",
+ .variable = "variable",
+ }
+ },
+ { "GET 1 variable\n",
+ {
+ .type = CTRL_TYPE_GET,
+ .id = "1",
+ .variable = "variable\n", /* current bug */
+ }
+ },
+ { "GET 1 var\ni\nable",
+ {
+ .type = CTRL_TYPE_GET,
+ .id = "1",
+ .variable = "var\ni\nable", /* current bug */
+ }
+ },
+ { "GET 1 variable value",
+ {
+ .type = CTRL_TYPE_GET,
+ .id = "1",
+ .variable = "variable",
+ .value = NULL,
+ }
+ },
+ { "GET 1 variable value\n",
+ {
+ .type = CTRL_TYPE_GET,
+ .id = "1",
+ .variable = "variable",
+ .value = NULL,
+ }
+ },
+ { "GET 1 variable multiple value tokens",
+ {
+ .type = CTRL_TYPE_GET,
+ .id = "1",
+ .variable = "variable",
+ .value = NULL,
+ }
+ },
+ { "GET 1 variable multiple value tokens\n",
+ {
+ .type = CTRL_TYPE_GET,
+ .id = "1",
+ .variable = "variable",
+ .value = NULL,
+ }
+ },
+ { "SET 1 variable value",
+ {
+ .type = CTRL_TYPE_SET,
+ .id = "1",
+ .variable = "variable",
+ .value = "value",
+ }
+ },
+ { "SET 1 variable value\n",
+ {
+ .type = CTRL_TYPE_SET,
+ .id = "1",
+ .variable = "variable",
+ .value = "value",
+ }
+ },
+ { "SET weird_id variable value",
+ {
+ .type = CTRL_TYPE_SET,
+ .id = "weird_id",
+ .variable = "variable",
+ .value = "value",
+ }
+ },
+ { "SET weird_id variable value\n",
+ {
+ .type = CTRL_TYPE_SET,
+ .id = "weird_id",
+ .variable = "variable",
+ .value = "value",
+ }
+ },
+ { "SET 1 variable multiple value tokens",
+ {
+ .type = CTRL_TYPE_SET,
+ .id = "1",
+ .variable = "variable",
+ .value = "multiple value tokens",
+ }
+ },
+ { "SET 1 variable multiple value tokens\n",
+ {
+ .type = CTRL_TYPE_SET,
+ .id = "1",
+ .variable = "variable",
+ .value = "multiple value tokens",
+ }
+ },
+ { "SET 1 variable value_with_trailing_spaces ",
+ {
+ .type = CTRL_TYPE_SET,
+ .id = "1",
+ .variable = "variable",
+ .value = "value_with_trailing_spaces ",
+ }
+ },
+ { "SET 1 variable value_with_trailing_spaces \n",
+ {
+ .type = CTRL_TYPE_SET,
+ .id = "1",
+ .variable = "variable",
+ .value = "value_with_trailing_spaces ",
+ }
+ },
+ { "SET \n special_char_id value",
+ {
+ .type = CTRL_TYPE_SET,
+ .id = "\n",
+ .variable = "special_char_id",
+ .value = "value",
+ }
+ },
+ { "SET \t special_char_id value",
+ {
+ .type = CTRL_TYPE_SET,
+ .id = "\t",
+ .variable = "special_char_id",
+ .value = "value",
+ }
+ },
+};
+
+static void test_parsing()
+{
+ 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);
+}
+
+static struct log_info_cat test_categories[] = {
+};
+
+static struct log_info info = {
+ .cat = test_categories,
+ .num_cat = ARRAY_SIZE(test_categories),
+};
+
int main(int argc, char **argv)
{
+ ctx = talloc_named_const(NULL, 1, "ctrl_test");
+ osmo_init_logging(&info);
+
printf("Checking ctrl types...\n");
check_type(CTRL_TYPE_UNKNOWN);
@@ -32,5 +281,7 @@ int main(int argc, char **argv)
check_type(CTRL_TYPE_ERROR);
check_type(64);
+ test_parsing();
+
return 0;
}