diff options
Diffstat (limited to 'src/lib/test-istream-jsonstr.c')
-rw-r--r-- | src/lib/test-istream-jsonstr.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/lib/test-istream-jsonstr.c b/src/lib/test-istream-jsonstr.c new file mode 100644 index 0000000..626994d --- /dev/null +++ b/src/lib/test-istream-jsonstr.c @@ -0,0 +1,139 @@ +/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "str.h" +#include "istream-private.h" +#include "istream-jsonstr.h" + +static const struct { + const char *input; + const char *output; + int stream_errno; +} tests[] = { + { "foo\\\\\\\"\\b\\f\\n\\r\\t\\u0001\\uffff\"", + "foo\\\"\b\f\n\r\t\001\xEF\xBF\xBF", 0 }, + { "\\ud801\\udc37\"", "\xf0\x90\x90\xb7", 0 }, /* valid codepoint */ + { "\"", "", 0 }, + { "foo\\?\"", "foo", EINVAL }, + { "foo\\?\"", "foo", EINVAL }, + { "", "", EPIPE }, + { "\\\"", "\"", EPIPE }, + { "foo", "foo", EPIPE }, + { "\\ud801", "", EPIPE }, /* high surrogate alone */ + { "\\udced\\udc37\"", "", EINVAL }, /* low surrogate before high */ + { "\\ud8011\\udc37\"", "", EINVAL }, /* has extra 1 in middle */ + { "hello \\udc37\"", "hello ", EINVAL }, /* low surrogate before high with valid prefix*/ + { "hello \\ud801", "hello ", EPIPE }, /* high surrogate alone with valid prefix */ + { "\\uabcg", "", EINVAL }, /* invalid hex value */ +}; + +static void +run_test_buffer(const char *json_input, const char *output, int stream_errno, + unsigned int skip_count) +{ + size_t json_input_len = strlen(json_input); + struct istream *input_data, *input; + const unsigned char *data; + size_t i, size; + ssize_t ret = 0; + + input_data = test_istream_create_data(json_input, json_input_len); + test_istream_set_allow_eof(input_data, FALSE); + input = i_stream_create_jsonstr(input_data); + + for (i = 1; i < json_input_len;) { + test_istream_set_size(input_data, i); + while ((ret = i_stream_read(input)) > 0) ; + if (ret == -1 && stream_errno != 0) + break; + test_assert_idx(ret == 0, i); + if (i + skip_count < json_input_len) + i += skip_count; + else + i++; + } + test_istream_set_allow_eof(input_data, TRUE); + test_istream_set_size(input_data, json_input_len); + ret = i_stream_read(input); + while (ret > 0 && stream_errno != 0) + ret = i_stream_read(input); + test_assert(ret == -1); + test_assert(input->stream_errno == stream_errno); + + if (stream_errno == 0) { + data = i_stream_get_data(input, &size); + test_assert(size == strlen(output)); + if (size > 0) + test_assert(memcmp(data, output, size) == 0); + } + i_stream_unref(&input); + i_stream_unref(&input_data); +} + +static void +run_test(const char *json_input, const char *output, int stream_errno) +{ + for (unsigned int i = 1; i <= 5; i++) + run_test_buffer(json_input, output, stream_errno, i); +} + +static void test_istream_jsonstr_autoretry(void) +{ + const char *json_input = "\\u0001\""; + const size_t json_input_len = strlen(json_input); + struct istream *input_data, *input; + + test_begin("istream-jsonstr autoretry"); + input_data = test_istream_create_data(json_input, json_input_len); + input = i_stream_create_jsonstr(input_data); + + test_istream_set_size(input_data, 2); + test_assert(i_stream_read(input_data) == 2); + test_istream_set_size(input_data, json_input_len); + test_assert(i_stream_read(input) == 1); + test_assert(i_stream_read(input) == -1); + + i_stream_unref(&input); + i_stream_unref(&input_data); + test_end(); +} + +static void test_istream_jsonstr_partial(void) +{ + size_t len = 0; + const char *json_input = "hello\\u0060x\""; + const char *output = "hello`x"; + const size_t json_input_len = strlen(json_input); + struct istream *input_data, *input; + + test_begin("istream-jsonstr partial"); + + input_data = test_istream_create_data(json_input, json_input_len); + input = i_stream_create_jsonstr(input_data); + test_istream_set_size(input_data, 9); + test_assert(i_stream_read(input) == 5); + test_istream_set_size(input_data, json_input_len); + test_assert(i_stream_read(input) == 2); + test_assert(i_stream_read(input) == -1); + + test_assert(memcmp(i_stream_get_data(input, &len), output, I_MIN(len, strlen(output))) == 0 && + len == strlen(output)); + + i_stream_unref(&input); + i_stream_unref(&input_data); + + test_end(); +} + +void test_istream_jsonstr(void) +{ + unsigned int i; + + for (i = 0; i < N_ELEMENTS(tests); i++) { + test_begin(t_strdup_printf("istream-jsonstr %u", i+1)); + run_test(tests[i].input, tests[i].output, tests[i].stream_errno); + test_end(); + } + test_istream_jsonstr_autoretry(); + test_istream_jsonstr_partial(); +} |