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; +} | 
