From 118a9053f04d0e215bb3fe20562990cc73ae69a2 Mon Sep 17 00:00:00 2001
From: Tavian Barnes <tavianator@tavianator.com>
Date: Fri, 31 May 2024 11:55:50 -0400
Subject: list: New SLIST_SPLICE() macro

---
 tests/list.c  | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/main.c  |  1 +
 tests/tests.h |  3 ++
 3 files changed, 101 insertions(+)
 create mode 100644 tests/list.c

(limited to 'tests')

diff --git a/tests/list.c b/tests/list.c
new file mode 100644
index 0000000..e14570f
--- /dev/null
+++ b/tests/list.c
@@ -0,0 +1,97 @@
+// Copyright © Tavian Barnes <tavianator@tavianator.com>
+// SPDX-License-Identifier: 0BSD
+
+#include "prelude.h"
+#include "tests.h"
+#include "list.h"
+
+struct item {
+	int n;
+	struct item *next;
+};
+
+struct list {
+	struct item *head;
+	struct item **tail;
+};
+
+static bool check_list_items(struct list *list, int *array, size_t size) {
+	struct item **cur = &list->head;
+	for (size_t i = 0; i < size; ++i) {
+		if (!bfs_check(*cur != NULL)) {
+			return false;
+		}
+		int n = (*cur)->n;
+		if (!bfs_check(n == array[i], "%d != %d", n, array[i])) {
+			return false;
+		}
+		cur = &(*cur)->next;
+	}
+
+	if (!bfs_check(*cur == NULL)) {
+		return false;
+	}
+	if (!bfs_check(list->tail == cur)) {
+		return false;
+	}
+
+	return true;
+}
+
+#define ARRAY(...) (int[]){ __VA_ARGS__ }, countof((int[]){ __VA_ARGS__ })
+#define EMPTY() NULL, 0
+
+bool check_list(void) {
+	struct list l1;
+	SLIST_INIT(&l1);
+	bfs_verify(check_list_items(&l1, EMPTY()));
+
+	struct list l2;
+	SLIST_INIT(&l2);
+	bfs_verify(check_list_items(&l2, EMPTY()));
+
+	SLIST_EXTEND(&l1, &l2);
+	bfs_verify(check_list_items(&l1, EMPTY()));
+
+	struct item i10 = { .n = 10 };
+	SLIST_APPEND(&l1, &i10);
+	bfs_verify(check_list_items(&l1, ARRAY(10)));
+
+	SLIST_EXTEND(&l1, &l2);
+	bfs_verify(check_list_items(&l1, ARRAY(10)));
+
+	SLIST_SPLICE(&l1, &l1.head, &l2);
+	bfs_verify(check_list_items(&l1, ARRAY(10)));
+
+	struct item i20 = { .n = 20 };
+	SLIST_PREPEND(&l2, &i20);
+	bfs_verify(check_list_items(&l2, ARRAY(20)));
+
+	SLIST_EXTEND(&l1, &l2);
+	bfs_verify(check_list_items(&l1, ARRAY(10, 20)));
+	bfs_verify(check_list_items(&l2, EMPTY()));
+
+	struct item i15 = { .n = 15 };
+	SLIST_APPEND(&l2, &i15);
+	SLIST_SPLICE(&l1, &i10.next, &l2);
+	bfs_verify(check_list_items(&l1, ARRAY(10, 15, 20)));
+	bfs_verify(check_list_items(&l2, EMPTY()));
+
+	SLIST_EXTEND(&l1, &l2);
+	bfs_verify(check_list_items(&l1, ARRAY(10, 15, 20)));
+
+	SLIST_SPLICE(&l1, &i10.next, &l2);
+	bfs_verify(check_list_items(&l1, ARRAY(10, 15, 20)));
+
+	SLIST_SPLICE(&l1, &l1.head, &l2);
+	bfs_verify(check_list_items(&l1, ARRAY(10, 15, 20)));
+
+	struct item i11 = { .n = 11 };
+	struct item i12 = { .n = 12 };
+	SLIST_APPEND(&l2, &i11);
+	SLIST_APPEND(&l2, &i12);
+	SLIST_SPLICE(&l1, &l1.head->next, &l2);
+	bfs_verify(check_list_items(&l1, ARRAY(10, 11, 12, 15, 20)));
+
+	return true;
+}
diff --git a/tests/main.c b/tests/main.c
index aef0583..bef2e37 100644
--- a/tests/main.c
+++ b/tests/main.c
@@ -111,6 +111,7 @@ int main(int argc, char *argv[]) {
 	run_test(&ctx, "bfstd", check_bfstd);
 	run_test(&ctx, "bit", check_bit);
 	run_test(&ctx, "ioq", check_ioq);
+	run_test(&ctx, "list", check_list);
 	run_test(&ctx, "sighook", check_sighook);
 	run_test(&ctx, "trie", check_trie);
 	run_test(&ctx, "xspawn", check_xspawn);
diff --git a/tests/tests.h b/tests/tests.h
index de95a49..2958fe1 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -27,6 +27,9 @@ bool check_bit(void);
 /** I/O queue tests. */
 bool check_ioq(void);
 
+/** Linked list tests. */
+bool check_list(void);
+
 /** Signal hook tests. */
 bool check_sighook(void);
 
-- 
cgit v1.2.3