diff --git a/lib/isc/tests/lex_test.c b/lib/isc/tests/lex_test.c index a4b27606e5..f712d7e276 100644 --- a/lib/isc/tests/lex_test.c +++ b/lib/isc/tests/lex_test.c @@ -29,6 +29,8 @@ #include "isctest.h" +#define AS_STR(x) (x).value.as_textregion.base + static bool debug = false; static int @@ -121,6 +123,217 @@ lex_setline(void **state) { isc_lex_destroy(&lex); } +static struct { + const char *text; + const char *string_value; + isc_result_t string_result; + isc_tokentype_t string_type; + const char *qstring_value; + isc_result_t qstring_result; + isc_tokentype_t qstring_type; + const char *qvpair_value; + isc_result_t qvpair_result; + isc_tokentype_t qvpair_type; +} parse_tests[] = { + { "", "", ISC_R_SUCCESS, isc_tokentype_eof, "", ISC_R_SUCCESS, + isc_tokentype_eof, "", ISC_R_SUCCESS, isc_tokentype_eof }, + { "1234", "1234", ISC_R_SUCCESS, isc_tokentype_string, "1234", + ISC_R_SUCCESS, isc_tokentype_string, "1234", ISC_R_SUCCESS, + isc_tokentype_string }, + { "1234=", "1234=", ISC_R_SUCCESS, isc_tokentype_string, + "1234=", ISC_R_SUCCESS, isc_tokentype_string, "1234=", ISC_R_SUCCESS, + isc_tokentype_vpair }, + { "1234=foo", "1234=foo", ISC_R_SUCCESS, isc_tokentype_string, + "1234=foo", ISC_R_SUCCESS, isc_tokentype_string, "1234=foo", + ISC_R_SUCCESS, isc_tokentype_vpair }, + { "1234=\"foo", "1234=\"foo", ISC_R_SUCCESS, isc_tokentype_string, + "1234=\"foo", ISC_R_SUCCESS, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0 }, + { "1234=\"foo\"", "1234=\"foo\"", ISC_R_SUCCESS, isc_tokentype_string, + "1234=\"foo\"", ISC_R_SUCCESS, isc_tokentype_string, "1234=foo", + ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key", "key", ISC_R_SUCCESS, isc_tokentype_string, "key", + ISC_R_SUCCESS, isc_tokentype_string, "key", ISC_R_SUCCESS, + isc_tokentype_string }, + { "\"key=", "\"key=", ISC_R_SUCCESS, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0, "\"key=", ISC_R_SUCCESS, + isc_tokentype_vpair }, + { "\"key=\"", "\"key=\"", ISC_R_SUCCESS, isc_tokentype_string, "key=", + ISC_R_SUCCESS, isc_tokentype_qstring, NULL, ISC_R_UNEXPECTEDEND, 0 }, + { "key=\"\"", "key=\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key=\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key=", ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key=\"a b\"", "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, "key=a b", + ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key=\"a\tb\"", "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, "key=a\tb", + ISC_R_SUCCESS, isc_tokentype_qvpair }, + /* double quote not immediately after '=' is not special. */ + { "key=c\"a b\"", "key=c\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key=c\"a", ISC_R_SUCCESS, isc_tokentype_string, "key=c\"a", + ISC_R_SUCCESS, isc_tokentype_vpair }, + /* remove special meaning for '=' by escaping */ + { "key\\=", "key\\=", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=", ISC_R_SUCCESS, isc_tokentype_string }, + { "key\\=\"a\"", "key\\=\"a\"", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=\"a\"", ISC_R_SUCCESS, isc_tokentype_string, "key\\=\"a\"", + ISC_R_SUCCESS, isc_tokentype_string }, + { "key\\=\"a \"", "key\\=\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=\"a", ISC_R_SUCCESS, isc_tokentype_string, "key\\=\"a", + ISC_R_SUCCESS, isc_tokentype_string }, + /* vpair with a key of 'key\=' (would need to be deescaped) */ + { "key\\==", "key\\==", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==", ISC_R_SUCCESS, isc_tokentype_vpair }, + { "key\\==\"\"", "key\\==\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==", ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key=\\\\\\\\", "key=\\\\\\\\", ISC_R_SUCCESS, isc_tokentype_string, + "key=\\\\\\\\", ISC_R_SUCCESS, isc_tokentype_string, "key=\\\\\\\\", + ISC_R_SUCCESS, isc_tokentype_vpair }, + { "key=\\\\\\\"", "key=\\\\\\\"", ISC_R_SUCCESS, isc_tokentype_string, + "key=\\\\\\\"", ISC_R_SUCCESS, isc_tokentype_string, "key=\\\\\\\"", + ISC_R_SUCCESS, isc_tokentype_vpair }, + /* incomplete escape sequence */ + { "key=\\\"\\", NULL, ISC_R_UNEXPECTEDEND, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0, NULL, ISC_R_UNEXPECTEDEND, 0 }, + /* incomplete escape sequence */ + { "key=\\", NULL, ISC_R_UNEXPECTEDEND, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0, NULL, ISC_R_UNEXPECTEDEND, 0 }, +}; + +/*% + * string + */ +static void +lex_string(void **state) { + isc_buffer_t buf; + isc_lex_t *lex = NULL; + isc_result_t result; + isc_token_t token; + size_t i; + + UNUSED(state); + + for (i = 0; i < ARRAY_SIZE(parse_tests); i++) { + result = isc_lex_create(test_mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_constinit(&buf, parse_tests[i].text, + strlen(parse_tests[i].text)); + isc_buffer_add(&buf, strlen(parse_tests[i].text)); + + result = isc_lex_openbuffer(lex, &buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_setsourceline(lex, 100); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(&token, 0, sizeof(token)); + result = isc_lex_getmastertoken(lex, &token, + isc_tokentype_string, true); + if (debug) { + fprintf(stdout, "# '%s' -> result=%s/%s, type=%u/%u\n", + parse_tests[i].text, isc_result_toid(result), + isc_result_toid(parse_tests[i].string_result), + token.type, parse_tests[i].string_type); + } + + assert_int_equal(result, parse_tests[i].string_result); + if (result == ISC_R_SUCCESS) { + switch (token.type) { + case isc_tokentype_string: + case isc_tokentype_qstring: + case isc_tokentype_vpair: + case isc_tokentype_qvpair: + if (debug) { + fprintf(stdout, "# value='%s'\n", + AS_STR(token)); + } + assert_int_equal(token.type, + parse_tests[i].string_type); + assert_string_equal( + AS_STR(token), + parse_tests[i].string_value); + break; + default: + assert_int_equal(token.type, + parse_tests[i].string_type); + break; + } + } + + isc_lex_destroy(&lex); + } +} + +/*% + * qstring + */ +static void +lex_qstring(void **state) { + isc_buffer_t buf; + isc_lex_t *lex = NULL; + isc_result_t result; + isc_token_t token; + size_t i; + + UNUSED(state); + + for (i = 0; i < ARRAY_SIZE(parse_tests); i++) { + result = isc_lex_create(test_mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_constinit(&buf, parse_tests[i].text, + strlen(parse_tests[i].text)); + isc_buffer_add(&buf, strlen(parse_tests[i].text)); + + result = isc_lex_openbuffer(lex, &buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_setsourceline(lex, 100); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(&token, 0, sizeof(token)); + result = isc_lex_getmastertoken(lex, &token, + isc_tokentype_qstring, true); + if (debug) { + fprintf(stdout, "# '%s' -> result=%s/%s, type=%u/%u\n", + parse_tests[i].text, isc_result_toid(result), + isc_result_toid(parse_tests[i].qstring_result), + token.type, parse_tests[i].qstring_type); + } + + assert_int_equal(result, parse_tests[i].qstring_result); + if (result == ISC_R_SUCCESS) { + switch (token.type) { + case isc_tokentype_string: + case isc_tokentype_qstring: + case isc_tokentype_vpair: + case isc_tokentype_qvpair: + if (debug) { + fprintf(stdout, "# value='%s'\n", + AS_STR(token)); + } + assert_int_equal(token.type, + parse_tests[i].qstring_type); + assert_string_equal( + AS_STR(token), + parse_tests[i].qstring_value); + break; + default: + assert_int_equal(token.type, + parse_tests[i].qstring_type); + break; + } + } + + isc_lex_destroy(&lex); + } +} + /*% * keypair is =. This has implications double quotes * in key names. @@ -133,52 +346,15 @@ lex_keypair(void **state) { isc_token_t token; size_t i; - struct { - const char *text; - const char *value; - isc_result_t result; - isc_tokentype_t type; - } tests[] = { - { "", "", ISC_R_SUCCESS, isc_tokentype_eof }, - { "1234", "1234", ISC_R_SUCCESS, isc_tokentype_string }, - { "1234=", "1234=", ISC_R_SUCCESS, isc_tokentype_vpair }, - { "1234=foo", "1234=foo", ISC_R_SUCCESS, isc_tokentype_vpair }, - { "1234=\"foo", NULL, ISC_R_UNEXPECTEDEND, 0 }, - { "1234=\"foo\"", "1234=foo", ISC_R_SUCCESS, - isc_tokentype_qvpair }, - { "key", "key", ISC_R_SUCCESS, isc_tokentype_string }, - { "\"key=", "\"key=", ISC_R_SUCCESS, isc_tokentype_vpair }, - { "\"key=\"", NULL, ISC_R_UNEXPECTEDEND, 0 }, - { "key=\"\"", "key=", ISC_R_SUCCESS, isc_tokentype_qvpair }, - { "key=\"a b\"", "key=a b", ISC_R_SUCCESS, - isc_tokentype_qvpair }, - { "key=\"a\tb\"", "key=a\tb", ISC_R_SUCCESS, - isc_tokentype_qvpair }, - /* double quote not immediately after '=' is not special. */ - { "key=c\"a b\"", "key=c\"a", ISC_R_SUCCESS, - isc_tokentype_vpair }, - /* remove special meaning for '=' by escaping */ - { "key\\=", "key\\=", ISC_R_SUCCESS, isc_tokentype_string }, - { "key\\=\"a\"", "key\\=\"a\"", ISC_R_SUCCESS, - isc_tokentype_string }, - { "key\\=\"a \"", "key\\=\"a", ISC_R_SUCCESS, - isc_tokentype_string }, - /* vpair with a key of 'key\=' (would need to be deescaped) */ - { "key\\==", "key\\==", ISC_R_SUCCESS, isc_tokentype_vpair }, - /* qvpair with a key of 'key\=' (would need to be deescaped) */ - { "key\\==\"\"", "key\\==", ISC_R_SUCCESS, - isc_tokentype_qvpair }, - }; - UNUSED(state); - for (i = 0; i < ARRAY_SIZE(tests); i++) { + for (i = 0; i < ARRAY_SIZE(parse_tests); i++) { result = isc_lex_create(test_mctx, 1024, &lex); assert_int_equal(result, ISC_R_SUCCESS); - isc_buffer_constinit(&buf, tests[i].text, - strlen(tests[i].text)); - isc_buffer_add(&buf, strlen(tests[i].text)); + isc_buffer_constinit(&buf, parse_tests[i].text, + strlen(parse_tests[i].text)); + isc_buffer_add(&buf, strlen(parse_tests[i].text)); result = isc_lex_openbuffer(lex, &buf); assert_int_equal(result, ISC_R_SUCCESS); @@ -191,12 +367,12 @@ lex_keypair(void **state) { isc_tokentype_qvpair, true); if (debug) { fprintf(stdout, "# '%s' -> result=%s/%s, type=%u/%u\n", - tests[i].text, isc_result_toid(result), - isc_result_toid(tests[i].result), token.type, - tests[i].type); + parse_tests[i].text, isc_result_toid(result), + isc_result_toid(parse_tests[i].qvpair_result), + token.type, parse_tests[i].qvpair_type); } - assert_int_equal(result, tests[i].result); + assert_int_equal(result, parse_tests[i].qvpair_result); if (result == ISC_R_SUCCESS) { switch (token.type) { case isc_tokentype_string: @@ -204,16 +380,18 @@ lex_keypair(void **state) { case isc_tokentype_vpair: case isc_tokentype_qvpair: if (debug) { -#define AS_STR(x) (x).value.as_textregion.base fprintf(stdout, "# value='%s'\n", AS_STR(token)); } - assert_int_equal(token.type, tests[i].type); - assert_string_equal(AS_STR(token), - tests[i].value); + assert_int_equal(token.type, + parse_tests[i].qvpair_type); + assert_string_equal( + AS_STR(token), + parse_tests[i].qvpair_value); break; default: - assert_int_equal(token.type, tests[i].type); + assert_int_equal(token.type, + parse_tests[i].qvpair_type); break; } } @@ -225,9 +403,9 @@ lex_keypair(void **state) { int main(int argc, char *argv[]) { const struct CMUnitTest tests[] = { - cmocka_unit_test(lex_0xff), - cmocka_unit_test(lex_keypair), - cmocka_unit_test(lex_setline), + cmocka_unit_test(lex_0xff), cmocka_unit_test(lex_keypair), + cmocka_unit_test(lex_setline), cmocka_unit_test(lex_string), + cmocka_unit_test(lex_qstring), }; UNUSED(argv);