aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile3
-rw-r--r--tests/src/test_lst.c458
2 files changed, 460 insertions, 1 deletions
diff --git a/tests/Makefile b/tests/Makefile
index 3fc0322..00f69b3 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -8,7 +8,8 @@ LIB = ../lib/libft.a
TESTS = test_strlen test_is test_mem test_cmp test_case test_strl test_search \
test_atoi test_alloc test_substr test_strjoin test_strtrim \
- test_split test_itoa test_strmapi test_striteri test_put
+ test_split test_itoa test_strmapi test_striteri test_put \
+ test_lst
BINS = $(TESTS:%=$(BINDIR)/%)
diff --git a/tests/src/test_lst.c b/tests/src/test_lst.c
new file mode 100644
index 0000000..f4b6988
--- /dev/null
+++ b/tests/src/test_lst.c
@@ -0,0 +1,458 @@
+#include "libft.h"
+#include "test_utils.h"
+#include <ctype.h>
+
+/* ── helpers ─────────────────────────────────────────────────────── */
+
+static void
+_s_del (void *content)
+{
+ free (content);
+}
+
+static void
+_s_toupper_content (void *content)
+{
+ char *s;
+
+ s = content;
+ while (*s)
+ {
+ *s = toupper ((unsigned char)*s);
+ s++;
+ }
+}
+
+static void *
+_s_dup_content (void *content)
+{
+ return (strdup (content));
+}
+
+/** Build a list of @p n nodes, each containing strdup'd decimal string. */
+static t_list *
+_s_build_list (int n)
+{
+ t_list *lst;
+ char buf[32];
+ int i;
+
+ lst = NULL;
+ for (i = 0; i < n; i++)
+ {
+ snprintf (buf, sizeof (buf), "%d", i);
+ ft_lstadd_back (&lst, ft_lstnew (strdup (buf)));
+ }
+ return (lst);
+}
+
+/* ── ft_lstnew ───────────────────────────────────────────────────── */
+
+static void
+_s_test_lstnew (void)
+{
+ _s_section ("ft_lstnew");
+
+ /* basic */
+ {
+ char *s = strdup ("hello");
+ t_list *n = ft_lstnew (s);
+ _s_check ("content set", n && n->content == s);
+ _s_check ("next NULL", n && n->next == NULL);
+ free (s);
+ free (n);
+ }
+
+ /* NULL content is valid */
+ {
+ t_list *n = ft_lstnew (NULL);
+ _s_check ("NULL content ok", n && n->content == NULL);
+ _s_check ("NULL content next", n && n->next == NULL);
+ free (n);
+ }
+}
+
+/* ── ft_lstadd_front ─────────────────────────────────────────────── */
+
+static void
+_s_test_lstadd_front (void)
+{
+ int i;
+
+ _s_section ("ft_lstadd_front");
+
+ /* prepend to empty list */
+ {
+ t_list *lst = NULL;
+ t_list *n = ft_lstnew (strdup ("first"));
+ ft_lstadd_front (&lst, n);
+ _s_check ("empty→head", lst == n);
+ _s_check ("empty→next NULL", lst->next == NULL);
+ ft_lstclear (&lst, _s_del);
+ }
+
+ /* prepend to non-empty */
+ {
+ t_list *lst = ft_lstnew (strdup ("second"));
+ t_list *old = lst;
+ t_list *n = ft_lstnew (strdup ("first"));
+ ft_lstadd_front (&lst, n);
+ _s_check ("new head", lst == n);
+ _s_check ("old follows", lst->next == old);
+ ft_lstclear (&lst, _s_del);
+ }
+
+ /* randomized: build by prepending, verify reverse order */
+ for (i = 0; i < _S_RAND_ITERS; i++)
+ {
+ int count = rand () % 20 + 2;
+ t_list *lst = NULL;
+ t_list *cur;
+ int j;
+ int ok;
+
+ for (j = 0; j < count; j++)
+ {
+ char buf[32];
+ snprintf (buf, sizeof (buf), "%d", j);
+ ft_lstadd_front (&lst, ft_lstnew (strdup (buf)));
+ }
+ /* first node should contain the highest index */
+ ok = 1;
+ cur = lst;
+ for (j = count - 1; j >= 0; j--)
+ {
+ char buf[32];
+ snprintf (buf, sizeof (buf), "%d", j);
+ if (!cur || strcmp (cur->content, buf) != 0)
+ {
+ ok = 0;
+ break;
+ }
+ cur = cur->next;
+ }
+ _s_check ("prepend order", ok);
+ ft_lstclear (&lst, _s_del);
+ }
+}
+
+/* ── ft_lstsize ──────────────────────────────────────────────────── */
+
+static void
+_s_test_lstsize (void)
+{
+ int i;
+ char label[64];
+
+ _s_section ("ft_lstsize");
+
+ _s_check_eq_int ("NULL→0", ft_lstsize (NULL), 0);
+
+ {
+ t_list *lst = ft_lstnew (NULL);
+ _s_check_eq_int ("single→1", ft_lstsize (lst), 1);
+ free (lst);
+ }
+
+ /* randomized */
+ for (i = 0; i < _S_RAND_ITERS; i++)
+ {
+ int count = rand () % 100 + 1;
+ t_list *lst = _s_build_list (count);
+ snprintf (label, sizeof (label), "size=%d", count);
+ _s_check_eq_int (label, ft_lstsize (lst), count);
+ ft_lstclear (&lst, _s_del);
+ }
+}
+
+/* ── ft_lstlast ──────────────────────────────────────────────────── */
+
+static void
+_s_test_lstlast (void)
+{
+ _s_section ("ft_lstlast");
+
+ _s_check ("NULL→NULL", ft_lstlast (NULL) == NULL);
+
+ /* single node */
+ {
+ t_list *lst = ft_lstnew (strdup ("only"));
+ t_list *last = ft_lstlast (lst);
+ _s_check ("single is last", last == lst);
+ _s_check ("last->next NULL", last->next == NULL);
+ ft_lstclear (&lst, _s_del);
+ }
+
+ /* multi node */
+ {
+ t_list *lst = _s_build_list (5);
+ t_list *last = ft_lstlast (lst);
+ _s_check ("last content", last && strcmp (last->content, "4") == 0);
+ _s_check ("last->next NULL", last && last->next == NULL);
+ ft_lstclear (&lst, _s_del);
+ }
+}
+
+/* ── ft_lstadd_back ──────────────────────────────────────────────── */
+
+static void
+_s_test_lstadd_back (void)
+{
+ int i;
+ char label[64];
+
+ _s_section ("ft_lstadd_back");
+
+ /* append to empty list */
+ {
+ t_list *lst = NULL;
+ t_list *n = ft_lstnew (strdup ("first"));
+ ft_lstadd_back (&lst, n);
+ _s_check ("empty→head", lst == n);
+ _s_check ("empty→next NULL", lst->next == NULL);
+ ft_lstclear (&lst, _s_del);
+ }
+
+ /* append to non-empty */
+ {
+ t_list *lst = ft_lstnew (strdup ("first"));
+ t_list *n = ft_lstnew (strdup ("second"));
+ ft_lstadd_back (&lst, n);
+ _s_check ("head unchanged", strcmp (lst->content, "first") == 0);
+ _s_check ("tail is new", lst->next == n);
+ ft_lstclear (&lst, _s_del);
+ }
+
+ /* randomized: build by appending, verify order */
+ for (i = 0; i < _S_RAND_ITERS; i++)
+ {
+ int count = rand () % 20 + 2;
+ t_list *lst = _s_build_list (count);
+ t_list *cur;
+ int j;
+ int ok;
+
+ ok = 1;
+ cur = lst;
+ for (j = 0; j < count; j++)
+ {
+ char buf[32];
+ snprintf (buf, sizeof (buf), "%d", j);
+ if (!cur || strcmp (cur->content, buf) != 0)
+ {
+ ok = 0;
+ break;
+ }
+ cur = cur->next;
+ }
+ snprintf (label, sizeof (label), "append order n=%d", count);
+ _s_check (label, ok);
+ ft_lstclear (&lst, _s_del);
+ }
+}
+
+/* ── ft_lstdelone ────────────────────────────────────────────────── */
+
+static void
+_s_test_lstdelone (void)
+{
+ _s_section ("ft_lstdelone");
+
+ /* does not free next */
+ {
+ t_list *a = ft_lstnew (strdup ("first"));
+ t_list *b = ft_lstnew (strdup ("second"));
+ a->next = b;
+ ft_lstdelone (a, _s_del);
+ /* b must still be accessible */
+ _s_check ("next survives", strcmp (b->content, "second") == 0);
+ ft_lstdelone (b, _s_del);
+ }
+
+ /* single node */
+ {
+ t_list *n = ft_lstnew (strdup ("only"));
+ ft_lstdelone (n, _s_del);
+ _s_check ("single delone ok", 1);
+ }
+}
+
+/* ── ft_lstclear ─────────────────────────────────────────────────── */
+
+static void
+_s_test_lstclear (void)
+{
+ int i;
+ char label[64];
+
+ _s_section ("ft_lstclear");
+
+ /* NULL list */
+ {
+ t_list *lst = NULL;
+ ft_lstclear (&lst, _s_del);
+ _s_check ("NULL clear safe", lst == NULL);
+ }
+
+ /* single */
+ {
+ t_list *lst = ft_lstnew (strdup ("only"));
+ ft_lstclear (&lst, _s_del);
+ _s_check ("single cleared", lst == NULL);
+ }
+
+ /* multi */
+ {
+ t_list *lst = _s_build_list (5);
+ ft_lstclear (&lst, _s_del);
+ _s_check ("multi cleared", lst == NULL);
+ }
+
+ /* randomized */
+ for (i = 0; i < _S_RAND_ITERS; i++)
+ {
+ int count = rand () % 50 + 1;
+ t_list *lst = _s_build_list (count);
+ ft_lstclear (&lst, _s_del);
+ snprintf (label, sizeof (label), "clear n=%d", count);
+ _s_check (label, lst == NULL);
+ }
+}
+
+/* ── ft_lstiter ──────────────────────────────────────────────────── */
+
+static void
+_s_test_lstiter (void)
+{
+ _s_section ("ft_lstiter");
+
+ /* NULL list does not crash */
+ ft_lstiter (NULL, _s_toupper_content);
+ _s_check ("NULL safe", 1);
+
+ /* apply toupper */
+ {
+ t_list *lst = NULL;
+ ft_lstadd_back (&lst, ft_lstnew (strdup ("hello")));
+ ft_lstadd_back (&lst, ft_lstnew (strdup ("world")));
+ ft_lstiter (lst, _s_toupper_content);
+ _s_check ("iter[0]", strcmp (lst->content, "HELLO") == 0);
+ _s_check ("iter[1]", strcmp (lst->next->content, "WORLD") == 0);
+ ft_lstclear (&lst, _s_del);
+ }
+
+ /* randomized: build list, iter toupper, verify */
+ {
+ int i;
+ for (i = 0; i < _S_RAND_ITERS; i++)
+ {
+ int count = rand () % 20 + 1;
+ t_list *lst = _s_build_list (count);
+ t_list *cur;
+ int ok;
+
+ ft_lstiter (lst, _s_toupper_content);
+ ok = 1;
+ cur = lst;
+ while (cur)
+ {
+ char *s = cur->content;
+ while (*s)
+ {
+ if (*s >= 'a' && *s <= 'z')
+ {
+ ok = 0;
+ break;
+ }
+ s++;
+ }
+ cur = cur->next;
+ }
+ _s_check ("iter toupper", ok);
+ ft_lstclear (&lst, _s_del);
+ }
+ }
+}
+
+/* ── ft_lstmap ───────────────────────────────────────────────────── */
+
+static void
+_s_test_lstmap (void)
+{
+ int i;
+
+ _s_section ("ft_lstmap");
+
+ /* NULL list */
+ {
+ t_list *res = ft_lstmap (NULL, _s_dup_content, _s_del);
+ _s_check ("NULL→NULL", res == NULL);
+ }
+
+ /* basic map (strdup) */
+ {
+ t_list *lst = NULL;
+ t_list *mapped;
+ ft_lstadd_back (&lst, ft_lstnew (strdup ("hello")));
+ ft_lstadd_back (&lst, ft_lstnew (strdup ("world")));
+ mapped = ft_lstmap (lst, _s_dup_content, _s_del);
+ _s_check ("map[0]", mapped && strcmp (mapped->content, "hello") == 0);
+ _s_check ("map[1]", mapped && mapped->next
+ && strcmp (mapped->next->content, "world") == 0);
+ /* original unchanged */
+ _s_check ("orig[0]", strcmp (lst->content, "hello") == 0);
+ /* independent nodes */
+ _s_check ("indep ptr", mapped->content != lst->content);
+ ft_lstclear (&lst, _s_del);
+ ft_lstclear (&mapped, _s_del);
+ }
+
+ /* randomized: build, map, verify same content but independent */
+ for (i = 0; i < _S_RAND_ITERS; i++)
+ {
+ int count = rand () % 20 + 1;
+ t_list *lst = _s_build_list (count);
+ t_list *mapped = ft_lstmap (lst, _s_dup_content, _s_del);
+ t_list *a;
+ t_list *b;
+ int ok;
+
+ ok = 1;
+ a = lst;
+ b = mapped;
+ while (a && b)
+ {
+ if (strcmp (a->content, b->content) != 0 || a->content == b->content)
+ {
+ ok = 0;
+ break;
+ }
+ a = a->next;
+ b = b->next;
+ }
+ if (a || b)
+ ok = 0;
+ _s_check ("map rand", ok);
+ ft_lstclear (&lst, _s_del);
+ ft_lstclear (&mapped, _s_del);
+ }
+}
+
+/* ── main ────────────────────────────────────────────────────────── */
+
+int
+main (void)
+{
+ srand (time (NULL));
+ _s_test_lstnew ();
+ _s_test_lstadd_front ();
+ _s_test_lstsize ();
+ _s_test_lstlast ();
+ _s_test_lstadd_back ();
+ _s_test_lstdelone ();
+ _s_test_lstclear ();
+ _s_test_lstiter ();
+ _s_test_lstmap ();
+ _s_print_results ();
+ return (_s_fail != 0);
+}