From: Aki Tuomi Date: Tue, 17 Nov 2020 07:29:30 +0000 (+0200) Subject: lib-mail: test-rfc822-parser - Add tests for content-type full parsing X-Git-Tag: 2.3.14.rc1~299 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0f3bbb5bf4b26393e02b221dd94ff8f4555db68f;p=thirdparty%2Fdovecot%2Fcore.git lib-mail: test-rfc822-parser - Add tests for content-type full parsing --- diff --git a/src/lib-mail/test-rfc822-parser.c b/src/lib-mail/test-rfc822-parser.c index e5cf405f69..a0e7ad04b8 100644 --- a/src/lib-mail/test-rfc822-parser.c +++ b/src/lib-mail/test-rfc822-parser.c @@ -1,6 +1,7 @@ /* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "array.h" #include "str.h" #include "rfc822-parser.h" #include "test-common.h" @@ -321,6 +322,112 @@ static void test_rfc822_parse_content_param(void) test_end(); } +struct param { + const char *key, *value; +}; + +static void parse_content_type_param(const void *input, size_t input_len, + const char *content_type, + const struct param *params, size_t param_count, + bool expect_content_type, int expect_ret, + int idx) +{ + struct rfc822_parser_context parser; + const char *key; + string_t *value = t_str_new(64); + unsigned int i = 0; + int ret; + + i_assert(params != NULL || param_count == 0); + + rfc822_parser_init(&parser, input, input_len, NULL); + ret = rfc822_parse_content_type(&parser, value); + test_assert_idx((expect_content_type && ret == 1) || + (!expect_content_type && ret == -1), idx); + test_assert_strcmp_idx(content_type, str_c(value), idx); + + /* parse content type first */ + while ((ret = rfc822_parse_content_param(&parser, &key, value)) > 0) { + if (i < param_count) { + test_assert_strcmp_idx(params[i].key, key, idx); + test_assert_strcmp_idx(params[i].value, str_c(value), idx); + } + i++; + } + + test_assert_idx(expect_ret == ret, idx); + test_assert_idx(i == param_count, idx); + rfc822_parser_deinit(&parser); +} + +#undef TEST_STRING +#define TEST_STRING(a) (a), sizeof((a))-1 + +#define X10(a) a a a a a a a a a a + +static void test_rfc822_parse_content_type_param(void) +{ + const char *input = + "(hello) text/plain ; (should we skip;comments=\"yes\")" + " param=value" + " ; param2=value2 (with comments (with comment) with;comment=\"yes\") " + " ; param3=\"value3 (with no comment ; or=value)\"" + " ; param4=\"\xe7\xa8\xae\xe9\xa1\x9e\"" + " ; \xe5\x90\xab\xe9\x87\x8f=\"\xe7\xa8\xae\xe9\xa1\x9e\"" + " ; "X10(X10(X10("a")))"="X10(X10(X10("a"))) + " ; "X10(X10(X10(X10("a"))))"="X10(X10(X10(X10("a")))) + " ; (comment) param7 (comment2) = (comment3) value7 (comment4) " + ; + + const struct param output[] = { + { "param", "value" }, + { "param2", "value2" }, + { "param3", "value3 (with no comment ; or=value)" }, + { "param4", "\xe7\xa8\xae\xe9\xa1\x9e" }, + { "\xe5\x90\xab\xe9\x87\x8f", "\xe7\xa8\xae\xe9\xa1\x9e" }, + { X10(X10(X10("a"))), X10(X10(X10("a"))) }, + { X10(X10(X10(X10("a")))), X10(X10(X10(X10("a")))) }, + { "param7", "value7" }, + }; + const struct param output5[] = { + { "charset", "" }, + }; + + test_begin("rfc822 parse content type with params"); + + int idx = 0; + parse_content_type_param(input, strlen(input), "text/plain", + output, N_ELEMENTS(output), TRUE, 0, idx++); + parse_content_type_param(TEST_STRING("text/"), "", NULL, 0, FALSE, 0, idx++); + parse_content_type_param( + TEST_STRING("text/\0plain ;"), "", NULL, 0, FALSE, -1, idx++); + parse_content_type_param( + TEST_STRING("text/plain\0;charset=us-ascii"), "", NULL, 0, FALSE, -1, idx++); + parse_content_type_param( + TEST_STRING("text/plain;charset\0=us-ascii"), "text/plain", NULL, 0, TRUE, -1, idx++); + parse_content_type_param( + TEST_STRING("text/plain;charset="), "text/plain", + output5, N_ELEMENTS(output5), TRUE, 0, idx++); + parse_content_type_param( + TEST_STRING("text/plain ; ; charset=us-ascii"), "text/plain", NULL, 0, TRUE, -1, idx++); + /* build a large one */ + ARRAY(struct param) output2; + t_array_init(&output2, 1000); + string_t *large = t_str_new(10000); + str_append(large, "text/plain"); + for (unsigned int i = 0; i < 1000; i++) { + str_printfa(large, " ; param%u=\"value%u\"", i, i); + struct param *param = array_append_space(&output2); + param->key = t_strdup_printf("param%u", i); + param->value = t_strdup_printf("value%u", i); + } + parse_content_type_param(large->data, large->used, + "text/plain", + array_idx(&output2, 0), array_count(&output2), + TRUE, 0, idx++); + test_end(); +} + int main(void) { static void (*const test_functions[])(void) = { @@ -331,6 +438,7 @@ int main(void) test_rfc822_parse_domain_literal, test_rfc822_parse_content_type, test_rfc822_parse_content_param, + test_rfc822_parse_content_type_param, NULL }; return test_run(test_functions);