summaryrefslogtreecommitdiffstats
path: root/src/lib/test-istream-jsonstr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/test-istream-jsonstr.c')
-rw-r--r--src/lib/test-istream-jsonstr.c139
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();
+}