rfc822: new module.
[ccan] / ccan / rfc822 / test / run-unfold.c
1 #include <ccan/foreach/foreach.h>
2 #include <ccan/failtest/failtest_override.h>
3 #include <ccan/failtest/failtest.h>
4 #include <ccan/tap/tap.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #define CCAN_RFC822_DEBUG
9
10 #include <ccan/rfc822/rfc822.h>
11
12 #include <ccan/rfc822/rfc822.c>
13
14 #include "testdata.h"
15 #include "helper.h"
16
17 #define UNFOLDED " This is a string with\tlots of \tplaces to fold"
18 #define FOLD_POINTS 11
19
20 #define BEFORE "Date: Tue, 22 Feb 2011 00:15:59 +1100\n" \
21         "From: Mister From <from@example.com>\n" \
22         "To: Mizz To <to@example.org>\n" \
23         "Subject:"
24
25 #define AFTER "Message-ID: <20110221131559.GA28327@example>\n" \
26         "\n" \
27         "body"
28
29 static struct bytestring fold_and_assemble(int foldat, int crlf, int truncated)
30 {
31         char *buf, *p;
32         int i, n = 0;
33
34         buf = talloc_array(NULL, char, strlen(BEFORE) + strlen(AFTER) + 3*strlen(UNFOLDED) + 2);
35         if (!buf)
36                 exit(0);
37
38         memcpy(buf, BEFORE, strlen(BEFORE));
39
40         p = buf + strlen(BEFORE);
41
42         for (i = 0; i < strlen(UNFOLDED); i++) {
43                 if (rfc822_iswsp(UNFOLDED[i])) {
44                         n++;
45                         if ((foldat == -1) || (foldat == n)) {
46                                 if (crlf)
47                                         *p++ = '\r';
48                                 *p++ = '\n';
49                         }
50                 }
51                 *p++ = UNFOLDED[i];
52         }
53
54         if (!truncated) {
55                 if (crlf)
56                         *p++ = '\r';
57                 *p++ = '\n';
58
59                 memcpy(p, AFTER, strlen(AFTER));
60                 p += strlen(AFTER);
61         }
62
63         return bytestring(buf, p - buf);
64 }
65
66 static void check_folded_header(const char *buf, size_t len)
67 {
68         struct rfc822_msg *msg;
69         struct rfc822_header *hdr;
70         struct bytestring hunfold;
71
72         msg = rfc822_start(NULL, buf, len);
73         allocation_failure_check();
74
75         hdr = rfc822_first_header(msg);
76         allocation_failure_check();
77         hdr = rfc822_next_header(msg, hdr);
78         allocation_failure_check();
79         hdr = rfc822_next_header(msg, hdr);
80         allocation_failure_check();
81
82         /* This is the one we care about */
83         hdr = rfc822_next_header(msg, hdr);
84         allocation_failure_check();
85
86         ok(hdr && (rfc822_header_errors(msg, hdr) == 0), "Folded header valid");
87         allocation_failure_check();
88
89         hunfold = rfc822_header_unfolded_value(msg, hdr);
90         allocation_failure_check();
91
92         ok(hunfold.len == strlen(UNFOLDED), "Unfolded length %d, should be %d",
93            hunfold.len, strlen(UNFOLDED));
94         ok1(memcmp(hunfold.ptr, UNFOLDED, hunfold.len) == 0);
95
96         rfc822_free(msg);
97         allocation_failure_check();
98 }
99
100 int main(int argc, char *argv[])
101 {
102         struct bytestring msgbuf;
103         int crlf, truncated, i;
104
105         failtest_setup(argc, argv);
106
107         plan_tests(3 * 2 * 2 * (FOLD_POINTS + 2));
108
109         foreach_int(crlf, 0, 1) {
110                 foreach_int(truncated, 0, 1) {
111                         for (i = -1; i <= FOLD_POINTS; i++) {
112                                 msgbuf = fold_and_assemble(i, crlf, truncated);
113                                 check_folded_header(msgbuf.ptr, msgbuf.len);
114                                 talloc_free(msgbuf.ptr);
115                         }
116                 }
117         }
118
119         /* This exits depending on whether all tests passed */
120         failtest_exit(exit_status());
121 }