summaryrefslogtreecommitdiffstats
path: root/src/lib/test-istream-crlf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/test-istream-crlf.c')
-rw-r--r--src/lib/test-istream-crlf.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/lib/test-istream-crlf.c b/src/lib/test-istream-crlf.c
new file mode 100644
index 0000000..5239e36
--- /dev/null
+++ b/src/lib/test-istream-crlf.c
@@ -0,0 +1,115 @@
+/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
+
+#include "test-lib.h"
+#include "str.h"
+#include "istream-private.h"
+#include "istream-crlf.h"
+
+static void test_istream_crlf_input(const char *input)
+{
+ string_t *output;
+ const unsigned char *data;
+ size_t size = 0;
+ ssize_t ret1, ret2;
+ unsigned int i, j, pos, input_len = strlen(input);
+ struct istream *istream, *crlf_istream;
+
+ output = t_str_new(256);
+
+ for (j = 0; j < 4; j++) {
+ istream = i_stream_create_from_data(input, input_len);
+ str_truncate(output, 0);
+ if (j%2 == 0) {
+ /* drop CRs */
+ crlf_istream = i_stream_create_lf(istream);
+ for (i = 0; i < input_len; i++) {
+ if (input[i] == '\r' &&
+ (i == input_len-1 || input[i+1] == '\n'))
+ ;
+ else
+ str_append_c(output, input[i]);
+ }
+ } else {
+ /* add missing CRs */
+ crlf_istream = i_stream_create_crlf(istream);
+ for (i = 0; i < input_len; i++) {
+ if (input[i] == '\n' &&
+ (i == 0 || input[i-1] != '\r'))
+ str_append_c(output, '\r');
+ str_append_c(output, input[i]);
+ }
+ }
+
+ pos = 0;
+ for (i = 1; i <= input_len; i++) {
+ if (j >= 2) {
+ i_stream_unref(&istream);
+ i_stream_unref(&crlf_istream);
+ istream = i_stream_create_from_data(input,
+ input_len);
+ crlf_istream = j%2 == 0 ?
+ i_stream_create_lf(istream) :
+ i_stream_create_crlf(istream);
+ pos = 0;
+ }
+ istream->real_stream->pos = i;
+ ret1 = i_stream_read(crlf_istream);
+ if (crlf_istream->real_stream->buffer_size != 0) {
+ /* this is pretty evil */
+ crlf_istream->real_stream->buffer_size =
+ I_MAX(crlf_istream->real_stream->pos, i);
+ }
+ ret2 = i_stream_read(crlf_istream);
+ data = i_stream_get_data(crlf_istream, &size);
+ if (ret1 > 0 || ret2 > 0) {
+ ret1 = I_MAX(ret1, 0) + I_MAX(ret2, 0);
+ test_assert(pos + (unsigned int)ret1 == size);
+ pos += ret1;
+ }
+ if (size > 0)
+ test_assert_idx(memcmp(data, str_data(output),
+ size) == 0, j*10000+i);
+ }
+ test_assert_idx(size == str_len(output), j*10000+i);
+ i_stream_unref(&crlf_istream);
+ i_stream_unref(&istream);
+ }
+}
+
+void test_istream_crlf(void)
+{
+ const char *input[] = {
+ "\rfoo",
+ "foo\nbar\r\nbaz\r\r\n",
+ "\r\nfoo",
+ "\r\r\n",
+ "\nfoo"
+ };
+ unsigned int i;
+
+ test_begin("istream crlf");
+ for (i = 0; i < N_ELEMENTS(input); i++)
+ test_istream_crlf_input(input[i]);
+ test_end();
+
+#define ISTREAM_CRLF_TEST_REPS 1000
+ test_begin("istream crlf(random)");
+ for (i = 0; i < ISTREAM_CRLF_TEST_REPS; i++) T_BEGIN {
+ char buf[100];
+ size_t len = 0;
+ while (len < sizeof(buf) - 1) {
+ switch(i_rand_limit(16)) {
+ case 0: goto outahere;
+ case 1: buf[len] = '\r'; break;
+ case 2: buf[len] = '\n'; break;
+ default: buf[len]= '.'; break;
+ }
+ len++;
+ }
+ outahere:
+ buf[len] = '\0';
+ if (len > 0)
+ test_istream_crlf_input(buf);
+ } T_END;
+ test_end();
+}