From 0206052b5660cb77cdd0a0ac3c83dd4c3d996007 Mon Sep 17 00:00:00 2001 From: William Casarin Date: Mon, 9 Jul 2018 15:48:55 -0700 Subject: started on positioning + command structure --- ccan/tal/str/test/helper.h | 22 +++++ ccan/tal/str/test/run-fmt-terminate.c | 22 +++++ ccan/tal/str/test/run-string.c | 90 +++++++++++++++++++ ccan/tal/str/test/run-strndup.c | 22 +++++ ccan/tal/str/test/run-strreg.c | 124 ++++++++++++++++++++++++++ ccan/tal/str/test/run-take.c | 48 +++++++++++ ccan/tal/str/test/run.c | 158 ++++++++++++++++++++++++++++++++++ 7 files changed, 486 insertions(+) create mode 100644 ccan/tal/str/test/helper.h create mode 100644 ccan/tal/str/test/run-fmt-terminate.c create mode 100644 ccan/tal/str/test/run-string.c create mode 100644 ccan/tal/str/test/run-strndup.c create mode 100644 ccan/tal/str/test/run-strreg.c create mode 100644 ccan/tal/str/test/run-take.c create mode 100644 ccan/tal/str/test/run.c (limited to 'ccan/tal/str/test') diff --git a/ccan/tal/str/test/helper.h b/ccan/tal/str/test/helper.h new file mode 100644 index 0000000..5f0b68f --- /dev/null +++ b/ccan/tal/str/test/helper.h @@ -0,0 +1,22 @@ +/* tal/talloc can't implement tal_first/tal_next. */ +#ifdef TAL_USE_TALLOC +static inline bool no_children(const void *ctx) +{ + return talloc_total_blocks(ctx) == 1; +} + +static inline bool single_child(const void *ctx, const void *child) +{ + return talloc_total_blocks(ctx) == 2 && tal_parent(child) == ctx; +} +#else +static inline bool no_children(const void *ctx) +{ + return !tal_first(ctx); +} + +static inline bool single_child(const void *ctx, const void *child) +{ + return tal_first(ctx) == child && !tal_next(child) && !tal_first(child); +} +#endif diff --git a/ccan/tal/str/test/run-fmt-terminate.c b/ccan/tal/str/test/run-fmt-terminate.c new file mode 100644 index 0000000..374ca03 --- /dev/null +++ b/ccan/tal/str/test/run-fmt-terminate.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include +#include "helper.h" + +/* Empty format string: should still terminate! */ +int main(void) +{ + char *str; + const char *fmt = ""; + + plan_tests(1); + /* GCC complains about empty format string, complains about non-literal + * with no args... */ + str = tal_fmt(NULL, fmt, ""); + ok1(!strcmp(str, "")); + tal_free(str); + + return exit_status(); +} diff --git a/ccan/tal/str/test/run-string.c b/ccan/tal/str/test/run-string.c new file mode 100644 index 0000000..533ad01 --- /dev/null +++ b/ccan/tal/str/test/run-string.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include "helper.h" + +int main(void) +{ + char *parent, *c; + + plan_tests(32); + + parent = tal(NULL, char); + ok1(parent); + + c = tal_strdup(parent, "hello"); + ok1(strcmp(c, "hello") == 0); + ok1(tal_parent(c) == parent); + tal_free(c); + + c = tal_strndup(parent, "hello", 3); + ok1(strcmp(c, "hel") == 0); + ok1(tal_parent(c) == parent); + tal_free(c); + +#ifdef TAL_USE_TALLOC + c = tal_talloc_typechk_(parent, char *); +#else + c = tal_typechk_(parent, char *); +#endif + c = tal_dup_arr(parent, char, "hello", 6, 0); + ok1(strcmp(c, "hello") == 0); + ok1(strcmp(tal_name(c), "char[]") == 0); + ok1(tal_parent(c) == parent); + tal_free(c); + + /* Now with an extra byte. */ + c = tal_dup_arr(parent, char, "hello", 6, 1); + ok1(strcmp(c, "hello") == 0); + ok1(strcmp(tal_name(c), "char[]") == 0); + ok1(tal_parent(c) == parent); + strcat(c, "x"); + tal_free(c); + + c = tal_fmt(parent, "hello %s", "there"); + ok1(strcmp(c, "hello there") == 0); + ok1(tal_parent(c) == parent); + tal_free(c); + + c = tal_strcat(parent, "hello ", "there"); + ok1(strcmp(c, "hello there") == 0); + ok1(tal_parent(c) == parent); + + /* Make sure take works correctly. */ + c = tal_strcat(parent, take(c), " again"); + ok1(strcmp(c, "hello there again") == 0); + ok1(tal_parent(c) == parent); + ok1(single_child(parent, c)); + + c = tal_strcat(parent, "And ", take(c)); + ok1(strcmp(c, "And hello there again") == 0); + ok1(tal_parent(c) == parent); + ok1(single_child(parent, c)); + + /* NULL pass through works... */ + c = tal_strcat(parent, take(NULL), take(c)); + ok1(!c); + ok1(no_children(parent)); + + c = tal_strcat(parent, take(tal_strdup(parent, "hi")), + take(NULL)); + ok1(!c); + ok1(no_children(parent)); + + c = tal_strcat(parent, take(NULL), take(NULL)); + ok1(!c); + ok1(no_children(parent)); + + /* Appending formatted strings. */ + c = tal_strdup(parent, "hi"); + ok1(tal_append_fmt(&c, "%s %s", "there", "world")); + ok1(strcmp(c, "hithere world") == 0); + ok1(tal_parent(c) == parent); + + ok1(!tal_append_fmt(&c, take(NULL), "there", "world")); + ok1(strcmp(c, "hithere world") == 0); + + tal_free(parent); + + return exit_status(); +} diff --git a/ccan/tal/str/test/run-strndup.c b/ccan/tal/str/test/run-strndup.c new file mode 100644 index 0000000..55e35fd --- /dev/null +++ b/ccan/tal/str/test/run-strndup.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include +#include "helper.h" + +int main(void) +{ + char *str, *copy; + + plan_tests(1); + str = malloc(5); + memcpy(str, "hello", 5); + /* We should be fine to strndup src without nul terminator. */ + copy = tal_strndup(NULL, str, 5); + ok1(!strcmp(copy, "hello")); + tal_free(copy); + free(str); + + return exit_status(); +} diff --git a/ccan/tal/str/test/run-strreg.c b/ccan/tal/str/test/run-strreg.c new file mode 100644 index 0000000..93b8602 --- /dev/null +++ b/ccan/tal/str/test/run-strreg.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include "helper.h" + +static bool find_parent(tal_t *child, tal_t *parent) +{ + tal_t *i; + + for (i = child; i; i = tal_parent(i)) + if (i == parent) + return true; + + return false; +} + +int main(void) +{ + void *ctx = tal_strdup(NULL, "toplevel"); + char *a, *b; + /* If it accesses this, it will crash. */ + char **invalid = (char **)1L; + + plan_tests(41); + /* Simple matching. */ + ok1(tal_strreg(ctx, "hello world!", "hello") == true); + ok1(tal_strreg(ctx, "hello world!", "hi") == false); + + /* No parentheses means we don't use any extra args. */ + ok1(tal_strreg(ctx, "hello world!", "hello", invalid) == true); + ok1(tal_strreg(ctx, "hello world!", "hi", invalid) == false); + + ok1(tal_strreg(ctx, "hello world!", "[a-z]+", invalid) == true); + ok1(tal_strreg(ctx, "hello world!", "([a-z]+)", &a, invalid) == true); + /* Found string */ + ok1(streq(a, "hello")); + /* Allocated off ctx */ + ok1(find_parent(a, ctx)); + tal_free(a); + + ok1(tal_strreg(ctx, "hello world!", "([a-z]*) ([a-z]+)", + &a, &b, invalid) == true); + ok1(streq(a, "hello")); + ok1(streq(b, "world")); + ok1(find_parent(a, ctx)); + ok1(find_parent(b, ctx)); + tal_free(a); + tal_free(b); + + /* * after parentheses returns last match. */ + ok1(tal_strreg(ctx, "hello world!", "([a-z])* ([a-z]+)", + &a, &b, invalid) == true); + ok1(streq(a, "o")); + ok1(streq(b, "world")); + tal_free(a); + tal_free(b); + + /* Nested parentheses are ordered by open brace. */ + ok1(tal_strreg(ctx, "hello world!", "(([a-z]*) world)", + &a, &b, invalid) == true); + ok1(streq(a, "hello world")); + ok1(streq(b, "hello")); + tal_free(a); + tal_free(b); + + /* Nested parentheses are ordered by open brace. */ + ok1(tal_strreg(ctx, "hello world!", "(([a-z]*) world)", + &a, &b, invalid) == true); + ok1(streq(a, "hello world")); + ok1(streq(b, "hello")); + tal_free(a); + tal_free(b); + + /* NULL means we're not interested. */ + ok1(tal_strreg(ctx, "hello world!", "((hello|goodbye) world)", + &a, NULL, invalid) == true); + ok1(streq(a, "hello world")); + tal_free(a); + + /* No leaks! */ + ok1(no_children(ctx)); + + /* NULL arg with take means always fail. */ + ok1(tal_strreg(ctx, take(NULL), "((hello|goodbye) world)", + &b, NULL, invalid) == false); + + /* Take string. */ + a = tal_strdup(ctx, "hello world!"); + ok1(tal_strreg(ctx, take(a), "([a-z]+)", &b, invalid) == true); + ok1(streq(b, "hello")); + ok1(tal_parent(b) == ctx); + tal_free(b); + ok1(no_children(ctx)); + + /* Take regex. */ + a = tal_strdup(ctx, "([a-z]+)"); + ok1(tal_strreg(ctx, "hello world!", take(a), &b, invalid) == true); + ok1(streq(b, "hello")); + ok1(tal_parent(b) == ctx); + tal_free(b); + ok1(no_children(ctx)); + + /* Take both. */ + a = tal_strdup(ctx, "([a-z]+)"); + ok1(tal_strreg(ctx, take(tal_strdup(ctx, "hello world!")), + take(a), &b, invalid) == true); + ok1(streq(b, "hello")); + ok1(tal_parent(b) == ctx); + tal_free(b); + ok1(no_children(ctx)); + + /* ... even if we fail to match. */ + a = tal_strdup(ctx, "([a-z]+)"); + ok1(tal_strreg(ctx, take(tal_strdup(ctx, "HELLO WORLD!")), + take(a), &b, invalid) == false); + ok1(no_children(ctx)); + tal_free(ctx); + + /* Don't get fooled by \(! */ + ok1(tal_strreg(ctx, "(hello) (world)!", "\\([a-z]*\\) \\([a-z]+\\)", + invalid) == true); + + return exit_status(); +} diff --git a/ccan/tal/str/test/run-take.c b/ccan/tal/str/test/run-take.c new file mode 100644 index 0000000..edf173f --- /dev/null +++ b/ccan/tal/str/test/run-take.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include "helper.h" + +int main(void) +{ + char *parent, *c; + + plan_tests(14); + + parent = tal(NULL, char); + ok1(parent); + + c = tal_strdup(parent, "hello"); + + c = tal_strdup(parent, take(c)); + ok1(strcmp(c, "hello") == 0); + ok1(tal_parent(c) == parent); + + c = tal_strndup(parent, take(c), 5); + ok1(strcmp(c, "hello") == 0); + ok1(tal_parent(c) == parent); + + c = tal_strndup(parent, take(c), 3); + ok1(strcmp(c, "hel") == 0); + ok1(tal_parent(c) == parent); + tal_free(c); + + c = tal_strdup(parent, "hello %s"); + c = tal_fmt(parent, take(c), "there"); + ok1(strcmp(c, "hello there") == 0); + ok1(tal_parent(c) == parent); + /* No leftover allocations. */ + tal_free(c); + ok1(no_children(parent)); + + tal_free(parent); + ok1(!taken_any()); + + /* NULL pass-through. */ + c = NULL; + ok1(tal_strdup(NULL, take(c)) == NULL); + ok1(tal_strndup(NULL, take(c), 5) == NULL); + ok1(tal_fmt(NULL, take(c), 0) == NULL); + + return exit_status(); +} diff --git a/ccan/tal/str/test/run.c b/ccan/tal/str/test/run.c new file mode 100644 index 0000000..a59d940 --- /dev/null +++ b/ccan/tal/str/test/run.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include "helper.h" + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) + +static const char *substrings[] += { "far", "bar", "baz", "b", "ba", "z", "ar", NULL }; + +int main(void) +{ + char **split, *str; + void *ctx; + + plan_tests(69); + split = tal_strsplit(NULL, "hello world", " ", STR_EMPTY_OK); + ok1(!strcmp(split[0], "hello")); + ok1(!strcmp(split[1], "")); + ok1(!strcmp(split[2], "world")); + ok1(split[3] == NULL); + ok1(tal_count(split) == 4); + tal_free(split); + + split = tal_strsplit(NULL, "hello world", " ", STR_NO_EMPTY); + ok1(!strcmp(split[0], "hello")); + ok1(!strcmp(split[1], "world")); + ok1(split[2] == NULL); + ok1(tal_count(split) == 3); + tal_free(split); + + split = tal_strsplit(NULL, " hello world", " ", STR_NO_EMPTY); + ok1(!strcmp(split[0], "hello")); + ok1(!strcmp(split[1], "world")); + ok1(split[2] == NULL); + ok1(tal_count(split) == 3); + tal_free(split); + + split = tal_strsplit(NULL, "hello world", "o ", STR_EMPTY_OK); + ok1(!strcmp(split[0], "hell")); + ok1(!strcmp(split[1], "")); + ok1(!strcmp(split[2], "")); + ok1(!strcmp(split[3], "w")); + ok1(!strcmp(split[4], "rld")); + ok1(split[5] == NULL); + ok1(tal_count(split) == 6); + + ctx = split; + split = tal_strsplit(ctx, "hello world", "o ", STR_EMPTY_OK); + ok1(tal_parent(split) == ctx); + tal_free(ctx); + + str = tal_strjoin(NULL, (char **)substrings, ", ", STR_TRAIL); + ok1(!strcmp(str, "far, bar, baz, b, ba, z, ar, ")); + ctx = str; + str = tal_strjoin(ctx, (char **)substrings, "", STR_TRAIL); + ok1(!strcmp(str, "farbarbazbbazar")); + ok1(tal_parent(str) == ctx); + str = tal_strjoin(ctx, (char **)substrings, ", ", STR_NO_TRAIL); + ok1(tal_parent(str) == ctx); + ok1(!strcmp(str, "far, bar, baz, b, ba, z, ar")); + str = tal_strjoin(ctx, (char **)substrings, "", STR_NO_TRAIL); + ok1(!strcmp(str, "farbarbazbbazar")); + ok1(tal_parent(str) == ctx); + tal_free(ctx); + + ctx = tal_strdup(NULL, "context"); + /* Pass through NULLs from take. */ + ok1(tal_strsplit(NULL, take(NULL), " ", STR_EMPTY_OK) == NULL); + ok1(tal_strsplit(NULL, "foo", take(NULL), STR_EMPTY_OK) == NULL); + + /* tal_strsplit take string. It reallocs it to same size, but + * that sometimes causes a move, so we can't directly check + * that split[0] == str. */ + str = tal_strdup(ctx, "hello world"); + ok1(tal_check(ctx, NULL)); + ok1(tal_check(str, NULL)); + split = tal_strsplit(ctx, take(str), " ", STR_EMPTY_OK); + ok1(tal_parent(split) == ctx); + ok1(!strcmp(split[0], "hello")); + ok1(!strcmp(split[1], "world")); + ok1(split[2] == NULL); + ok1(tal_check(split, NULL)); + ok1(tal_check(ctx, NULL)); + tal_free(split); + /* Previous free should get rid of str */ + ok1(no_children(ctx)); + + /* tal_strsplit take delims */ + str = tal_strdup(ctx, " "); + split = tal_strsplit(ctx, "hello world", take(str), STR_EMPTY_OK); + ok1(tal_parent(split) == ctx); + ok1(!strcmp(split[0], "hello")); + ok1(!strcmp(split[1], "world")); + ok1(split[2] == NULL); + ok1(tal_check(split, NULL)); + ok1(tal_check(ctx, NULL)); + tal_free(split); + /* str is gone... */ + ok1(no_children(ctx)); + + /* tal_strsplit takes both. */ + split = tal_strsplit(ctx, take(tal_strdup(NULL, "hello world")), + take(tal_strdup(NULL, " ")), STR_EMPTY_OK); + ok1(tal_parent(split) == ctx); + ok1(!strcmp(split[0], "hello")); + ok1(!strcmp(split[1], "world")); + ok1(split[2] == NULL); + ok1(tal_check(split, NULL)); + ok1(tal_check(ctx, NULL)); + tal_free(split); + /* temp allocs are gone... */ + ok1(no_children(ctx)); + + /* tal_strjoin passthrough taken NULLs OK. */ + ok1(tal_strjoin(ctx, take(NULL), "", STR_TRAIL) == NULL); + ok1(tal_strjoin(ctx, take(NULL), "", STR_NO_TRAIL) == NULL); + ok1(tal_strjoin(ctx, split, take(NULL), STR_TRAIL) == NULL); + ok1(tal_strjoin(ctx, split, take(NULL), STR_NO_TRAIL) == NULL); + + /* tal_strjoin take strings[] */ + split = tal_strsplit(ctx, "hello world", " ", STR_EMPTY_OK); + str = tal_strjoin(ctx, take(split), " there ", STR_NO_TRAIL); + ok1(!strcmp(str, "hello there world")); + ok1(tal_parent(str) == ctx); + /* split is gone... */ + ok1(single_child(ctx, str)); + tal_free(str); + ok1(no_children(ctx)); + + /* tal_strjoin take delim */ + split = tal_strsplit(ctx, "hello world", " ", STR_EMPTY_OK); + str = tal_strjoin(ctx, split, take(tal_strdup(ctx, " there ")), + STR_NO_TRAIL); + ok1(!strcmp(str, "hello there world")); + ok1(tal_parent(str) == ctx); + tal_free(split); + /* tmp alloc is gone, str is only remainder. */ + ok1(single_child(ctx, str)); + tal_free(str); + ok1(no_children(ctx)); + + /* tal_strjoin take both. */ + str = tal_strjoin(ctx, take(tal_strsplit(ctx, "hello world", " ", + STR_EMPTY_OK)), + take(tal_strdup(ctx, " there ")), STR_NO_TRAIL); + ok1(!strcmp(str, "hello there world")); + ok1(tal_parent(str) == ctx); + /* tmp allocs are gone, str is only remainder. */ + ok1(single_child(ctx, str)); + tal_free(str); + ok1(no_children(ctx)); + tal_free(ctx); + + return exit_status(); +} -- cgit v1.2.3