diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
commit | 0441d265f2bb9da249c7abf333f0f771fadb4ab5 (patch) | |
tree | 3f3789daa2f6db22da6e55e92bee0062a7d613fe /src/lib-imap/test-imap-parser.c | |
parent | Initial commit. (diff) | |
download | dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.tar.xz dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.zip |
Adding upstream version 1:2.3.21+dfsg1.upstream/1%2.3.21+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib-imap/test-imap-parser.c')
-rw-r--r-- | src/lib-imap/test-imap-parser.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/src/lib-imap/test-imap-parser.c b/src/lib-imap/test-imap-parser.c new file mode 100644 index 0000000..3ca4e34 --- /dev/null +++ b/src/lib-imap/test-imap-parser.c @@ -0,0 +1,157 @@ +/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "istream.h" +#include "imap-parser.h" +#include "test-common.h" + +static void test_imap_parser_crlf(void) +{ + static const char *test_input = "foo\r\nx\ry\n"; + struct istream *input; + struct imap_parser *parser; + const struct imap_arg *args; + unsigned int i; + enum imap_parser_error parse_error; + + test_begin("imap parser crlf handling"); + input = test_istream_create(test_input); + parser = imap_parser_create(input, NULL, 1024); + + /* must return -2 until LF is read */ + for (i = 0; test_input[i] != '\n'; i++) { + test_istream_set_size(input, i+1); + (void)i_stream_read(input); + test_assert(imap_parser_read_args(parser, 0, 0, &args) == -2); + } + test_istream_set_size(input, i+1); + (void)i_stream_read(input); + test_assert(imap_parser_read_args(parser, 0, 0, &args) == 1); + test_assert(args[0].type == IMAP_ARG_ATOM); + test_assert(args[1].type == IMAP_ARG_EOL); + + /* CR without LF should fail with error */ + imap_parser_reset(parser); + i_stream_seek(input, ++i); + test_istream_set_size(input, ++i); + (void)i_stream_read(input); + test_assert(imap_parser_read_args(parser, 0, 0, &args) == -2); + test_istream_set_size(input, ++i); + (void)i_stream_read(input); + test_assert(imap_parser_read_args(parser, 0, 0, &args) == -2); + test_istream_set_size(input, ++i); + (void)i_stream_read(input); + test_assert(imap_parser_read_args(parser, 0, 0, &args) == -1); + test_assert(strcmp(imap_parser_get_error + (parser, &parse_error), "CR sent without LF") == 0 && + parse_error == IMAP_PARSE_ERROR_BAD_SYNTAX); + + imap_parser_unref(&parser); + i_stream_destroy(&input); + test_end(); +} + +static void test_imap_parser_partial_list(void) +{ + static const char *test_input = "((((foo {1000000}\r\n"; + struct istream *input; + struct imap_parser *parser; + const struct imap_arg *args, *sub_list; + + test_begin("imap parser partial list"); + input = test_istream_create(test_input); + parser = imap_parser_create(input, NULL, 1024); + + (void)i_stream_read(input); + test_assert(imap_parser_read_args(parser, 0, + IMAP_PARSE_FLAG_LITERAL_SIZE, &args) == 1); + for (unsigned int i = 0; i < 4; i++) { + sub_list = imap_arg_as_list(&args[0]); + test_assert(IMAP_ARG_IS_EOL(&args[1])); + args = sub_list; + } + test_assert(imap_arg_atom_equals(&args[0], "foo")); + test_assert(args[1].type == IMAP_ARG_LITERAL_SIZE); + test_assert(IMAP_ARG_IS_EOL(&args[2])); + + imap_parser_unref(&parser); + i_stream_destroy(&input); + test_end(); +} + +static void test_imap_parser_read_tag_cmd(void) +{ + enum read_type { + BOTH, + TAG, + COMMAND + }; + struct { + const char *input; + const char *tag; + int ret; + enum read_type type; + } tests[] = { + { "tag foo", "tag", 1, BOTH }, + { "tag\r", "tag", 1, BOTH }, + { "tag\rfoo", "tag", 1, BOTH }, + { "tag\nfoo", "tag", 1, BOTH }, + { "tag\r\nfoo", "tag", 1, BOTH }, + { "\n", NULL, -1, BOTH }, + { "tag", NULL, 0, BOTH }, + { "tag\t", NULL, -1, BOTH }, + { "tag\001", NULL, -1, BOTH }, + { "tag\x80", NULL, -1, BOTH }, + { "tag(", NULL, -1, BOTH }, + { "tag)", NULL, -1, BOTH }, + { "tag{", NULL, -1, BOTH }, + { "tag/ ", "tag/", 1, BOTH }, + { "tag%", NULL, -1, BOTH }, + { "tag*", NULL, -1, BOTH }, + { "tag\"", NULL, -1, BOTH }, + { "tag\\", NULL, -1, BOTH }, + { "tag+", NULL, -1, TAG }, + { "tag+ ", "tag+", 1, COMMAND }, + }; + struct istream *input; + struct imap_parser *parser; + const char *atom; + int ret; + + test_begin("imap_parser_read_tag and imap_parser_read_command_name"); + for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) { + if (tests[i].type != COMMAND) { + input = test_istream_create(tests[i].input); + test_assert(i_stream_read(input) > 0); + parser = imap_parser_create(input, NULL, 1024); + ret = imap_parser_read_tag(parser, &atom); + test_assert_idx(ret == tests[i].ret, i); + test_assert_idx(ret <= 0 || strcmp(tests[i].tag, atom) == 0, i); + imap_parser_unref(&parser); + i_stream_destroy(&input); + } + + if (tests[i].type != TAG) { + input = test_istream_create(tests[i].input); + test_assert(i_stream_read(input) > 0); + parser = imap_parser_create(input, NULL, 1024); + ret = imap_parser_read_command_name(parser, &atom); + test_assert_idx(ret == tests[i].ret, i); + test_assert_idx(ret <= 0 || strcmp(tests[i].tag, atom) == 0, i); + imap_parser_unref(&parser); + i_stream_destroy(&input); + } + } + test_end(); +} + +int main(void) +{ + static void (*const test_functions[])(void) = { + test_imap_parser_crlf, + test_imap_parser_partial_list, + test_imap_parser_read_tag_cmd, + NULL + }; + return test_run(test_functions); +} |