[gmime] Automated message/partial unit tests



commit 1a8d582d74870d6051e2ad02fd84549e74bff722
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Fri Mar 3 15:12:41 2017 -0500

    Automated message/partial unit tests

 tests/.gitignore                                   |    1 -
 tests/Makefile.am                                  |    6 +-
 .../partial/input/skippy}/message-partial.1        |    0
 .../partial/input/skippy}/message-partial.2        |  Bin 4384 -> 4384 bytes
 .../partial/output/skippy}                         |   63 ++++-
 tests/test-partial.c                               |  265 +++++++++++++++-----
 6 files changed, 255 insertions(+), 80 deletions(-)
---
diff --git a/tests/.gitignore b/tests/.gitignore
index 0992199..9d1a70f 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -4,7 +4,6 @@ Makefile
 .libs/
 *.lo
 *.o
-data
 test-best
 test-cat
 test-headers
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 01d0e62..bdd80e6 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -14,6 +14,7 @@ AUTOMATED_TESTS =     \
        test-streams    \
        test-cat        \
        test-headers    \
+       test-partial    \
        test-mbox       \
        test-mime
 
@@ -28,8 +29,7 @@ endif
 MANUAL_TESTS =         \
        test-best       \
        test-parser     \
-       test-html       \
-       test-partial
+       test-html
 
 noinst_PROGRAMS = $(AUTOMATED_TESTS) $(MANUAL_TESTS)
 
@@ -81,7 +81,7 @@ test_iconv_LDFLAGS =
 test_iconv_DEPENDENCIES = $(DEPS)
 test_iconv_LDADD = $(LDADDS)
 
-test_partial_SOURCES = test-partial.c
+test_partial_SOURCES = test-partial.c testsuite.c testsuite.h
 test_partial_LDFLAGS = 
 test_partial_DEPENDENCIES = $(DEPS)
 test_partial_LDADD = $(LDADDS)
diff --git a/tests/message-partial.1 b/tests/data/partial/input/skippy/message-partial.1
similarity index 100%
copy from tests/message-partial.1
copy to tests/data/partial/input/skippy/message-partial.1
diff --git a/tests/message-partial.1 b/tests/data/partial/output/skippy
similarity index 97%
rename from tests/message-partial.1
rename to tests/data/partial/output/skippy
index 5d6f635..5be2555 100644
--- a/tests/message-partial.1
+++ b/tests/data/partial/output/skippy
@@ -1,17 +1,3 @@
-Path: 
atlpnn01.usenetserver.com!newsfeeds-atl2!peer1-sjc1.usenetserver.com!usenetserver.com!hub1.nntpserver.com!newsfeed4.cidera.com!newsfeed1.cidera.com!Cidera!cyclone1.gnilink.net!news-out.nuthinbutnews.com!propagator-sterling!news-in.nuthinbutnews.com!micro-heart-of-gold.mit.edu!nntp.club.cc.cmu.edu!bb3.andrew.cmu.edu!newsfeed.srv.cs.cmu.edu!anon.lcs.mit.edu!nym.alias.net!mail2news
-Date: 2 May 2002 09:42:33 -0000
-From: anonymous anon lcs mit edu
-Subject: {15_3779; Victoria & Cherry}: suzeFan - 2377h003.jpg (1/2)
-Newsgroups: alt.binaries.pictures.suze
-MIME-Version: 1.0
-Message-ID: <skippy Soft 1020332481_1 id com>
-Content-Type: message/partial; id="<skippy Soft 1020332481 id com>"; number=1; total=2
-Mail-To-News-Contact: postmaster nym alias net
-Organization: mail2news nym alias net
-Lines: 2042
-Xref: usenetserver.com alt.binaries.pictures.suze:408595
-X-Received-Date: Thu, 02 May 2002 06:28:50 EDT (atlpnn01.usenetserver.com)
-
 Message-ID: <skippy Soft 1020332481 id com>
 Subject: {15_3779; Victoria & Cherry}: suzeFan - 2377h003.jpg
 MIME-Version: 1.0
@@ -2053,3 +2039,52 @@ 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
+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
+
+------skippy.Soft.1020332481--
+
diff --git a/tests/test-partial.c b/tests/test-partial.c
index 3981976..b7c60bd 100644
--- a/tests/test-partial.c
+++ b/tests/test-partial.c
@@ -27,93 +27,234 @@
 
 #include <gmime/gmime.h>
 
+#include "testsuite.h"
 
-void
-print_depth (int depth)
-{
-       int i;
-       
-       for (i = 0; i < depth; i++)
-               fprintf (stdout, "   ");
-}
+extern int verbose;
 
