]> git.ozlabs.org Git - ccan/blobdiff - ccan/pushpull/test/run.c
pushpull: new module.
[ccan] / ccan / pushpull / test / run.c
diff --git a/ccan/pushpull/test/run.c b/ccan/pushpull/test/run.c
new file mode 100644 (file)
index 0000000..f51ef20
--- /dev/null
@@ -0,0 +1,150 @@
+#include <ccan/pushpull/pushpull.h>
+/* Include the C files directly. */
+#include <ccan/pushpull/push.c>
+#include <ccan/pushpull/pull.c>
+#include <ccan/tap/tap.h>
+
+struct foo {
+       uint64_t vu64;
+       uint32_t vu32;
+       uint16_t vu16;
+       uint8_t vu8;
+       unsigned char vuchar;
+       int64_t vs64;
+       int32_t vs32;
+       int16_t vs16;
+       int8_t vs8;
+       char vchar;
+       char bytes[100];
+};
+
+static void *fail_reallocfn(void *ptr, size_t size)
+{
+       return NULL;
+}
+
+static bool push_foo(char **p, size_t *len, const struct foo *foo)
+{
+       return push_u64(p, len, foo->vu64) &&
+               push_u32(p, len, foo->vu32) &&
+               push_u16(p, len, foo->vu16) &&
+               push_u8(p, len, foo->vu8) &&
+               push_uchar(p, len, foo->vuchar) &&
+               push_s64(p, len, foo->vs64) &&
+               push_s32(p, len, foo->vs32) &&
+               push_s16(p, len, foo->vs16) &&
+               push_s8(p, len, foo->vs8) &&
+               push_char(p, len, foo->vchar) &&
+               push_bytes(p, len, foo->bytes, sizeof(foo->bytes));
+}
+
+static bool pull_foo(const char **p, size_t *len, struct foo *foo)
+{
+       int ret;
+
+       ret = pull_u64(p, len, &foo->vu64) +
+               pull_u32(p, len, &foo->vu32) +
+               pull_u16(p, len, &foo->vu16) +
+               pull_u8(p, len, &foo->vu8) +
+               pull_uchar(p, len, &foo->vuchar) +
+               pull_s64(p, len, &foo->vs64) +
+               pull_s32(p, len, &foo->vs32) +
+               pull_s16(p, len, &foo->vs16) +
+               pull_s8(p, len, &foo->vs8) +
+               pull_char(p, len, &foo->vchar) +
+               pull_bytes(p, len, foo->bytes, sizeof(foo->bytes));
+
+       if (ret != 11)
+               ok1(len == 0 && *p == NULL);
+       return ret == 11;
+}
+
+static bool foo_equal(const struct foo *f1, const struct foo *f2)
+{
+       return f1->vu64 == f2->vu64 &&
+               f1->vu32 == f2->vu32 &&
+               f1->vu16 == f2->vu16 &&
+               f1->vu8 == f2->vu8 &&
+               f1->vuchar == f2->vuchar &&
+               f1->vs64 == f2->vs64 &&
+               f1->vs32 == f2->vs32 &&
+               f1->vs16 == f2->vs16 &&
+               f1->vs8 == f2->vs8 &&
+               f1->vchar == f2->vchar &&
+               memcmp(f1->bytes, f2->bytes, sizeof(f1->bytes)) == 0;
+}
+
+int main(void)
+{
+       char *buffer;
+       const char *p;
+       size_t len, left;
+       struct foo *foo, *foo2;
+
+       /* This is how many tests you plan to run */
+       plan_tests(17);
+
+       /* Valgrind will make sure we don't read padding! */
+       foo = malloc(sizeof(*foo));
+       foo->vu64 = 0x01020304050607ULL;
+       foo->vu32 = 0x08090a0b;
+       foo->vu16 = 0x0c0d;
+       foo->vu8 = 0x0e;
+       foo->vuchar = 0x0f;
+       foo->vs64 = -0x1011121314151617LL;
+       foo->vs32 = -0x18191a1b;
+       foo->vs16 = -0x1c1d;
+       foo->vs8 = -0x1e;
+       foo->vchar = -0x1f;
+       memset(foo->bytes, 0x20, sizeof(foo->bytes));
+       strcpy(foo->bytes, "This is a test");
+
+       buffer = malloc(1);
+       len = 0;
+       ok1(push_foo(&buffer, &len, foo));
+       ok1(len <= sizeof(*foo));
+
+       /* Triggers valgrind's uninitialized value warning */
+       ok1(!memchr(buffer, 0x21, len));
+
+       p = buffer;
+       left = len;
+       foo2 = malloc(sizeof(*foo2));
+       ok1(pull_foo(&p, &left, foo2));
+       ok1(left == 0);
+       ok1(p == buffer + len);
+       ok1(foo_equal(foo, foo2));
+
+       /* Too-small for pull, it should fail and set ptr/len to 0 */
+       p = buffer;
+       left = 0;
+       ok1(!pull_u64(&p, &left, &foo2->vu64));
+       ok1(p == NULL && left == 0);
+       /* Shouldn't change field! */
+       ok1(foo_equal(foo, foo2));
+
+       left = 7;
+       ok1(!pull_u64(&p, &left, &foo2->vu64));
+       ok1(p == NULL && left == 0);
+       /* Shouldn't change field! */
+       ok1(foo_equal(foo, foo2));
+
+       /* Discard should work. */
+       left = len;
+       ok1(pull_bytes(&p, &left, NULL, sizeof(foo->bytes)));
+       ok1(left == len - sizeof(foo->bytes));
+
+       /* Push failures should be clean. */
+       push_set_realloc(fail_reallocfn);
+       p = buffer;
+       left = len;
+       ok1(!push_u64(&buffer, &left, foo->vu64));
+       ok1(p == buffer && left == len);
+
+       free(buffer);
+       free(foo);
+       free(foo2);
+
+       /* This exits depending on whether all tests passed */
+       return exit_status();
+}