From: Markus Valentin Date: Fri, 6 Nov 2020 10:47:18 +0000 (+0100) Subject: lib-mail: Add tests for message-size functions X-Git-Tag: 2.3.14.rc1~293 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=362ebb22c1d92e58e4edd892b07466355937299a;p=thirdparty%2Fdovecot%2Fcore.git lib-mail: Add tests for message-size functions Integrate testing of header and body size to existing tests and add new tests specifically for message-size. --- diff --git a/src/lib-mail/Makefile.am b/src/lib-mail/Makefile.am index 9127cccff8..f260694f18 100644 --- a/src/lib-mail/Makefile.am +++ b/src/lib-mail/Makefile.am @@ -106,6 +106,7 @@ test_programs = \ test-message-part \ test-message-part-serialize \ test-message-search \ + test-message-size \ test-message-snippet \ test-ostream-dot \ test-qp-decoder \ @@ -196,6 +197,10 @@ test_message_search_SOURCES = test-message-search.c test_message_search_LDADD = $(test_libs) ../lib-charset/libcharset.la test_message_search_DEPENDENCIES = $(test_deps) ../lib-charset/libcharset.la +test_message_size_SOURCES = test-message-size.c +test_message_size_LDADD = $(test_libs) +test_message_size_DEPENDENCIES = $(test_deps) + test_message_snippet_SOURCES = test-message-snippet.c test_message_snippet_LDADD = $(test_message_decoder_LDADD) test_message_snippet_DEPENDENCIES = $(test_deps) diff --git a/src/lib-mail/test-message-header-parser.c b/src/lib-mail/test-message-header-parser.c index 7362f6c630..a9fea89a5c 100644 --- a/src/lib-mail/test-message-header-parser.c +++ b/src/lib-mail/test-message-header-parser.c @@ -132,8 +132,9 @@ static void test_message_header_parser(void) MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE; enum message_header_parser_flags hdr_flags; struct message_header_parser_ctx *parser; - struct message_size hdr_size; + struct message_size hdr_size, hdr_size2; struct istream *input; + bool has_nuls; test_begin("message header parser"); input = test_istream_create(test1_msg); @@ -143,7 +144,14 @@ static void test_message_header_parser(void) parser = message_parse_header_init(input, &hdr_size, hdr_flags); test_message_header_parser_one(parser, hdr_flags); message_parse_header_deinit(&parser); + i_stream_seek(input, 0); + message_get_header_size(input, &hdr_size2, &has_nuls); } + + test_assert(!has_nuls); + test_assert(hdr_size.physical_size == hdr_size2.physical_size); + test_assert(hdr_size.virtual_size == hdr_size2.virtual_size); + test_assert(hdr_size.lines == hdr_size2.lines); test_assert(hdr_size.physical_size == strlen(test1_msg)-TEST1_MSG_BODY_LEN); test_assert(hdr_size.virtual_size == strlen(test1_msg) - TEST1_MSG_BODY_LEN + 4); @@ -199,13 +207,15 @@ static void test_message_header_parser_partial(void) static void test_message_header_parser_long_lines_str(const char *str, unsigned int buffer_size, - struct message_size *size_r) + struct message_size *size_r, + struct message_size *size_2_r) { struct message_header_parser_ctx *parser; struct message_header_line *hdr; struct istream *input; unsigned int i; size_t len = strlen(str); + bool has_nuls; input = test_istream_create(str); test_istream_set_max_buffer_size(input, buffer_size); @@ -216,6 +226,12 @@ test_message_header_parser_long_lines_str(const char *str, while (message_parse_header_next(parser, &hdr) > 0) ; } message_parse_header_deinit(&parser); + i_stream_seek(input, 0); + /* Buffer must be +1 for message_get_header_size as it's using + i_stream_read_bytes which does not work with lower buffersize + because it returns -2 (input buffer full) if 2 bytes are wanted. */ + test_istream_set_max_buffer_size(input, buffer_size+1); + message_get_header_size(input, size_2_r, &has_nuls); i_stream_unref(&input); } @@ -223,21 +239,25 @@ static void test_message_header_parser_long_lines(void) { static const char *lf_str = "1234567890: 345\n\n"; static const char *crlf_str = "1234567890: 345\r\n\r\n"; - struct message_size hdr_size; + struct message_size hdr_size, hdr_size2; size_t i, len; test_begin("message header parser long lines"); len = strlen(lf_str); for (i = 2; i < len; i++) { - test_message_header_parser_long_lines_str(lf_str, i, &hdr_size); + test_message_header_parser_long_lines_str(lf_str, i, &hdr_size, &hdr_size2); test_assert(hdr_size.physical_size == len); test_assert(hdr_size.virtual_size == len + 2); + test_assert(hdr_size.virtual_size == hdr_size2.virtual_size); + test_assert(hdr_size.physical_size == hdr_size2.physical_size); } len = strlen(crlf_str); for (i = 3; i < len; i++) { - test_message_header_parser_long_lines_str(crlf_str, i, &hdr_size); + test_message_header_parser_long_lines_str(crlf_str, i, &hdr_size, &hdr_size2); test_assert(hdr_size.physical_size == len); test_assert(hdr_size.virtual_size == len); + test_assert(hdr_size.virtual_size == hdr_size2.virtual_size); + test_assert(hdr_size.physical_size == hdr_size2.physical_size); } test_end(); } diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c index b99fc74dd1..8c5a3404f1 100644 --- a/src/lib-mail/test-message-parser.c +++ b/src/lib-mail/test-message-parser.c @@ -5,6 +5,7 @@ #include "istream.h" #include "message-parser.h" #include "message-part-data.h" +#include "message-size.h" #include "test-common.h" static const char test_msg[] = @@ -202,6 +203,33 @@ static void test_message_parser_stop_early(void) test_end(); } +static void test_message_parser_get_sizes(struct istream *input, + struct message_size *body_size_r, + struct message_size *header_size_r, + bool expect_has_nuls) +{ + bool has_nuls; + i_zero(body_size_r); + i_zero(header_size_r); + + message_get_header_size(input, header_size_r, &has_nuls); + test_assert(has_nuls == expect_has_nuls); + message_get_body_size(input, body_size_r, &has_nuls); + test_assert(has_nuls == expect_has_nuls); +} + +static void test_message_parser_assert_sizes(const struct message_part *part, + const struct message_size *body_size, + const struct message_size *header_size) +{ + test_assert(part->header_size.lines == header_size->lines); + test_assert(part->header_size.physical_size == header_size->physical_size); + test_assert(part->header_size.virtual_size == header_size->virtual_size); + test_assert(part->body_size.lines == body_size->lines); + test_assert(part->body_size.physical_size == body_size->physical_size); + test_assert(part->body_size.virtual_size == body_size->virtual_size); +} + static void test_message_parser_truncated_mime_headers(void) { static const char input_msg[] = @@ -217,6 +245,7 @@ static const char input_msg[] = "--:foo--\n"; struct istream *input; struct message_part *parts, *part; + struct message_size body_size, header_size; pool_t pool; test_begin("message parser truncated mime headers"); @@ -225,6 +254,9 @@ static const char input_msg[] = test_assert(message_parse_stream(pool, input, &set_empty, FALSE, &parts) < 0); + i_stream_seek(input, 0); + test_message_parser_get_sizes(input, &body_size, &header_size, FALSE); + test_assert((parts->flags & MESSAGE_PART_FLAG_MULTIPART) != 0); test_assert(parts->children_count == 4); test_assert(parts->header_size.lines == 2); @@ -233,6 +265,8 @@ static const char input_msg[] = test_assert(parts->body_size.lines == 8); test_assert(parts->body_size.physical_size == 112); test_assert(parts->body_size.virtual_size == 112+7); + test_message_parser_assert_sizes(parts, &body_size, &header_size); + test_assert(parts->children->physical_pos == 55); test_assert(parts->children->header_size.physical_size == 0); test_assert(parts->children->body_size.physical_size == 0); @@ -276,6 +310,7 @@ static const char input_msg[] = "--a\n\n"; struct istream *input; struct message_part *parts; + struct message_size body_size, header_size; pool_t pool; test_begin("message parser truncated mime headers 2"); @@ -284,6 +319,9 @@ static const char input_msg[] = test_assert(message_parse_stream(pool, input, &set_empty, FALSE, &parts) < 0); + i_stream_seek(input, 0); + test_message_parser_get_sizes(input, &body_size, &header_size, FALSE); + test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); test_assert(parts->children_count == 2); test_assert(parts->header_size.lines == 2); @@ -292,6 +330,7 @@ static const char input_msg[] = test_assert(parts->body_size.lines == 8); test_assert(parts->body_size.physical_size == 86); test_assert(parts->body_size.virtual_size == 86+8); + test_message_parser_assert_sizes(parts, &body_size, &header_size); test_assert(parts->children->children_count == 0); test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); @@ -397,6 +436,7 @@ static const char input_msg[] = "body\n"; struct istream *input; struct message_part *parts; + struct message_size body_size, header_size; pool_t pool; test_begin("message parser duplicate mime boundary"); @@ -405,6 +445,9 @@ static const char input_msg[] = test_assert(message_parse_stream(pool, input, &set_empty, FALSE, &parts) < 0); + i_stream_seek(input, 0); + test_message_parser_get_sizes(input, &body_size, &header_size, FALSE); + test_assert(parts->children_count == 2); test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); test_assert(parts->header_size.lines == 2); @@ -413,6 +456,8 @@ static const char input_msg[] = test_assert(parts->body_size.lines == 7); test_assert(parts->body_size.physical_size == 84); test_assert(parts->body_size.virtual_size == 84+7); + test_message_parser_assert_sizes(parts, &body_size, &header_size); + test_assert(parts->children->children_count == 1); test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); test_assert(parts->children->physical_pos == 49); @@ -452,6 +497,7 @@ static const char input_msg[] = "body\n"; struct istream *input; struct message_part *parts; + struct message_size body_size, header_size; pool_t pool; test_begin("message parser garbage suffix mime boundary"); @@ -460,6 +506,9 @@ static const char input_msg[] = test_assert(message_parse_stream(pool, input, &set_empty, FALSE, &parts) < 0); + i_stream_seek(input, 0); + test_message_parser_get_sizes(input, &body_size, &header_size, FALSE); + test_assert(parts->children_count == 2); test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); test_assert(parts->header_size.lines == 2); @@ -468,6 +517,8 @@ static const char input_msg[] = test_assert(parts->body_size.lines == 7); test_assert(parts->body_size.physical_size == 86); test_assert(parts->body_size.virtual_size == 86+7); + test_message_parser_assert_sizes(parts, &body_size, &header_size); + test_assert(parts->children->children_count == 1); test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); test_assert(parts->children->physical_pos == 50); @@ -554,6 +605,8 @@ static const char input_msg[] = test_assert(message_parse_stream(pool, input, &set_empty, FALSE, &parts) < 0); + i_stream_seek(input, 0); + test_assert(parts->children_count == 2); test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); test_assert(parts->header_size.lines == 2); @@ -602,6 +655,7 @@ static const char input_msg[] = "--a--\n\n"; struct istream *input; struct message_part *parts, *part; + struct message_size body_size, header_size; pool_t pool; test_begin("message parser continuing truncated mime boundary"); @@ -610,6 +664,9 @@ static const char input_msg[] = test_assert(message_parse_stream(pool, input, &set_empty, FALSE, &parts) < 0); + i_stream_seek(input, 0); + test_message_parser_get_sizes(input, &body_size, &header_size, FALSE); + part = parts; test_assert(part->children_count == 3); test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); @@ -619,6 +676,7 @@ static const char input_msg[] = test_assert(part->body_size.lines == 9); test_assert(part->body_size.physical_size == 112); test_assert(part->body_size.virtual_size == 112+9); + test_message_parser_assert_sizes(part, &body_size, &header_size); part = parts->children; test_assert(part->children_count == 0); @@ -679,6 +737,7 @@ static const char input_msg[] = "body2\n"; struct istream *input; struct message_part *parts; + struct message_size body_size, header_size; pool_t pool; test_begin("message parser continuing mime boundary reverse"); @@ -687,6 +746,9 @@ static const char input_msg[] = test_assert(message_parse_stream(pool, input, &set_empty, FALSE, &parts) < 0); + i_stream_seek(input, 0); + test_message_parser_get_sizes(input, &body_size, &header_size, FALSE); + test_assert(parts->children_count == 3); test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); test_assert(parts->header_size.lines == 2); @@ -695,6 +757,8 @@ static const char input_msg[] = test_assert(parts->body_size.lines == 11); test_assert(parts->body_size.physical_size == 121); test_assert(parts->body_size.virtual_size == 121+11); + test_message_parser_assert_sizes(parts, &body_size, &header_size); + test_assert(parts->children->children_count == 1); test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); test_assert(parts->children->physical_pos == 51); @@ -790,6 +854,7 @@ static const char input_msg[] = "4444\n"; struct istream *input; struct message_part *parts, *part; + struct message_size body_size, header_size; pool_t pool; test_begin("message parser long mime boundary"); @@ -798,6 +863,9 @@ static const char input_msg[] = test_assert(message_parse_stream(pool, input, &set_empty, FALSE, &parts) < 0); + i_stream_seek(input, 0); + test_message_parser_get_sizes(input, &body_size, &header_size, FALSE); + part = parts; test_assert(part->children_count == 6); test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); @@ -807,6 +875,7 @@ static const char input_msg[] = test_assert(part->body_size.lines == 22); test_assert(part->body_size.physical_size == 871); test_assert(part->body_size.virtual_size == 871+22); + test_message_parser_assert_sizes(part, &body_size, &header_size); part = parts->children; test_assert(part->children_count == 5); @@ -871,6 +940,7 @@ static const char input_msg[] = }; struct istream *input; struct message_part *parts, *part; + struct message_size body_size, header_size; pool_t pool; test_begin("message parser mime part nested limit"); @@ -879,6 +949,9 @@ static const char input_msg[] = test_assert(message_parse_stream(pool, input, &parser_set, FALSE, &parts) < 0); + i_stream_seek(input, 0); + test_message_parser_get_sizes(input, &body_size, &header_size, FALSE); + part = parts; test_assert(part->children_count == 2); test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); @@ -888,6 +961,7 @@ static const char input_msg[] = test_assert(part->body_size.lines == 15); test_assert(part->body_size.physical_size == 148); test_assert(part->body_size.virtual_size == 148+15); + test_message_parser_assert_sizes(part, &body_size, &header_size); part = parts->children; test_assert(part->children_count == 0); @@ -930,6 +1004,7 @@ static const char input_msg[] = }; struct istream *input; struct message_part *parts, *part; + struct message_size body_size, header_size; pool_t pool; test_begin("message parser mime part nested limit rfc822"); @@ -938,6 +1013,9 @@ static const char input_msg[] = test_assert(message_parse_stream(pool, input, &parser_set, FALSE, &parts) < 0); + i_stream_seek(input, 0); + test_message_parser_get_sizes(input, &body_size, &header_size, FALSE); + part = parts; test_assert(part->children_count == 1); test_assert(part->flags == (MESSAGE_PART_FLAG_MESSAGE_RFC822 | MESSAGE_PART_FLAG_IS_MIME)); @@ -947,6 +1025,7 @@ static const char input_msg[] = test_assert(part->body_size.lines == 5); test_assert(part->body_size.physical_size == 58); test_assert(part->body_size.virtual_size == 58+5); + test_message_parser_assert_sizes(part, &body_size, &header_size); part = parts->children; test_assert(part->children_count == 0); @@ -989,6 +1068,7 @@ static const char input_msg[] = }; struct istream *input; struct message_part *parts, *part; + struct message_size body_size, header_size; pool_t pool; test_begin("message parser mime part limit"); @@ -997,6 +1077,9 @@ static const char input_msg[] = test_assert(message_parse_stream(pool, input, &parser_set, FALSE, &parts) < 0); + i_stream_seek(input, 0); + test_message_parser_get_sizes(input, &body_size, &header_size, FALSE); + part = parts; test_assert(part->children_count == 3); test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); @@ -1006,6 +1089,7 @@ static const char input_msg[] = test_assert(part->body_size.lines == 15); test_assert(part->body_size.physical_size == 148); test_assert(part->body_size.virtual_size == 148+15); + test_message_parser_assert_sizes(part, &body_size, &header_size); part = parts->children; test_assert(part->children_count == 2); diff --git a/src/lib-mail/test-message-size.c b/src/lib-mail/test-message-size.c new file mode 100644 index 0000000000..4342c27a28 --- /dev/null +++ b/src/lib-mail/test-message-size.c @@ -0,0 +1,159 @@ +/* Copyright (c) 2020 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "istream.h" +#include "message-size.h" +#include "test-common.h" + +static const char test_msg[] = +"Return-Path: \n" +"Subject: Hello world\n" +"From: Test User \n" +"To: Another User \n" +"Message-Id: <1.2.3.4@example>\n" +"Mime-Version: 1.0\n" +"Date: Sun, 23 May 2007 04:58:08 +0300\n" +"Content-Type: multipart/signed; micalg=pgp-sha1;\n" +" protocol=\"application/pgp-signature\";\n" +" boundary=\"=-GNQXLhuj24Pl1aCkk4/d\"\n" +"\n" +"--=-GNQXLhuj24Pl1aCkk4/d\n" +"Content-Type: text/plain\n" +"Content-Transfer-Encoding: quoted-printable\n" +"\n" +"There was a day=20\n" +"a happy=20day\n" +"\n" +"--=-GNQXLhuj24Pl1aCkk4/d\n" +"Content-Type: application/pgp-signature; name=signature.asc\n" +"\n" +"-----BEGIN PGP SIGNATURE-----\n" +"Version: GnuPG v1.2.4 (GNU/Linux)\n" +"\n" +"invalid\n" +"-----END PGP SIGNATURE-----\n" +"\n" +"--=-GNQXLhuj24Pl1aCkk4/d--\n" +"\n" +"\n"; + +static const char test_msg_with_nuls[] = +"Return-Path: \n" +"Subject: Hello world\n" +"From: Test User \n" +"To: Another User \n" +"Message-Id: <1.2.3.4@example>\n" +"Mime-Version: 1.0\0\n" +"Date: Sun, 23 May 2007 04:58:08 +0300\n" +"Content-Type: multipart/signed; micalg=pgp-sha1;\n" +" protocol=\"application/pgp-signature\";\n" +" boundary=\"=-GNQXLhuj24Pl1aCkk4/d\"\n" +"\n" +"--=-GNQXLhuj24Pl1aCkk4/d\n" +"\n" +"Content-Type: text/plain\n" +"Content-Transfer-Encoding: quoted-printable\n" +"\n" +"There was\0 a day=20\n" +"a happy=20day\n" +"\n" +"--=-GNQXLhuj24Pl1aCkk4/d\n" +"Content-Type: application/pgp-signature; name=signature.asc\n" +"\n" +"-----BEGIN PGP SIGNATURE-----\n" +"Version: GnuPG v1.2.4 (GNU/Linux)\n" +"\n" +"inva\0lid\n" +"-----END PGP SIGNATURE-----\n" +"\n" +"--=-GNQXLhuj24Pl1aCkk4/d--\n" +"\n" +"\n"; + +struct test_case { + const char *test_name; + const char *message; + bool has_nuls; + unsigned int body_newlines; + unsigned int header_newlines; + unsigned int message_len; + unsigned int header_len; +}; +static const struct test_case test_cases[] = { + { + .test_name = "message size", + .message = test_msg, + .has_nuls = FALSE, + .body_newlines = 19, + .header_newlines = 11, + .message_len = sizeof(test_msg)-1, + .header_len = 335, + }, + { + .test_name = "message size with nuls", + .message = test_msg_with_nuls, + .has_nuls = TRUE, + .body_newlines = 20, + .header_newlines = 11, + .message_len = sizeof(test_msg_with_nuls)-1, + .header_len = 336, + }, +}; + +static void test_message_size(void) +{ + struct istream *input; + struct message_size body_size, header_size; + bool has_nuls; + bool last_cr; + unsigned int i; + + for (i = 0; i < N_ELEMENTS(test_cases); i++) { + test_begin(test_cases[i].test_name); + input = i_stream_create_from_data(test_cases[i].message, + test_cases[i].message_len); + + /* Read physical_size */ + message_get_header_size(input, &header_size, &has_nuls); + test_assert_idx(has_nuls == test_cases[i].has_nuls, i); + test_assert_idx(input->v_offset == test_cases[i].header_len, i); + message_get_body_size(input, &body_size, &has_nuls); + test_assert_idx(has_nuls == test_cases[i].has_nuls, i); + test_assert_idx(input->v_offset - body_size.physical_size == + test_cases[i].header_len, i); + test_assert_idx(body_size.physical_size + header_size.physical_size == + test_cases[i].message_len, i); + + /* Test last_cr handling */ + i_stream_seek(input, 0); + message_skip_virtual(input, 0, &last_cr); + test_assert_idx(!last_cr, i); + message_skip_virtual(input, header_size.virtual_size-1, &last_cr); + test_assert_idx(last_cr, i); + message_skip_virtual(input, 2, &last_cr); + test_assert_idx(!last_cr, i); + + /* Skipped header size so read body again */ + message_get_body_size(input, &body_size, &has_nuls); + test_assert_idx(has_nuls == test_cases[i].has_nuls, i); + test_assert_idx(input->v_offset - body_size.physical_size == + test_cases[i].header_len, i); + test_assert_idx(body_size.physical_size + test_cases[i].body_newlines == + body_size.virtual_size, i); + test_assert_idx(body_size.virtual_size + header_size.virtual_size - + test_cases[i].body_newlines - test_cases[i].header_newlines == + test_cases[i].message_len, i); + + i_stream_unref(&input); + test_end(); + } +} + +int main(void) +{ + static void (*const test_functions[])(void) = { + test_message_size, + NULL + }; + return test_run(test_functions); +}