util/tests: Add list iterator tests
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

Reviewed-by: Rob Clark <rob.clark@oss.qualcomm.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37061>
This commit is contained in:
Ella Stanforth 2025-09-09 12:41:40 +01:00 committed by Marge Bot
parent d943a91b71
commit 01c7c97ef7
2 changed files with 118 additions and 0 deletions

View file

@ -401,6 +401,7 @@ if with_tests
'tests/half_float_test.cpp',
'tests/int_min_max.cpp',
'tests/linear_test.cpp',
'tests/list_test.cpp',
'tests/mesa-sha1_test.cpp',
'tests/os_mman_test.cpp',
'tests/perf/u_trace_test.cpp',

View file

@ -0,0 +1,117 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#include <gtest/gtest.h>
#include "util/macros.h"
#include "util/list.h"
struct test_node {
struct list_head link;
};
/* node count must be even or some tests may try deleting the head */
#define NODE_COUNT (8)
struct test_ctx {
struct list_head list;
struct test_node nodes[NODE_COUNT];
};
static void init_test_ctx(struct test_ctx *ctx) {
list_inithead(&ctx->list);
for (unsigned i = 0; i < ARRAY_SIZE(ctx->nodes); i++) {
list_addtail(&ctx->nodes[i].link, &ctx->list);
}
}
#define LIST_LAST_EQ_TEST(name, iterator, node, stmt, index) \
TEST(list, name) { \
struct test_ctx ctx = {}; \
init_test_ctx(&ctx); \
struct test_node *__last_node = NULL; \
iterator (struct test_node, node, &ctx.list, link) { \
__last_node = node; \
stmt; \
} \
EXPECT_EQ(__last_node, &ctx.nodes[index]); \
}
#define LIST_DEATH_TEST(name, iterator, node, stmt, msg) \
TEST(list, name) { \
struct test_ctx ctx = {}; \
init_test_ctx(&ctx); \
EXPECT_DEATH({ \
iterator (struct test_node, node, &ctx.list, link) { \
stmt; \
} \
}, msg); \
}
LIST_LAST_EQ_TEST(del_node_safe, list_for_each_entry_safe, node, {
list_del(&node->link);
}, NODE_COUNT - 1)
LIST_LAST_EQ_TEST(delinit_node_safe, list_for_each_entry_safe, node, {
list_delinit(&node->link);
}, NODE_COUNT - 1)
LIST_LAST_EQ_TEST(del_next, list_for_each_entry, node, {
list_del(node->link.next);
}, NODE_COUNT - 2)
LIST_LAST_EQ_TEST(delinit_next, list_for_each_entry, node, {
list_delinit(node->link.next);
}, NODE_COUNT - 2)
LIST_LAST_EQ_TEST(del_node_safe_rev, list_for_each_entry_safe_rev, node, {
list_del(&node->link);
}, 0)
LIST_LAST_EQ_TEST(delinit_node_safe_rev, list_for_each_entry_safe_rev, node, {
list_delinit(&node->link);
}, 0)
LIST_LAST_EQ_TEST(del_prev_rev, list_for_each_entry_rev, node, {
list_del(node->link.prev);
}, 1)
LIST_LAST_EQ_TEST(delinit_prev_rev, list_for_each_entry_rev, node, {
list_delinit(node->link.prev);
}, 1)
#ifndef NDEBUG
LIST_DEATH_TEST(del_node, list_for_each_entry, node, {
list_del(&node->link);
}, "use _safe iterator")
LIST_DEATH_TEST(delinit_node, list_for_each_entry, node, {
list_delinit(&node->link);
}, "use _safe iterator")
LIST_DEATH_TEST(del_next_safe, list_for_each_entry_safe, node, {
list_del(node->link.next);
}, "use non _safe iterator")
LIST_DEATH_TEST(delinit_next_safe, list_for_each_entry_safe, node, {
list_delinit(node->link.next);
}, "use non _safe iterator")
LIST_DEATH_TEST(del_node_rev, list_for_each_entry_rev, node, {
list_del(&node->link);
}, "use _safe iterator")
LIST_DEATH_TEST(delinit_node_rev, list_for_each_entry_rev, node, {
list_delinit(&node->link);
}, "use _safe iterator")
LIST_DEATH_TEST(del_prev_safe_rev, list_for_each_entry_safe_rev, node, {
list_del(node->link.prev);
}, "use non _safe iterator")
LIST_DEATH_TEST(delinit_prev_safe_rev, list_for_each_entry_safe_rev, node, {
list_delinit(node->link.prev);
}, "use non _safe iterator")
#endif