/* * Copyright (C) 2021 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ /** * @{ * * @file * @author Martine Lenders */ #include #include "embUnit.h" #include "kernel_defines.h" #include "ut_process.h" #include "tests-ut_process.h" static char _res_buf[128U]; static const ut_process_var_t _test_vec[] = { /* Taken from https://datatracker.ietf.org/doc/html/rfc6570#section-3.2 * minus the level 4 variables */ { .name = "dub", .value = "me/too", }, { .name = "hello", .value = "Hello World!", }, { .name = "half", .value = "50%", }, { .name = "var", .value = "value", }, { .name = "who", .value = "fred", }, { .name = "base", .value = "http://example.com/home/", }, { .name = "path", .value = "/foo/bar", }, { .name = "v", .value = "6", }, { .name = "x", .value = "1024", }, { .name = "y", .value = "768", }, { .name = "empty", .value = "", }, { .name = "undef", .value = NULL }, }; static void _setup(void) { memset(_res_buf, 0, sizeof(_res_buf)); } static void test_expand_str__overview_example(void) { /* Tests example from * https://datatracker.ietf.org/doc/html/rfc6570#section-1.1 */ static const char *ut = "http://www.example.com/foo{?query,number}"; static const ut_process_var_t vars[] = { { .name = "number", .value = "100", }, { .name = "query", .value = "mycelium", }, }; size_t res_buf_len = sizeof(_res_buf); TEST_ASSERT_EQUAL_INT( sizeof("http://www.example.com/foo?query=mycelium&number=100") - 1, ut_process_str_expand(ut, vars, ARRAY_SIZE(vars), _res_buf, &res_buf_len) ); TEST_ASSERT_EQUAL_STRING( "http://www.example.com/foo?query=mycelium&number=100", _res_buf ); TEST_ASSERT_EQUAL_INT( sizeof("http://www.example.com/foo?query=mycelium&number=100") - 1, res_buf_len ); TEST_ASSERT_EQUAL_INT( sizeof("http://www.example.com/foo?number=100") - 1, ut_process_str_expand(ut, vars, 1U, _res_buf, &res_buf_len) ); TEST_ASSERT_EQUAL_STRING( "http://www.example.com/foo?number=100", _res_buf ); TEST_ASSERT_EQUAL_INT( sizeof("http://www.example.com/foo?number=100") - 1, res_buf_len ); TEST_ASSERT_EQUAL_INT( sizeof("http://www.example.com/foo") - 1, ut_process_str_expand(ut, NULL, 0U, _res_buf, &res_buf_len) ); TEST_ASSERT_EQUAL_STRING( "http://www.example.com/foo", _res_buf ); TEST_ASSERT_EQUAL_INT( sizeof("http://www.example.com/foo") - 1, res_buf_len ); } #define ASSERT_EXPANSION(template, expansion) \ res_buf_len = sizeof(_res_buf); \ TEST_ASSERT_EQUAL_INT(sizeof(expansion) - 1, ut_process_str_expand( \ template, _test_vec, ARRAY_SIZE(_test_vec), _res_buf, &res_buf_len \ )); \ TEST_ASSERT_EQUAL_STRING(expansion, _res_buf) static void test_expand_str__simple(void) { size_t res_buf_len; /* see https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.2 * except level 4 expansions */ ASSERT_EXPANSION("{var}", "value"); ASSERT_EXPANSION("{hello}", "Hello%20World%21"); ASSERT_EXPANSION("{half}", "50%25"); ASSERT_EXPANSION("O{empty}X", "OX"); ASSERT_EXPANSION("O{undef}X", "OX"); ASSERT_EXPANSION("{x,y}", "1024,768"); ASSERT_EXPANSION("{x,hello,y}", "1024,Hello%20World%21,768"); ASSERT_EXPANSION("?{x,empty}", "?1024,"); ASSERT_EXPANSION("?{x,undef}", "?1024"); ASSERT_EXPANSION("?{undef,y}", "?768"); } static void test_expand_str__reserved(void) { size_t res_buf_len; /* see https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.3 * except level 4 expansions */ ASSERT_EXPANSION("{+var}", "value"); ASSERT_EXPANSION("{+hello}", "Hello%20World!"); ASSERT_EXPANSION("{+half}", "50%25"); ASSERT_EXPANSION("{base}index", "http%3A%2F%2Fexample.com%2Fhome%2Findex"); ASSERT_EXPANSION("{+base}index", "http://example.com/home/index"); ASSERT_EXPANSION("O{+empty}X", "OX"); ASSERT_EXPANSION("O{+undef}X", "OX"); ASSERT_EXPANSION("{+path}/here", "/foo/bar/here"); ASSERT_EXPANSION("here?ref={+path}", "here?ref=/foo/bar"); ASSERT_EXPANSION("up{+path}{var}/here", "up/foo/barvalue/here"); ASSERT_EXPANSION("{+x,hello,y}", "1024,Hello%20World!,768"); ASSERT_EXPANSION("{+path,x}/here", "/foo/bar,1024/here"); } static void test_expand_str__fragment(void) { size_t res_buf_len; /* see https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.4 * except level 4 expansions */ ASSERT_EXPANSION("{#var}", "#value"); ASSERT_EXPANSION("{#hello}", "#Hello%20World!"); ASSERT_EXPANSION("{#half}", "#50%25"); ASSERT_EXPANSION("foo{#empty}", "foo#"); ASSERT_EXPANSION("foo{#undef}", "foo"); ASSERT_EXPANSION("{#x,hello,y}", "#1024,Hello%20World!,768"); ASSERT_EXPANSION("{#path,x}/here", "#/foo/bar,1024/here"); } static void test_expand_str__label(void) { size_t res_buf_len; /* see https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.5 * except level 4 expansions */ ASSERT_EXPANSION("{.who}", ".fred"); ASSERT_EXPANSION("{.who,who}", ".fred.fred"); ASSERT_EXPANSION("{.half,who}", ".50%25.fred"); ASSERT_EXPANSION("X{.var}", "X.value"); ASSERT_EXPANSION("X{.empty}", "X."); ASSERT_EXPANSION("X{.undef}", "X"); /* unreserved set is not really tested with provided set, so add a test for * that */ ASSERT_EXPANSION("{.hello}", ".Hello%20World%21"); } static void test_expand_str__path(void) { size_t res_buf_len; /* see https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.6 * except level 4 expansions */ ASSERT_EXPANSION("{/who}", "/fred"); ASSERT_EXPANSION("{/who,who}", "/fred/fred"); ASSERT_EXPANSION("{/half,who}", "/50%25/fred"); ASSERT_EXPANSION("{/who,dub}", "/fred/me%2Ftoo"); ASSERT_EXPANSION("{/var}", "/value"); ASSERT_EXPANSION("{/var,empty}", "/value/"); ASSERT_EXPANSION("{/var,undef}", "/value"); ASSERT_EXPANSION("{/var,x}/here", "/value/1024/here"); /* unreserved set is not really tested with provided set, so add a test for * that */ ASSERT_EXPANSION("{/hello}", "/Hello%20World%21"); } static void test_expand_str__path_param(void) { size_t res_buf_len; /* see https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.7 * except level 4 expansions */ ASSERT_EXPANSION("{;who}", ";who=fred"); ASSERT_EXPANSION("{;half}", ";half=50%25"); ASSERT_EXPANSION("{;empty}", ";empty"); ASSERT_EXPANSION("{;v,empty,who}", ";v=6;empty;who=fred"); ASSERT_EXPANSION("{;v,bar,who}", ";v=6;who=fred"); ASSERT_EXPANSION("{;x,y}", ";x=1024;y=768"); ASSERT_EXPANSION("{;x,y,empty}", ";x=1024;y=768;empty"); ASSERT_EXPANSION("{;x,y,undef}", ";x=1024;y=768"); /* unreserved set is not really tested with provided set, so add a test for * that */ ASSERT_EXPANSION("{;hello}", ";hello=Hello%20World%21"); } static void test_expand_str__query(void) { size_t res_buf_len; /* see https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.8 * except level 4 expansions */ ASSERT_EXPANSION("{?who}", "?who=fred"); ASSERT_EXPANSION("{?half}", "?half=50%25"); ASSERT_EXPANSION("{?x,y}", "?x=1024&y=768"); ASSERT_EXPANSION("{?x,y,empty}", "?x=1024&y=768&empty="); ASSERT_EXPANSION("{?x,y,undef}", "?x=1024&y=768"); /* unreserved set is not really tested with provided set, so add a test for * that */ ASSERT_EXPANSION("{?hello}", "?hello=Hello%20World%21"); } static void test_expand_str__query_cont(void) { size_t res_buf_len; /* see https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.8 * except level 4 expansions */ ASSERT_EXPANSION("{&who}", "&who=fred"); ASSERT_EXPANSION("{&half}", "&half=50%25"); ASSERT_EXPANSION("?fixed=yes{&x}", "?fixed=yes&x=1024"); ASSERT_EXPANSION("{&x,y,empty}", "&x=1024&y=768&empty="); ASSERT_EXPANSION("{&x,y,undef}", "&x=1024&y=768"); /* unreserved set is not really tested with provided set, so add a test for * that */ ASSERT_EXPANSION("{&hello}", "&hello=Hello%20World%21"); } static void test_expand_str__dup_open(void) { size_t res_buf_len; ASSERT_EXPANSION("{half{who}", "{halffred"); ASSERT_EXPANSION("{{half{who}", "{{halffred"); ASSERT_EXPANSION("half{who}{{", "halffred{{"); } static void test_expand_str__dup_close(void) { size_t res_buf_len; ASSERT_EXPANSION("{half{who}}", "{halffred}"); ASSERT_EXPANSION("half{who}}}", "halffred}}"); } #define ASSERT_ENOBUFS_EXPANSION(template, res_len) \ res_buf_len = (res_len); \ TEST_ASSERT_EQUAL_INT(-ENOBUFS, ut_process_str_expand( \ template, _test_vec, ARRAY_SIZE(_test_vec), _res_buf, &res_buf_len \ )) static void test_expand_str__enobufs(void) { size_t res_buf_len; ASSERT_ENOBUFS_EXPANSION("{half{who}}", sizeof("{half") - 1); ASSERT_ENOBUFS_EXPANSION("foo{#empty}", sizeof("fo") - 1); ASSERT_ENOBUFS_EXPANSION("{thisisonlyatest", sizeof("{thisi") - 1); ASSERT_ENOBUFS_EXPANSION("foo", sizeof("foo") - 1); ASSERT_ENOBUFS_EXPANSION("{?x,y,empty}", sizeof("?x=1024&") - 1); ASSERT_ENOBUFS_EXPANSION("{?half}", sizeof("?hal") - 1); ASSERT_ENOBUFS_EXPANSION("{?half}", sizeof("?half") - 1); ASSERT_ENOBUFS_EXPANSION("{?half}", sizeof("?half=50") - 1); ASSERT_ENOBUFS_EXPANSION("foo{#empty}", sizeof("foo") - 1); } #define ASSERT_EINVAL_EXPANSION(template) \ res_buf_len = sizeof(_res_buf); \ TEST_ASSERT_EQUAL_INT(-EINVAL, ut_process_str_expand( \ template, _test_vec, ARRAY_SIZE(_test_vec), _res_buf, &res_buf_len \ )) static void test_expand_str__einval(void) { size_t res_buf_len; ASSERT_EINVAL_EXPANSION("{?x,,empty}"); ASSERT_EINVAL_EXPANSION("{=x,y,empty}"); ASSERT_EINVAL_EXPANSION("{?x,$,empty}"); } static Test *_ut_process_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { new_TestFixture(test_expand_str__overview_example), new_TestFixture(test_expand_str__simple), new_TestFixture(test_expand_str__reserved), new_TestFixture(test_expand_str__fragment), new_TestFixture(test_expand_str__label), new_TestFixture(test_expand_str__path), new_TestFixture(test_expand_str__path_param), new_TestFixture(test_expand_str__query), new_TestFixture(test_expand_str__query_cont), new_TestFixture(test_expand_str__dup_open), new_TestFixture(test_expand_str__dup_close), new_TestFixture(test_expand_str__enobufs), new_TestFixture(test_expand_str__einval), }; EMB_UNIT_TESTCALLER(ut_process_tests, _setup, NULL, fixtures); return (Test *)&ut_process_tests; } void tests_ut_process(void) { TESTS_RUN(_ut_process_tests()); } /** @} */