aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2025-01-31 19:59:22 +0100
committerMattias Andrée <m@maandree.se>2025-01-31 19:59:22 +0100
commit66ff79748a73888b802bab4866b350989a48a136 (patch)
tree0c194581586468f3f8630e55bc83ef04d989ca80
parentFix some mistakes (diff)
downloadlibenv-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>
-rw-r--r--.gitignore1
-rw-r--r--Makefile13
-rw-r--r--common.h3
-rw-r--r--libenv_filter_name_list.c3
-rw-r--r--libenv_filter_name_list_with_dealloc.c3
-rw-r--r--libenv_filter_variable_list.36
-rw-r--r--libenv_filter_variable_list.c3
-rw-r--r--libenv_filter_variable_list_with_dealloc.c3
-rw-r--r--libenv_get_chosen_list.c3
-rw-r--r--libenv_get_complete_list.c10
-rw-r--r--libenv_select_name_list.c3
-rw-r--r--libenv_select_name_list_with_dealloc.c3
-rw-r--r--libenv_select_variable_list.38
-rw-r--r--libenv_select_variable_list.c3
-rw-r--r--libenv_select_variable_list_with_dealloc.c3
-rw-r--r--libenv_vfilter_name_list.c3
-rw-r--r--libenv_vfilter_name_list_with_dealloc.c3
-rw-r--r--libenv_vfilter_variable_list.c3
-rw-r--r--libenv_vfilter_variable_list_with_dealloc.c3
-rw-r--r--libenv_vget_chosen_list.c4
-rw-r--r--libenv_vprocess_list__.c13
-rw-r--r--libenv_vselect_name_list.c3
-rw-r--r--libenv_vselect_name_list_with_dealloc.c3
-rw-r--r--libenv_vselect_variable_list.c3
-rw-r--r--libenv_vselect_variable_list_with_dealloc.c3
-rw-r--r--test.c235
26 files changed, 270 insertions, 74 deletions
diff --git a/.gitignore b/.gitignore
index a071ed4..c2c489c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@
*.gcov
*.gcno
*.gcda
+/test
diff --git a/Makefile b/Makefile
index 18d3ff1..e94edb7 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/common.h b/common.h
index 02af2a1..5d4cce2 100644
--- a/common.h
+++ b/common.h
@@ -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 */
diff --git a/test.c b/test.c
new file mode 100644
index 0000000..5a5017e
--- /dev/null
+++ b/test.c
@@ -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;
+}