]> git.ozlabs.org Git - ccan/blobdiff - ccan/rfc822/test/run-hdr-and-body.c
rfc822: new module.
[ccan] / ccan / rfc822 / test / run-hdr-and-body.c
diff --git a/ccan/rfc822/test/run-hdr-and-body.c b/ccan/rfc822/test/run-hdr-and-body.c
new file mode 100644 (file)
index 0000000..d3f563f
--- /dev/null
@@ -0,0 +1,185 @@
+#include <ccan/foreach/foreach.h>
+#include <ccan/failtest/failtest_override.h>
+#include <ccan/failtest/failtest.h>
+#include <ccan/tap/tap.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CCAN_RFC822_DEBUG
+
+#include <ccan/rfc822/rfc822.h>
+
+#include <ccan/rfc822/rfc822.c>
+
+#include "testdata.h"
+#include "helper.h"
+
+#define CHECK_HEADERS(_e, _msg, _h, _n, _crlf) \
+       do { \
+               int _i; \
+               for (_i = 0; _i < (_e)->nhdrs; _i++) {  \
+                       (_h) = rfc822_next_header((_msg), (_h)); \
+                       ok((_h), "header %d exists %s", _i, (_n)); \
+                       if (!(_h)) \
+                               break; \
+                       check_header((_msg), (_h), (_e)->hdrs[_i].name, \
+                                    (_e)->hdrs[_i].val, crlf); \
+               } \
+       } while (0)
+
+static void check_header(struct rfc822_msg *msg,
+                        struct rfc822_header *h,
+                        const char *name, const char *val,
+                        int crlf)
+{
+       struct bytestring hname, hvalue, hfull;
+       size_t namelen = strlen(name);
+       size_t valuelen = strlen(val);
+       size_t nln = crlf ? 2 : 1;
+       size_t fulllen = namelen + valuelen + 1 + nln;
+
+       ok(rfc822_header_errors(msg, h) == 0, "Header valid");
+       allocation_failure_check();
+
+       hname = rfc822_header_raw_name(msg, h);
+       allocation_failure_check();
+
+       ok(hname.ptr && bytestring_eq(hname, bytestring_from_string(name)),
+          "Header name \"%.*s\"", hname.len, hname.ptr);
+
+       hvalue = rfc822_header_raw_value(msg, h);
+       allocation_failure_check();
+
+       ok(hvalue.ptr && ((valuelen + nln) == hvalue.len)
+          && (memcmp(val, hvalue.ptr, valuelen) == 0)
+          && (!crlf || (hvalue.ptr[hvalue.len - 2] == '\r'))
+          && (hvalue.ptr[hvalue.len - 1] == '\n'),
+          "Header value");
+
+       hfull = rfc822_header_raw_content(msg, h);
+       allocation_failure_check();
+
+       ok(hfull.ptr && (fulllen == hfull.len)
+          && (memcmp(name, hfull.ptr, namelen) == 0)
+          && (hfull.ptr[namelen] == ':')
+          && (memcmp(val, hfull.ptr + namelen + 1, valuelen) == 0)
+          && (!crlf || (hfull.ptr[fulllen-2] == '\r'))
+          && (hfull.ptr[fulllen-1] == '\n'),
+          "Full header");
+}
+
+static void test_bodyhdr(const struct aexample *e, const char *buf, size_t len,
+                        const char *exname, int crlf)
+{
+       struct rfc822_msg *msg;
+       struct rfc822_header *h = NULL;
+       struct bytestring body;
+
+       msg = rfc822_start(NULL, buf, len);
+       allocation_failure_check();
+
+       ok(msg, "opened %s", exname);
+
+       body = rfc822_body(msg);
+       allocation_failure_check();
+       ok(bytestring_eq(body, bytestring_from_string(e->body)),
+          "body content %s", exname);
+
+       CHECK_HEADERS(e, msg, h, exname, crlf);
+       h = rfc822_next_header(msg, h);
+       allocation_failure_check();
+       ok(!h, "Too many headers for %s", exname);
+
+       rfc822_free(msg);
+       allocation_failure_check();
+}
+
+static void test_hdrbody(const struct aexample *e, const char *buf, size_t len,
+                        const char *exname, int crlf)
+{
+       struct rfc822_msg *msg;
+       struct rfc822_header *h = NULL;
+       struct bytestring body;
+
+       msg = rfc822_start(NULL, buf, len);
+       allocation_failure_check();
+       ok(msg, "opened %s", exname);
+
+       CHECK_HEADERS(e, msg, h, exname, crlf);
+       h = rfc822_next_header(msg, h);
+       allocation_failure_check();
+       ok(!h, "Too many headers for %s", exname);
+
+       body = rfc822_body(msg);
+       allocation_failure_check();
+       ok(bytestring_eq(body, bytestring_from_string(e->body)),
+          "body content %s", exname);
+
+       rfc822_free(msg);
+       allocation_failure_check();
+}
+
+static void test_hdrhdr(const struct aexample *e, const char *buf, size_t len,
+                       const char *exname, int crlf)
+{
+       struct rfc822_msg *msg;
+       struct rfc822_header *h;
+
+       msg = rfc822_start(NULL, buf, len);
+       allocation_failure_check();
+       ok(msg, "opened %s", exname);
+
+       h = NULL;
+       CHECK_HEADERS(e, msg, h, exname, crlf);
+
+       h = rfc822_next_header(msg, h);
+       allocation_failure_check();
+       ok(!h, "Too many headers for %s", exname);
+
+       /* And again, this time it should be cached */
+       h = NULL;
+       CHECK_HEADERS(e, msg, h, exname, crlf);
+
+       h = rfc822_next_header(msg, h);
+       allocation_failure_check();
+       ok(!h, "Too many headers for %s", exname);
+
+       rfc822_free(msg);
+       allocation_failure_check();
+}
+
+int main(int argc, char *argv[])
+{
+       struct aexample *e;
+
+       /* This is how many tests you plan to run */
+       plan_tests(20*num_aexamples() + 40*num_aexample_hdrs());
+
+       failtest_setup(argc, argv);
+
+       for_each_aexample(e) {
+               int crlf;
+
+               foreach_int(crlf, 0, 1) {
+                       const char *buf;
+                       size_t len;
+                       char exname[256];
+
+                       sprintf(exname, "%s[%s]", e->name, NLT(crlf));
+
+                       buf = assemble_msg(e, &len, crlf);
+                       ok((buf), "assembled %s", exname);
+                       if (!buf)
+                               continue;
+
+                       test_bodyhdr(e, buf, len, exname, crlf);
+                       test_hdrbody(e, buf, len, exname, crlf);
+                       test_hdrhdr(e, buf, len, exname, crlf);
+
+                       talloc_free(buf);
+               }
+       }
+
+       /* This exits depending on whether all tests passed */
+       failtest_exit(exit_status());
+}