]> git.ozlabs.org Git - ccan/blobdiff - ccan/take/test/run.c
take: new module for parameter ownership.
[ccan] / ccan / take / test / run.c
diff --git a/ccan/take/test/run.c b/ccan/take/test/run.c
new file mode 100644 (file)
index 0000000..0c8ca2a
--- /dev/null
@@ -0,0 +1,102 @@
+#include <stdlib.h>
+#include <stdbool.h>
+
+static bool fail_realloc;
+static void *my_realloc(void *p, size_t len)
+{
+       if (fail_realloc)
+               return NULL;
+       return realloc(p, len);
+}
+#define realloc my_realloc
+
+#include <ccan/take/take.h>
+#include <ccan/take/take.c>
+#include <ccan/tap/tap.h>
+
+static int my_allocfail_called;
+static void my_allocfail(const void *p)
+{
+       my_allocfail_called++;
+}      
+
+static void recurse(const char *takeme, int count)
+{
+       if (count < 1000)
+               recurse(take(strdup(takeme)), count+1);
+       if (taken(takeme))
+               free((char *)takeme);
+}
+
+int main(void)
+{
+       const char *p = "hi";
+
+       plan_tests(43);
+
+       /* We can take NULL. */
+       ok1(take(NULL) == NULL);
+       ok1(is_taken(NULL));
+       ok1(taken_any());
+       ok1(taken(NULL)); /* Undoes take() */
+       ok1(!is_taken(NULL));
+       ok1(!taken(NULL));
+
+       /* We can take NULL twice! */
+       ok1(take(NULL) == NULL);
+       ok1(take(NULL) == NULL);
+       ok1(is_taken(NULL));
+       ok1(taken_any());
+       ok1(taken(NULL)); /* Undoes take() */
+       ok1(is_taken(NULL));
+       ok1(taken_any());
+       ok1(taken(NULL)); /* Undoes take() */
+       ok1(!is_taken(NULL));
+       ok1(!taken(NULL));
+       ok1(!taken_any());
+
+       /* We can take a real pointer. */
+       ok1(take(p) == p);
+       ok1(is_taken(p));
+       ok1(taken_any());
+       ok1(taken(p)); /* Undoes take() */
+       ok1(!is_taken(p));
+       ok1(!taken(p));
+       ok1(!taken_any());
+
+       /* Force a failure. */
+       ok1(!my_allocfail_called);
+       ok1(take(p) == p);
+       ok1(take(p+1) == p+1);
+
+       fail_realloc = true;
+       /* Without a handler, must pass through and leak. */
+       ok1(take(p+2) == p+2);
+       ok1(!taken(p+2));
+
+       /* Now, with a handler. */
+       take_allocfail(my_allocfail);
+       ok1(take(p+2) == NULL);
+
+       ok1(my_allocfail_called == 1);
+       ok1(taken_any());
+       ok1(taken(p));
+       ok1(taken(p+1));
+       ok1(is_taken(NULL));
+       ok1(taken(NULL));
+       ok1(!taken(NULL));
+       ok1(!taken_any());
+
+       /* Test some deep nesting. */
+       fail_realloc = false;
+       recurse("hello", 0);
+       ok1(max_taken == 1000);
+       ok1(!taken_any());
+
+       take_cleanup();
+       ok1(num_taken == 0);
+       ok1(max_taken == 0);
+       ok1(takenarr == NULL);
+
+       return exit_status();
+}