#include #include #include #include #include #include #include #include #include #include static void check_type(enum ctrl_type c) { const char *t = get_value_string(ctrl_type_vals, c); int v = get_string_value(ctrl_type_vals, t); printf("ctrl type %d is %s ", c, t); if (v < 0) printf("[PARSE FAILED]\n"); else 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); check_type(CTRL_TYPE_GET); check_type(CTRL_TYPE_SET); check_type(CTRL_TYPE_GET_REPLY); check_type(CTRL_TYPE_SET_REPLY); check_type(CTRL_TYPE_TRAP); check_type(CTRL_TYPE_ERROR); check_type(64); test_parsing(); return 0; }