From 669f7dbd8fa520fe0cb8580c090ba70e63abb7d8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Sat, 18 Jun 2022 16:43:16 +0200 Subject: [PATCH] add test for copy_msg_convert() --- src/.gitignore | 1 + src/Makefile.am | 5 +- src/tst_msg_cvt.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++ src/util.c | 4 +- 4 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 src/tst_msg_cvt.c diff --git a/src/.gitignore b/src/.gitignore index 4c38883..5e7fc35 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -3,6 +3,7 @@ /mbsync /mdconvert /tst_imap_msgs +/tst_msg_cvt /tst_timers /tmp diff --git a/src/Makefile.am b/src/Makefile.am index f1eb996..ab56418 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,7 +54,10 @@ man_MANS = mbsync.1 $(mdconvert_man) tst_imap_msgs_SOURCES = tst_imap_msgs.c imap_msgs.c util.c -check_PROGRAMS = tst_imap_msgs +tst_msg_cvt_SOURCES = tst_msg_cvt.c sync_msg_cvt.c util.c +tst_msg_cvt_CFLAGS = -DQPRINTF_BUFF=10000 + +check_PROGRAMS = tst_imap_msgs tst_msg_cvt TESTS = $(check_PROGRAMS) tst_timers_SOURCES = tst_timers.c util.c diff --git a/src/tst_msg_cvt.c b/src/tst_msg_cvt.c new file mode 100644 index 0000000..afd437a --- /dev/null +++ b/src/tst_msg_cvt.c @@ -0,0 +1,181 @@ +// SPDX-FileCopyrightText: 2022 Oswald Buddenhagen +// SPDX-License-Identifier: GPL-2.0-or-later +// +// isync test suite +// + +#include "sync_p.h" + +#define TUID "one two tuid" + +static_assert( sizeof(TUID) - 1 == TUIDL, "TUID size mismatch" ); + +static size_t +strip_cr( char *buf ) +{ + size_t i, j = 0; + char c, pc = 0; + for (i = 0; (c = buf[i]); i++) { + if (c == '\n' && pc == '\r') + j--; + buf[j++] = c; + pc = c; + } + buf[j] = 0; + return j; +} + +#define NL_UNIX 0 +#define NL_ANY 1 + +#define AS_IS 0 +#define ADD_TUID 1 + +#define FULL 0 +#define MINIMAL 1 + +#define REGULAR 0 +#define FLAGGED 1 + +#define BIG_SIZE 2345687 +#define BIG_SIZE_STR "2.2MiB" + +#define SEP "=============" + +static void +test( const char *name, const char *in, int scr, int rscr, const char *out, int tcr, int rtcr, int add_tuid, int minimal, int flagged ) +{ + assert( !rscr || scr ); + assert( !rtcr || tcr ); + assert( !minimal || add_tuid ); + assert( !flagged || minimal ); + + printf( "Testing %s, %s (%s) => %s (%s)%s%s%s ...\n", name, + rscr ? "CRLF" : "LF", scr ? "Any" : "Unix", rtcr ? "CRLF" : "LF", tcr ? "Any" : "Unix", + add_tuid ? ", add TUID" : "", minimal ? ", minimal" : "", flagged ? ", flagged" : "" ); + + sync_rec_t srec; + message_t msg; + copy_vars_t vars; + vars.minimal = minimal; + if (add_tuid) { + vars.srec = &srec; + memcpy( vars.srec->tuid, TUID, TUIDL ); + if (minimal) { + vars.msg = &msg; + vars.msg->size = BIG_SIZE; + vars.data.flags = flagged ? F_FLAGGED : 0; + } + } else { + vars.srec = 0; + } + vars.data.data = strdup( in ); + vars.data.len = rscr ? strlen( in ) : strip_cr( vars.data.data ); + char *orig = strdup( vars.data.data ); + const char *err = copy_msg_convert( scr, tcr, &vars ); + if (err) { + printf( "FAIL: %s!\n", err ); + exit( 1 ); + } + if (!rtcr) { + char *tout = strdup( out ); + size_t toutl = strip_cr( tout ); + if (toutl != vars.data.len || memcmp( vars.data.data, tout, toutl )) { + xprintf( "FAIL!\n" + SEP " Input " SEP "\n%!&s\n" + SEP " Expected output " SEP "\n%!&s\n" + SEP " Output " SEP "\n%.*!&s\n" SEP "\n", + orig, tout, vars.data.len, vars.data.data ); + exit( 1 ); + } + free( tout ); + } else { + size_t outl = strlen( out ); + if (outl != vars.data.len || memcmp( vars.data.data, out, outl )) { + xprintf( "FAIL!\n" + SEP " Input " SEP "\n%!&s\n" + SEP " Expected output (%u bytes) " SEP "\n%!&s\n" + SEP " Actual output (%u bytes) " SEP "\n%.*!&s\n" SEP "\n", + orig, outl, out, vars.data.len, vars.data.len, vars.data.data ); + exit( 1 ); + } + } + free( orig ); + free( vars.data.data ); +} + +static void +tests( const char *name, const char *in, const char *out, int add_tuid, int minimal, int flagged ) +{ + test( name, in, NL_UNIX, NL_UNIX, out, NL_ANY, NL_ANY, add_tuid, minimal, flagged ); + test( name, in, NL_ANY, NL_UNIX, out, NL_UNIX, NL_UNIX, add_tuid, minimal, flagged ); + test( name, in, NL_ANY, NL_ANY, out, NL_UNIX, NL_UNIX, add_tuid, minimal, flagged ); + // Skip if (scr == tcr && !srec), like copy_msg() does. + if (add_tuid) { + test( name, in, NL_UNIX, NL_UNIX, out, NL_UNIX, NL_UNIX, ADD_TUID, minimal, flagged ); + test( name, in, NL_ANY, NL_UNIX, out, NL_ANY, NL_UNIX, ADD_TUID, minimal, flagged ); + test( name, in, NL_ANY, NL_ANY, out, NL_ANY, NL_ANY, ADD_TUID, minimal, flagged ); + } +} + +static void +fulltests( const char *name, const char *in, const char *out, int add_tuid ) +{ + tests( name, in, out, add_tuid, FULL, REGULAR ); +} + +static void +mintests( const char *name, const char *in, const char *out, int flagged ) +{ + tests( name, in, out, ADD_TUID, MINIMAL, flagged ); +} + +#define FROM "From: devil\r\n" +#define TO "To: me\r\n" +#define IN_TUID "X-TUID: garbage\r\n" +#define OUT_TUID "X-TUID: " TUID "\r\n" +#define SUBJECT "Subject: hell\r\n" +#define PH_SUBJECT "Subject: [placeholder] hell\r\n" +#define NO_SUBJECT "Subject: [placeholder] (No Subject)\r\n" +#define BODY "\r\nHi,\r\n\r\n...\r\n" +#define PH_BODY "\r\nHaving a size of 2.2MiB, this message is over the MaxSize limit.\r\n" \ + "Flag it and sync again (Sync mode Upgrade) to fetch its real contents.\r\n" +#define FLAGGED_PH_BODY PH_BODY "\r\nThe original message is flagged as important.\r\n" + +#define scc static const char + +int +main( void ) +{ + scc in_from_to[] = FROM TO BODY; + fulltests( "from / to", in_from_to, in_from_to, AS_IS ); + scc out_from_to[] = FROM TO OUT_TUID BODY; + fulltests( "from / to", in_from_to, out_from_to, ADD_TUID ); + scc in_from_tuid_to[] = FROM IN_TUID TO BODY; + scc out_from_tuid_to[] = FROM OUT_TUID TO BODY; + fulltests( "from / tuid / to", in_from_tuid_to, out_from_tuid_to, ADD_TUID ); + + scc out_from_to_ph[] = FROM TO OUT_TUID NO_SUBJECT PH_BODY; + mintests( "from / to", in_from_to, out_from_to_ph, REGULAR ); + scc out_from_to_flagged_ph[] = FROM TO OUT_TUID NO_SUBJECT FLAGGED_PH_BODY; + mintests( "from / to", in_from_to, out_from_to_flagged_ph, FLAGGED ); + scc out_from_tuid_to_ph[] = FROM OUT_TUID TO NO_SUBJECT PH_BODY; + mintests( "from / tuid / to", in_from_tuid_to, out_from_tuid_to_ph, REGULAR ); + scc in_from_subj_to[] = FROM SUBJECT TO BODY; + scc out_from_subj_to[] = FROM PH_SUBJECT TO OUT_TUID PH_BODY; + mintests( "from / subject / to", in_from_subj_to, out_from_subj_to, REGULAR ); + scc in_from_subj_tuid_to[] = FROM SUBJECT IN_TUID TO BODY; + scc out_from_subj_tuid_to[] = FROM PH_SUBJECT OUT_TUID TO PH_BODY; + mintests( "from / subject / tuid / to", in_from_subj_tuid_to, out_from_subj_tuid_to, REGULAR ); + scc in_subj_from_tuid_to[] = SUBJECT FROM IN_TUID TO BODY; + scc out_subj_from_tuid_to[] = PH_SUBJECT FROM OUT_TUID TO PH_BODY; + mintests( "subject / from / tuid / to", in_subj_from_tuid_to, out_subj_from_tuid_to, REGULAR ); + scc in_from_tuid_subj_to[] = FROM IN_TUID SUBJECT TO BODY; + scc out_from_tuid_subj_to[] = FROM OUT_TUID PH_SUBJECT TO PH_BODY; + mintests( "from / tuid / subject / to", in_from_tuid_subj_to, out_from_tuid_subj_to, REGULAR ); + scc in_tuid_from_subj_to[] = IN_TUID FROM SUBJECT TO BODY; + scc out_tuid_from_subj_to[] = OUT_TUID FROM PH_SUBJECT TO PH_BODY; + mintests( "tuid / from / subject / to", in_tuid_from_subj_to, out_tuid_from_subj_to, REGULAR ); + + return 0; +} diff --git a/src/util.c b/src/util.c index aa8f28a..767694d 100644 --- a/src/util.c +++ b/src/util.c @@ -196,7 +196,9 @@ sys_error( const char *msg, ... ) // TODO: Trade off segments vs. buffer capacity dynamically. #define QPRINTF_SEGS 16 -#define QPRINTF_BUFF 1000 +#ifndef QPRINTF_BUFF +# define QPRINTF_BUFF 1000 +#endif typedef void (*printf_cb)( const char **segs, uint *segls, int nsegs, uint totlen, void *aux );