diff options
author | Mattias Andrée <m@maandree.se> | 2025-01-31 19:59:22 +0100 |
---|---|---|
committer | Mattias Andrée <m@maandree.se> | 2025-01-31 19:59:22 +0100 |
commit | 66ff79748a73888b802bab4866b350989a48a136 (patch) | |
tree | 0c194581586468f3f8630e55bc83ef04d989ca80 | |
parent | Fix some mistakes (diff) | |
download | libenv-66ff79748a73888b802bab4866b350989a48a136.tar.gz libenv-66ff79748a73888b802bab4866b350989a48a136.tar.bz2 libenv-66ff79748a73888b802bab4866b350989a48a136.tar.xz |
Fix mistakes and add tests
Signed-off-by: Mattias Andrée <m@maandree.se>
26 files changed, 270 insertions, 74 deletions
@@ -12,3 +12,4 @@ *.gcov *.gcno *.gcda +/test @@ -65,9 +65,10 @@ MAN7 =\ LOBJ = $(OBJ:.o=.lo) -all: libenv.a libenv.$(LIBEXT) +all: libenv.a libenv.$(LIBEXT) test $(OBJ): $(HDR) $(LOBJ): $(HDR) +test.o: libenv_get_complete_list.c $(HDR) .c.o: $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) @@ -83,6 +84,12 @@ libenv.a: $(OBJ) libenv.$(LIBEXT): $(LOBJ) $(CC) $(LIBFLAGS) -o $@ $(LOBJ) $(LDFLAGS) +test: test.o $(OBJ_TESTABLE) + $(CC) -o $@ test.o $(OBJ_TESTABLE) $(LDFLAGS) + +check: test + $(CHECK_PREFIX) ./test + install: libenv.a libenv.$(LIBEXT) mkdir -p -- "$(DESTDIR)$(PREFIX)/lib" mkdir -p -- "$(DESTDIR)$(PREFIX)/include" @@ -108,9 +115,9 @@ uninstall: clean: -rm -f -- *.o *.a *.lo *.su *.so *.so.* *.dll *.dylib - -rm -f -- *.gch *.gcov *.gcno *.gcda *.$(LIBEXT) + -rm -f -- *.gch *.gcov *.gcno *.gcda *.$(LIBEXT) test .SUFFIXES: .SUFFIXES: .lo .o .c -.PHONY: all install uninstall clean +.PHONY: all check install uninstall clean @@ -3,6 +3,9 @@ #include <stdlib.h> +#define NCLASSWORDS 1U + + #define HAVE_HEAD 1 #define NO_HEAD 0 diff --git a/libenv_filter_name_list.c b/libenv_filter_name_list.c index bfcf3a2..c036390 100644 --- a/libenv_filter_name_list.c +++ b/libenv_filter_name_list.c @@ -10,6 +10,3 @@ libenv_filter_name_list(const char **variables, ...) return libenv_vfilter_name_list(variables, classes); va_end(classes); } - - -/* TODO test */ diff --git a/libenv_filter_name_list_with_dealloc.c b/libenv_filter_name_list_with_dealloc.c index 986be3b..619d5ea 100644 --- a/libenv_filter_name_list_with_dealloc.c +++ b/libenv_filter_name_list_with_dealloc.c @@ -10,6 +10,3 @@ libenv_filter_name_list_with_dealloc(char **variables, ...) return libenv_vfilter_name_list_with_dealloc(variables, classes); va_end(classes); } - - -/* TODO test */ diff --git a/libenv_filter_variable_list.3 b/libenv_filter_variable_list.3 index 132cb28..c9dc8d7 100644 --- a/libenv_filter_variable_list.3 +++ b/libenv_filter_variable_list.3 @@ -20,10 +20,10 @@ The .BR libenv_filter_variable_list () function removes elements in .I variables -that match the name, optionally with an equals sign +that match the name, with an equals sign .RB ( = ) -followed by anything, of an environment variable that -belong to all the environment variable classes listed +afterward followed by anything, of an environment variable +that belong to all the environment variable classes listed after the .I variables argument. The list must end with diff --git a/libenv_filter_variable_list.c b/libenv_filter_variable_list.c index fa02ef9..3c1d1cd 100644 --- a/libenv_filter_variable_list.c +++ b/libenv_filter_variable_list.c @@ -10,6 +10,3 @@ libenv_filter_variable_list(const char **variables, ...) return libenv_vfilter_variable_list(variables, classes); va_end(classes); } - - -/* TODO test */ diff --git a/libenv_filter_variable_list_with_dealloc.c b/libenv_filter_variable_list_with_dealloc.c index 6332659..7ff303b 100644 --- a/libenv_filter_variable_list_with_dealloc.c +++ b/libenv_filter_variable_list_with_dealloc.c @@ -10,6 +10,3 @@ libenv_filter_variable_list_with_dealloc(char **variables, ...) return libenv_vfilter_variable_list_with_dealloc(variables, classes); va_end(classes); } - - -/* TODO test */ diff --git a/libenv_get_chosen_list.c b/libenv_get_chosen_list.c index f4975fd..1940985 100644 --- a/libenv_get_chosen_list.c +++ b/libenv_get_chosen_list.c @@ -10,6 +10,3 @@ libenv_get_chosen_list(enum libenv_class classes_head, ...) return libenv_vget_chosen_list(classes_head, classes_tail); va_end(classes_tail); } - - -/* TODO test */ diff --git a/libenv_get_complete_list.c b/libenv_get_complete_list.c index 9a542c9..e40ed91 100644 --- a/libenv_get_complete_list.c +++ b/libenv_get_complete_list.c @@ -1,8 +1,7 @@ /* See LICENSE file for copyright and license details. */ +#ifndef TEST_C #include "common.h" -#define NCLASSWORDS 1U - #define _(E) ((uint64_t)1 << (E)) @@ -48,10 +47,11 @@ DECLARE(classes__exec__path, _(LIBENV_EXEC) | SU_SAFE | LOGIN_UNSAFE | PATH); #undef REMOTE_UNSAFE #undef PATH #undef DECLARE + #define V(S) {S, CLASSES} -static struct libenv_variable list[] = { +static struct libenv_variable list[] = { /* TODO validate */ #define CLASSES classes__display V("DISPLAY"), @@ -199,9 +199,11 @@ static struct libenv_variable list[] = { #undef V +#endif + const struct libenv_variable * -libenv_get_complete_list(size_t *nclasswords_out, size_t *count_out) /* TODO test */ +libenv_get_complete_list(size_t *nclasswords_out, size_t *count_out) { if (nclasswords_out) *nclasswords_out = NCLASSWORDS; diff --git a/libenv_select_name_list.c b/libenv_select_name_list.c index 705e499..b71afd9 100644 --- a/libenv_select_name_list.c +++ b/libenv_select_name_list.c @@ -10,6 +10,3 @@ libenv_select_name_list(const char **variables, ...) return libenv_vselect_name_list(variables, classes); va_end(classes); } - - -/* TODO test */ diff --git a/libenv_select_name_list_with_dealloc.c b/libenv_select_name_list_with_dealloc.c index b6bc0ca..4e23a11 100644 --- a/libenv_select_name_list_with_dealloc.c +++ b/libenv_select_name_list_with_dealloc.c @@ -10,6 +10,3 @@ libenv_select_name_list_with_dealloc(char **variables, ...) return libenv_vselect_name_list_with_dealloc(variables, classes); va_end(classes); } - - -/* TODO test */ diff --git a/libenv_select_variable_list.3 b/libenv_select_variable_list.3 index b38950f..a03a053 100644 --- a/libenv_select_variable_list.3 +++ b/libenv_select_variable_list.3 @@ -20,11 +20,11 @@ The .BR libenv_select_variable_list () function removes elements in .I variables -that match the name, optionally with an equals sign +that match the name, with an equals sign .RB ( = ) -followed by anything, of an environment variable that -do not belong to any of the environment variable classes -listed after the +afterward followed by anything, of an environment variable +that do not belong to any of the environment variable +classes listed after the .I variables argument. The list must end with .I LIBENV_END diff --git a/libenv_select_variable_list.c b/libenv_select_variable_list.c index ff902af..41ed67e 100644 --- a/libenv_select_variable_list.c +++ b/libenv_select_variable_list.c @@ -10,6 +10,3 @@ libenv_select_variable_list(const char **variables, ...) return libenv_vselect_variable_list(variables, classes); va_end(classes); } - - -/* TODO test */ diff --git a/libenv_select_variable_list_with_dealloc.c b/libenv_select_variable_list_with_dealloc.c index 0018577..935739b 100644 --- a/libenv_select_variable_list_with_dealloc.c +++ b/libenv_select_variable_list_with_dealloc.c @@ -10,6 +10,3 @@ libenv_select_variable_list_with_dealloc(char **variables, ...) return libenv_vselect_variable_list_with_dealloc(variables, classes); va_end(classes); } - - -/* TODO test */ diff --git a/libenv_vfilter_name_list.c b/libenv_vfilter_name_list.c index 7ed841a..7985f82 100644 --- a/libenv_vfilter_name_list.c +++ b/libenv_vfilter_name_list.c @@ -7,6 +7,3 @@ libenv_vfilter_name_list(const char **variables, va_list classes) { return libenv_vprocess_list_without_dealloc__(variables, 0, classes, NO_HEAD, NAMES, FILTER); } - - -/* TODO test */ diff --git a/libenv_vfilter_name_list_with_dealloc.c b/libenv_vfilter_name_list_with_dealloc.c index 5140c57..1719acc 100644 --- a/libenv_vfilter_name_list_with_dealloc.c +++ b/libenv_vfilter_name_list_with_dealloc.c @@ -7,6 +7,3 @@ libenv_vfilter_name_list_with_dealloc(char **variables, va_list classes) { return libenv_vprocess_list_with_dealloc__(variables, 0, classes, NO_HEAD, NAMES, FILTER); } - - -/* TODO test */ diff --git a/libenv_vfilter_variable_list.c b/libenv_vfilter_variable_list.c index 6e8f371..bf53a3b 100644 --- a/libenv_vfilter_variable_list.c +++ b/libenv_vfilter_variable_list.c @@ -7,6 +7,3 @@ libenv_vfilter_variable_list(const char **variables, va_list classes) { return libenv_vprocess_list_without_dealloc__(variables, 0, classes, NO_HEAD, VARIABLES, FILTER); } - - -/* TODO test */ diff --git a/libenv_vfilter_variable_list_with_dealloc.c b/libenv_vfilter_variable_list_with_dealloc.c index 65431db..0c738da 100644 --- a/libenv_vfilter_variable_list_with_dealloc.c +++ b/libenv_vfilter_variable_list_with_dealloc.c @@ -7,6 +7,3 @@ libenv_vfilter_variable_list_with_dealloc(char **variables, va_list classes) { return libenv_vprocess_list_with_dealloc__(variables, 0, classes, NO_HEAD, VARIABLES, FILTER); } - - -/* TODO test */ diff --git a/libenv_vget_chosen_list.c b/libenv_vget_chosen_list.c index 2a5e1e6..59a3ebd 100644 --- a/libenv_vget_chosen_list.c +++ b/libenv_vget_chosen_list.c @@ -15,9 +15,7 @@ libenv_vget_chosen_list(enum libenv_class classes_head, va_list classes_tail) return NULL; for (i = 0; i < count; i++) names[i] = vars[i].name; + names[count] = NULL; libenv_vprocess_list_without_dealloc__(names, classes_head, classes_tail, HAVE_HEAD, NAMES, SELECT); return names; } - - -/* TODO test */ diff --git a/libenv_vprocess_list__.c b/libenv_vprocess_list__.c index b590d4b..1eb211f 100644 --- a/libenv_vprocess_list__.c +++ b/libenv_vprocess_list__.c @@ -8,15 +8,14 @@ matches(const char *var, const struct libenv_variable *known, int is_name_only, { size_t i, w, b; for (; known->name; known++) { - for (i = 0;; i++) + for (i = 0; known->name[i]; i++) if (var[i] != known->name[i]) - break; - if (known->name[i]) - continue; + goto next; if (var[i] == (is_name_only ? '\0' : '=')) goto found; + next:; } - return 0; + return all && !classes_head; found: for (; classes_head; classes_head = va_arg(classes_tail, enum libenv_class)) { @@ -51,8 +50,10 @@ libenv_vprocess_list__(void *variables_, enum libenv_class classes_head, va_list known = libenv_get_complete_list(&nclasswords, NULL); for (i = 0; variables[i]; i++) { + int match; va_copy(classes_tail_2, classes_tail); - if (filter ^ matches(variables[i], known, names, classes_head, classes_tail_2, all, nclasswords)) + match = matches(variables[i], known, names, classes_head, classes_tail_2, all, nclasswords); + if (filter ^ match) variables[n++] = variables[i]; else if (dealloc) free(variables[i]); diff --git a/libenv_vselect_name_list.c b/libenv_vselect_name_list.c index 5eef51e..3e1726d 100644 --- a/libenv_vselect_name_list.c +++ b/libenv_vselect_name_list.c @@ -7,6 +7,3 @@ libenv_vselect_name_list(const char **variables, va_list classes) { return libenv_vprocess_list_without_dealloc__(variables, 0, classes, NO_HEAD, NAMES, SELECT); } - - -/* TODO test */ diff --git a/libenv_vselect_name_list_with_dealloc.c b/libenv_vselect_name_list_with_dealloc.c index 95f35ed..6c66019 100644 --- a/libenv_vselect_name_list_with_dealloc.c +++ b/libenv_vselect_name_list_with_dealloc.c @@ -7,6 +7,3 @@ libenv_vselect_name_list_with_dealloc(char **variables, va_list classes) { return libenv_vprocess_list_with_dealloc__(variables, 0, classes, NO_HEAD, NAMES, SELECT); } - - -/* TODO test */ diff --git a/libenv_vselect_variable_list.c b/libenv_vselect_variable_list.c index 0e57710..44c50f5 100644 --- a/libenv_vselect_variable_list.c +++ b/libenv_vselect_variable_list.c @@ -7,6 +7,3 @@ libenv_vselect_variable_list(const char **variables, va_list classes) { return libenv_vprocess_list_without_dealloc__(variables, 0, classes, NO_HEAD, VARIABLES, SELECT); } - - -/* TODO test */ diff --git a/libenv_vselect_variable_list_with_dealloc.c b/libenv_vselect_variable_list_with_dealloc.c index cec9d7a..3430f57 100644 --- a/libenv_vselect_variable_list_with_dealloc.c +++ b/libenv_vselect_variable_list_with_dealloc.c @@ -7,6 +7,3 @@ libenv_vselect_variable_list_with_dealloc(char **variables, va_list classes) { return libenv_vprocess_list_with_dealloc__(variables, 0, classes, NO_HEAD, VARIABLES, SELECT); } - - -/* TODO test */ @@ -0,0 +1,235 @@ +/* See LICENSE file for copyright and license details. */ +#define TEST_C +#include "common.h" +#include <assert.h> /* TODO improve output */ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + + +static uint64_t classes_1 = (1 << 1); +static uint64_t classes_1_2 = (1 << 1) | (1 << 2); +static uint64_t classes_1_2_3 = (1 << 1) | (1 << 2) | (1 << 3); +static uint64_t classes_2 = (1 << 2); + +static struct libenv_variable list[] = { + {"a", &classes_1}, + {"aa", &classes_1_2}, + {"BB", &classes_1_2_3}, + {"bb", &classes_2}, + {"b", &classes_1}, + {NULL, NULL} +}; + +#include "libenv_get_complete_list.c" + + +union list_process_function { + size_t (*dyn)(char **, ...); + size_t (*cnst)(const char **, ...); +}; + + +static void +dealloc(char **strings) +{ + size_t i; + for (i = 0; strings[i]; i++) + free(strings[i]); +} + + +static void +check(size_t count, char **strings, ...) +{ + size_t i, len; + const char *expect; + va_list args; + va_start(args, strings); + for (i = 0; (expect = va_arg(args, const char *)); i++) { + len = strlen(expect); + assert(strings[i]); + assert(!strncmp(strings[i], expect, len)); + assert(!strings[i][len] || strings[i][len] == '='); + } + va_end(args); + assert(!strings[i]); + assert(count == i); +} + + +#define CHECK(CALL, ...)\ + do {\ + char *strings[8];\ + char *allocations[8];\ + size_t i;\ + char *p;\ + assert(strings[0] = allocations[0] = strdup("a="));\ + assert(strings[1] = allocations[1] = strdup("aa=1"));\ + assert(strings[2] = allocations[2] = strdup("b=12"));\ + assert(strings[3] = allocations[3] = strdup("bb=34"));\ + assert(strings[4] = allocations[4] = strdup("BB"));\ + assert(strings[5] = allocations[5] = strdup("x=5"));\ + assert(strings[6] = allocations[6] = strdup("xx"));\ + strings[7] = allocations[7] = NULL;\ + if (!variable_version) {\ + for (i = 0; strings[i]; i++) {\ + for (p = strings[i]; *p && *p != '='; p++);\ + *p = '\0';\ + }\ + }\ + check(CALL, strings, __VA_ARGS__);\ + dealloc(dealloc_version ? strings : allocations);\ + } while (0) + + +static void +test_filter(int dealloc_version, int variable_version, const union list_process_function *function) +{ + CHECK((*function->dyn)(strings, LIBENV_END), NULL); /* each contain all of nothing, so remove all */ + if (!variable_version) { + CHECK((*function->dyn)(strings, 3, LIBENV_END), "a", "aa", "b", "bb", "x", "xx", NULL); + CHECK((*function->dyn)(strings, 2, LIBENV_END), "a", "b", "x", "xx", NULL); + CHECK((*function->dyn)(strings, 1, 2, 3, LIBENV_END), "a", "aa", "b", "bb", "x", "xx", NULL); + CHECK((*function->dyn)(strings, 1, 2, LIBENV_END), "a", "b", "bb", "x", "xx", NULL); + } else { + CHECK((*function->dyn)(strings, 3, LIBENV_END), "a", "aa", "b", "bb", "BB", "x", "xx", NULL); + CHECK((*function->dyn)(strings, 2, LIBENV_END), "a", "b", "BB", "x", "xx", NULL); + CHECK((*function->dyn)(strings, 1, 2, 3, LIBENV_END), "a", "aa", "b", "bb", "BB", "x", "xx", NULL); + CHECK((*function->dyn)(strings, 1, 2, LIBENV_END), "a", "b", "bb", "BB", "x", "xx", NULL); + } + CHECK((*function->dyn)(strings, 10, LIBENV_END), "a", "aa", "b", "bb", "BB", "x", "xx", NULL); + CHECK((*function->dyn)(strings, 64, LIBENV_END), "a", "aa", "b", "bb", "BB", "x", "xx", NULL); + CHECK((*function->dyn)(strings, 100000, LIBENV_END), "a", "aa", "b", "bb", "BB", "x", "xx", NULL); +} + + +static void +test_select(int dealloc_version, int variable_version, const union list_process_function *function) +{ + const char *BB = variable_version ? NULL : "BB"; + CHECK((*function->dyn)(strings, LIBENV_END), NULL); /* none contain any of nothing, so select all */ + CHECK((*function->dyn)(strings, 3, LIBENV_END), BB, NULL); + CHECK((*function->dyn)(strings, 2, LIBENV_END), "aa", "bb", BB, NULL); + CHECK((*function->dyn)(strings, 1, 2, 3, LIBENV_END), "a", "aa", "b", "bb", BB, NULL); + CHECK((*function->dyn)(strings, 1, 2, LIBENV_END), "a", "aa", "b", "bb", BB, NULL); + CHECK((*function->dyn)(strings, 1, 3, LIBENV_END), "a", "aa", "b", BB, NULL); + CHECK((*function->dyn)(strings, 10, LIBENV_END), NULL); + CHECK((*function->dyn)(strings, 64, LIBENV_END), NULL); + CHECK((*function->dyn)(strings, 100000, LIBENV_END), NULL); +} + + +#undef CHECK + + +static void +test_get_chosen_list(void) /* TODO check memory failure behaviour */ +{ + const char **r; + + assert(r = libenv_get_chosen_list(LIBENV_END)); + assert(!r[0]); + free(r); + + assert(r = libenv_get_chosen_list(1, LIBENV_END)); + assert(r[0] && !strcmp(r[0], "a")); + assert(r[1] && !strcmp(r[1], "aa")); + assert(r[2] && !strcmp(r[2], "BB")); + assert(r[3] && !strcmp(r[3], "b")); + assert(!r[4]); + free(r); + + assert(r = libenv_get_chosen_list(2, LIBENV_END)); + assert(r[0] && !strcmp(r[0], "aa")); + assert(r[1] && !strcmp(r[1], "BB")); + assert(r[2] && !strcmp(r[2], "bb")); + assert(!r[3]); + free(r); + + assert(r = libenv_get_chosen_list(3, LIBENV_END)); + assert(r[0] && !strcmp(r[0], "BB")); + assert(!r[1]); + free(r); + + assert(r = libenv_get_chosen_list(1, 2, LIBENV_END)); + assert(r[0] && !strcmp(r[0], "a")); + assert(r[1] && !strcmp(r[1], "aa")); + assert(r[2] && !strcmp(r[2], "BB")); + assert(r[3] && !strcmp(r[3], "bb")); + assert(r[4] && !strcmp(r[4], "b")); + assert(!r[5]); + free(r); + + assert(r = libenv_get_chosen_list(2, 3, LIBENV_END)); + assert(r[0] && !strcmp(r[0], "aa")); + assert(r[1] && !strcmp(r[1], "BB")); + assert(r[2] && !strcmp(r[2], "bb")); + assert(!r[3]); + free(r); + + assert(r = libenv_get_chosen_list(3, 1, LIBENV_END)); + assert(r[0] && !strcmp(r[0], "a")); + assert(r[1] && !strcmp(r[1], "aa")); + assert(r[2] && !strcmp(r[2], "BB")); + assert(r[3] && !strcmp(r[3], "b")); + assert(!r[4]); + free(r); + + assert(r = libenv_get_chosen_list(1, 2, 3, LIBENV_END)); + assert(r[0] && !strcmp(r[0], "a")); + assert(r[1] && !strcmp(r[1], "aa")); + assert(r[2] && !strcmp(r[2], "BB")); + assert(r[3] && !strcmp(r[3], "bb")); + assert(r[4] && !strcmp(r[4], "b")); + assert(!r[5]); + free(r); + + assert(r = libenv_get_chosen_list(10, LIBENV_END)); + assert(!r[0]); + free(r); + + assert(r = libenv_get_chosen_list(64, LIBENV_END)); + assert(!r[0]); + free(r); + + assert(r = libenv_get_chosen_list(1000, LIBENV_END)); + assert(!r[0]); + free(r); +} + + +int +main(void) +{ + union list_process_function f; + + f.cnst = &libenv_filter_name_list; + test_filter(0, 0, &f); + + f.dyn = &libenv_filter_name_list_with_dealloc; + test_filter(1, 0, &f); + + f.cnst = &libenv_filter_variable_list; + test_filter(0, 1, &f); + + f.dyn = &libenv_filter_variable_list_with_dealloc; + test_filter(1, 1, &f); + + f.cnst = &libenv_select_name_list; + test_select(0, 0, &f); + + f.dyn = &libenv_select_name_list_with_dealloc; + test_select(1, 0, &f); + + f.cnst = &libenv_select_variable_list; + test_select(0, 1, &f); + + f.dyn = &libenv_select_variable_list_with_dealloc; + test_select(1, 1, &f); + + test_get_chosen_list(); + + /* TODO check for memory leaks */ + return 0; +} |