-void
-print_mime_struct (GMimeObject *part, int depth)
+#define d(x)
+#define v(x) if (verbose > 3) x
+
+static gboolean
+streams_match (GMimeStream *expected, GMimeStream *actual)
 {
-       const GMimeContentType *type;
-       GMimeMultipart *multipart;
-       GMimeObject *subpart;
-       int i, n;
-       
-       print_depth (depth);
-       type = g_mime_object_get_content_type (part);
-       fprintf (stdout, "Content-Type: %s/%s\n", type->type, type->subtype);
+       char buf[4096], dbuf[4096], errstr[1024], *bufptr, *bufend, *dbufptr;
+       gint64 len, totalsize, totalread = 0;
+       size_t nread, size;
+       gint64 offset = 0;
+       ssize_t n;
+       
+       v(fprintf (stdout, "Checking if streams match... "));
+       
+       if (expected->bound_end != -1) {
+               totalsize = expected->bound_end - expected->position;
+       } else if ((len = g_mime_stream_length (expected)) == -1) {
+               sprintf (errstr, "Error: Unable to get length of expected stream\n");
+               goto fail;
+       } else if (len < (expected->position - expected->bound_start)) {
+               sprintf (errstr, "Error: Overflow on expected stream?\n");
+               goto fail;
+       } else {
+               totalsize = len - (expected->position - expected->bound_start);
+       }
+       
+       while (totalread < totalsize) {
+               if ((n = g_mime_stream_read (expected, buf, sizeof (buf))) <= 0)
+                       break;
+               
+               size = n;
+               nread = 0;
+               totalread += n;
+               
+               d(fprintf (stderr, "read %zu bytes from expected stream\n", size));
                
-       if (GMIME_IS_MULTIPART (part)) {
-               multipart = (GMimeMultipart *) part;
+               do {
+                       if ((n = g_mime_stream_read (actual, dbuf + nread, size - nread)) <= 0) {
+                               fprintf (stderr, "actual stream's read(%p, dbuf + %zu, %zu) returned %zd, 
EOF\n", actual, nread, size - nread, n);
+                               break;
+                       }
+                       d(fprintf (stderr, "read %zd bytes from actual stream\n", n));
+                       nread += n;
+               } while (nread < size);
                
-               n = g_mime_multipart_get_count (multipart);
-               for (i = 0; i < n; i++) {
-                       subpart = g_mime_multipart_get_part (multipart, i);
-                       print_mime_struct (subpart, depth + 1);
-                       g_object_unref (subpart);
+               if (nread < size) {
+                       sprintf (errstr, "Error: actual stream appears to be truncated, short %zu+ bytes\n",
+                                size - nread);
+                       goto fail;
                }
+               
+               bufend = buf + size;
+               dbufptr = dbuf;
+               bufptr = buf;
+               
+               while (bufptr < bufend) {
+                       if (*bufptr != *dbufptr)
+                               break;
+                       
+                       dbufptr++;
+                       bufptr++;
+               }
+               
+               if (bufptr < bufend) {
+                       sprintf (errstr, "Error: content does not match at offset %" G_GINT64_FORMAT "\n",
+                                offset + (bufptr - buf));
+                       /*fprintf (stderr, "-->'%.*s'<--\nvs\n-->'%.*s'<--\n",
+                         bufend - bufptr, bufptr, bufend - bufptr, dbufptr);*/
+                       goto fail;
+               } else {
+                       d(fprintf (stderr, "%zu bytes identical\n", size));
+               }
+               
+               offset += size;
+       }
+       
+       if (totalread < totalsize) {
+               strcpy (errstr, "Error: expected more data from input stream\n");
+               goto fail;
        }
+       
+       if ((n = g_mime_stream_read (actual, buf, sizeof (buf))) > 0) {
+               strcpy (errstr, "Error: actual stream appears to contain extra content\n");
+               goto fail;
+       }
+       
+       v(fputs ("passed\n", stdout));
+       
+       return TRUE;
+       
+ fail:
+       
+       v(fputs ("failed\n", stdout));
+       v(fputs (errstr, stderr));
+       
+       return FALSE;
 }
 
-
 int main (int argc, char **argv)
 {
+       const char *datadir = "data/partial";
+       GMimeStream *stream, *combined, *expected;
+       GString *input, *output;
        GMimeMessage *message;
        GMimeParser *parser;
-       GMimeStream *stream;
        GPtrArray *partials;
+       int inlen, outlen;
+       GDir *data, *dir;
+       const char *dent;
+       struct stat st;
+       char *path;
        int fd, i;
        
-       if (argc < 2)
-               return 0;
-       
        g_mime_init ();
        
-       parser = g_mime_parser_new ();
+       testsuite_init (argc, argv);
        
-       partials = g_ptr_array_new ();
-       for (i = 1; i < argc; i++) {
-               if ((fd = open (argv[i], O_RDONLY, 0)) == -1)
-                       return -1;
-               
-               stream = g_mime_stream_fs_new (fd);
-               g_mime_parser_init_with_stream (parser, stream);
-               g_object_unref (stream);
-               
-               if (!(message = g_mime_parser_construct_message (parser)))
-                       return -2;
-               
-               if (!GMIME_IS_MESSAGE_PARTIAL (message->mime_part))
-                       return -3;
-               
-               g_ptr_array_add (partials, message->mime_part);
-               g_object_ref (message->mime_part);
-               g_object_unref (message);
-       }
+       testsuite_start ("message/partial");
+       
+       output = g_string_new (datadir);
+       g_string_append_c (output, G_DIR_SEPARATOR);
+       g_string_append (output, "output");
        
-       g_object_unref (parser);
+       input = g_string_new (datadir);
+       g_string_append_c (input, G_DIR_SEPARATOR);
+       g_string_append (input, "input");
        
-       message = g_mime_message_partial_reconstruct_message ((GMimeMessagePartial **) partials->pdata,
-                                                             partials->len);
-       g_ptr_array_free (partials, TRUE);
-       if (!message)
-               return -4;
+       if (!(data = g_dir_open (input->str, 0, NULL)))
+               goto exit;
        
-       stream = g_mime_stream_fs_new (STDERR_FILENO);
-       g_mime_object_write_to_stream (GMIME_OBJECT (message), stream);
+       g_string_append_c (output, G_DIR_SEPARATOR);
+       g_string_append_c (input, G_DIR_SEPARATOR);
+       outlen = output->len;
+       inlen = input->len;
        
-       print_mime_struct (message->mime_part, 0);
+       while ((dent = g_dir_read_name (data))) {
+               g_string_append (output, dent);
+               g_string_append (input, dent);
+               
+               parser = g_mime_parser_new ();
+               partials = g_ptr_array_new ();
+               dir = NULL;
+               
+               testsuite_check ("%s", dent);
+               try {
+                       if (!(dir = g_dir_open (input->str, 0, NULL)))
+                               throw (exception_new ("Failed to open `%s'", input->str));
+                       
+                       while ((dent = g_dir_read_name (dir))) {
+                               path = g_build_filename (input->str, dent, NULL);
+                               
+                               if ((fd = open (path, O_RDONLY, 0)) == -1)
+                                       throw (exception_new ("Failed to open `%s'", path));
+                               
+                               stream = g_mime_stream_fs_new (fd);
+                               g_mime_parser_init_with_stream (parser, stream);
+                               g_object_unref (stream);
+                               
+                               if (!(message = g_mime_parser_construct_message (parser)))
+                                       throw (exception_new ("Failed to parse `%s'", path));
+                               
+                               if (!GMIME_IS_MESSAGE_PARTIAL (message->mime_part)) {
+                                       g_object_unref (message);
+                                       throw (exception_new ("`%s' is not a message/partial", path));
+                               }
+                               
+                               g_ptr_array_add (partials, message->mime_part);
+                               g_object_ref (message->mime_part);
+                               g_object_unref (message);
+                               g_free (path);
+                               path = NULL;
+                       }
+                       
+                       if (!(message = g_mime_message_partial_reconstruct_message ((GMimeMessagePartial **) 
partials->pdata, partials->len)))
+                               throw (exception_new ("Failed to recombine message/partial `%s'", 
input->str));
+                       
+                       combined = g_mime_stream_mem_new ();
+                       g_mime_object_write_to_stream (GMIME_OBJECT (message), combined);
+                       g_mime_stream_reset (combined);
+                       g_object_unref (message);
+                       
+                       if ((fd = open (output->str, O_RDONLY, 0)) == -1) {
+                               fd = open (output->str, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+                               expected = g_mime_stream_fs_new (fd);
+                               g_mime_stream_write_to_stream (combined, expected);
+                               g_object_unref (expected);
+                               
+                               g_object_unref (combined);
+                               throw (exception_new ("Failed to open `%s'", output->str));
+                       }
+                       
+                       expected = g_mime_stream_fs_new (fd);
+                       
+                       if (!streams_match (expected, combined)) {
+                               g_object_unref (combined);
+                               g_object_unref (expected);
+                               
+                               throw (exception_new ("messages do not match for `%s'", input->str));
+                       }
+                       
+                       g_object_unref (combined);
+                       g_object_unref (expected);
+                       g_dir_close (dir);
+                       
+                       testsuite_check_passed ();
+               } catch (ex) {
+                       testsuite_check_failed ("%s: %s", input->str, ex->message);
+                       
+                       if (dir != NULL)
+                               g_dir_close (dir);
+                       
+                       g_free (path);
+               } finally;
+               
+               g_string_truncate (output, outlen);
+               g_string_truncate (input, inlen);
+               g_ptr_array_free (partials, TRUE);
+               g_object_unref (parser);
+       }
        
-       g_object_unref (message);
-       g_object_unref (stream);
+ exit:
+       testsuite_end ();
        
        g_mime_shutdown ();
        
-       return 0;
+       return testsuite_exit ();
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]