418 lines
9.9 KiB
C
418 lines
9.9 KiB
C
/*
|
|
* Copyright (c) 2019 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <ztest.h>
|
|
#include <zephyr/sys/sflist.h>
|
|
|
|
static sys_sflist_t test_list;
|
|
static sys_sflist_t append_list;
|
|
|
|
struct container_node {
|
|
sys_sfnode_t node;
|
|
int unused;
|
|
};
|
|
|
|
static struct container_node test_node_1;
|
|
static struct container_node test_node_2;
|
|
static struct container_node test_node_3;
|
|
static struct container_node test_node_4;
|
|
|
|
static inline bool verify_emptyness(sys_sflist_t *list)
|
|
{
|
|
sys_sfnode_t *node;
|
|
sys_sfnode_t *s_node;
|
|
struct container_node *cnode;
|
|
struct container_node *s_cnode;
|
|
int count;
|
|
|
|
if (!sys_sflist_is_empty(list)) {
|
|
return false;
|
|
}
|
|
|
|
if (sys_sflist_peek_head(list)) {
|
|
return false;
|
|
}
|
|
|
|
if (sys_sflist_peek_tail(list)) {
|
|
return false;
|
|
}
|
|
|
|
count = 0;
|
|
SYS_SFLIST_FOR_EACH_NODE(list, node) {
|
|
count++;
|
|
}
|
|
|
|
if (count) {
|
|
return false;
|
|
}
|
|
|
|
SYS_SFLIST_FOR_EACH_NODE_SAFE(list, node, s_node) {
|
|
count++;
|
|
}
|
|
|
|
if (count) {
|
|
return false;
|
|
}
|
|
|
|
count = 0;
|
|
SYS_SFLIST_FOR_EACH_CONTAINER(list, cnode, node) {
|
|
count++;
|
|
}
|
|
|
|
if (count) {
|
|
return false;
|
|
}
|
|
|
|
count = 0;
|
|
SYS_SFLIST_FOR_EACH_CONTAINER_SAFE(list, cnode, s_cnode, node) {
|
|
count++;
|
|
}
|
|
|
|
if (count) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline bool verify_content_amount(sys_sflist_t *list, int amount)
|
|
{
|
|
sys_sfnode_t *node;
|
|
sys_sfnode_t *s_node;
|
|
struct container_node *cnode;
|
|
struct container_node *s_cnode;
|
|
int count;
|
|
|
|
if (sys_sflist_is_empty(list)) {
|
|
return false;
|
|
}
|
|
|
|
if (!sys_sflist_peek_head(list)) {
|
|
return false;
|
|
}
|
|
|
|
if (!sys_sflist_peek_tail(list)) {
|
|
return false;
|
|
}
|
|
|
|
count = 0;
|
|
SYS_SFLIST_FOR_EACH_NODE(list, node) {
|
|
count++;
|
|
}
|
|
|
|
if (count != amount) {
|
|
return false;
|
|
}
|
|
|
|
count = 0;
|
|
SYS_SFLIST_FOR_EACH_NODE_SAFE(list, node, s_node) {
|
|
count++;
|
|
}
|
|
|
|
if (count != amount) {
|
|
return false;
|
|
}
|
|
|
|
count = 0;
|
|
SYS_SFLIST_FOR_EACH_CONTAINER(list, cnode, node) {
|
|
count++;
|
|
}
|
|
|
|
if (count != amount) {
|
|
return false;
|
|
}
|
|
|
|
count = 0;
|
|
SYS_SFLIST_FOR_EACH_CONTAINER_SAFE(list, cnode, s_cnode, node) {
|
|
count++;
|
|
}
|
|
|
|
if (count != amount) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static inline bool verify_tail_head(sys_sflist_t *list,
|
|
sys_sfnode_t *head,
|
|
sys_sfnode_t *tail,
|
|
bool same)
|
|
{
|
|
if (sys_sflist_peek_head(list) != head) {
|
|
return false;
|
|
}
|
|
|
|
if (sys_sflist_peek_tail(list) != tail) {
|
|
return false;
|
|
}
|
|
|
|
if (same) {
|
|
if (sys_sflist_peek_head(list) != sys_sflist_peek_tail(list)) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if (sys_sflist_peek_head(list) == sys_sflist_peek_tail(list)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
/**
|
|
* @addtogroup kernel_common_tests
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief Test singly linked list functionalities
|
|
*
|
|
* @details Test list initialization, append item to the list,
|
|
* find and remove item, prepend, append, remove list
|
|
*
|
|
* @see sys_sflist_init(), sys_sflist_append(),
|
|
* sys_sflist_find_and_remove(), sys_sflist_prepend(),
|
|
* sys_sflist_remove(), sys_sflist_get(), sys_sflist_get_not_empty(),
|
|
* sys_sflist_append_list(), sys_sflist_merge_list()
|
|
*/
|
|
void test_sflist(void)
|
|
{
|
|
sys_sflist_init(&test_list);
|
|
|
|
zassert_true((verify_emptyness(&test_list)),
|
|
"test_list should be empty");
|
|
|
|
/* Appending node 1 */
|
|
sys_sflist_append(&test_list, &test_node_1.node);
|
|
zassert_true((verify_content_amount(&test_list, 1)),
|
|
"test_list has wrong content");
|
|
|
|
zassert_true((verify_tail_head(&test_list, &test_node_1.node,
|
|
&test_node_1.node, true)),
|
|
"test_list head/tail are wrong");
|
|
|
|
/* Finding and removing node 1 */
|
|
sys_sflist_find_and_remove(&test_list, &test_node_1.node);
|
|
zassert_true((verify_emptyness(&test_list)),
|
|
"test_list should be empty");
|
|
|
|
/* Prepending node 1 */
|
|
sys_sflist_prepend(&test_list, &test_node_1.node);
|
|
zassert_true((verify_content_amount(&test_list, 1)),
|
|
"test_list has wrong content");
|
|
|
|
zassert_true((verify_tail_head(&test_list, &test_node_1.node,
|
|
&test_node_1.node, true)),
|
|
"test_list head/tail are wrong");
|
|
|
|
/* Removing node 1 */
|
|
sys_sflist_remove(&test_list, NULL, &test_node_1.node);
|
|
zassert_true((verify_emptyness(&test_list)),
|
|
"test_list should be empty");
|
|
|
|
/* Appending node 1 */
|
|
sys_sflist_append(&test_list, &test_node_1.node);
|
|
/* Prepending node 2 */
|
|
sys_sflist_prepend(&test_list, &test_node_2.node);
|
|
|
|
zassert_true((verify_content_amount(&test_list, 2)),
|
|
"test_list has wrong content");
|
|
|
|
zassert_true((verify_tail_head(&test_list, &test_node_2.node,
|
|
&test_node_1.node, false)),
|
|
"test_list head/tail are wrong");
|
|
|
|
/* Appending node 3 */
|
|
sys_sflist_append(&test_list, &test_node_3.node);
|
|
|
|
zassert_true((verify_content_amount(&test_list, 3)),
|
|
"test_list has wrong content");
|
|
|
|
zassert_true((verify_tail_head(&test_list, &test_node_2.node,
|
|
&test_node_3.node, false)),
|
|
"test_list head/tail are wrong");
|
|
|
|
zassert_true((sys_sflist_peek_next(&test_node_2.node) ==
|
|
&test_node_1.node),
|
|
"test_list node links are wrong");
|
|
|
|
/* Inserting node 4 after node 2, peek with nocheck variant */
|
|
sys_sflist_insert(&test_list, &test_node_2.node, &test_node_4.node);
|
|
|
|
zassert_true((verify_tail_head(&test_list, &test_node_2.node,
|
|
&test_node_3.node, false)),
|
|
"test_list head/tail are wrong");
|
|
|
|
zassert_true((sys_sflist_peek_next_no_check(&test_node_2.node) ==
|
|
&test_node_4.node),
|
|
"test_list node links are wrong");
|
|
|
|
/* Finding and removing node 1 */
|
|
sys_sflist_find_and_remove(&test_list, &test_node_1.node);
|
|
zassert_true((verify_content_amount(&test_list, 3)),
|
|
"test_list has wrong content");
|
|
|
|
zassert_true((verify_tail_head(&test_list, &test_node_2.node,
|
|
&test_node_3.node, false)),
|
|
"test_list head/tail are wrong");
|
|
|
|
/* Removing node 3 */
|
|
sys_sflist_remove(&test_list, &test_node_4.node, &test_node_3.node);
|
|
zassert_true((verify_content_amount(&test_list, 2)),
|
|
"test_list has wrong content");
|
|
|
|
zassert_true((verify_tail_head(&test_list, &test_node_2.node,
|
|
&test_node_4.node, false)),
|
|
"test_list head/tail are wrong");
|
|
|
|
/* Removing node 4 */
|
|
sys_sflist_remove(&test_list, &test_node_2.node, &test_node_4.node);
|
|
zassert_true((verify_content_amount(&test_list, 1)),
|
|
"test_list has wrong content");
|
|
|
|
zassert_true((verify_tail_head(&test_list, &test_node_2.node,
|
|
&test_node_2.node, true)),
|
|
"test_list head/tail are wrong");
|
|
|
|
/* Removing node 2 */
|
|
sys_sflist_remove(&test_list, NULL, &test_node_2.node);
|
|
zassert_true((verify_emptyness(&test_list)),
|
|
"test_list should be empty");
|
|
|
|
/* test iterator from a node */
|
|
struct data_node {
|
|
sys_sfnode_t node;
|
|
int data;
|
|
} data_node[6] = {
|
|
{ .data = 0 },
|
|
{ .data = 1 },
|
|
{ .data = 2 },
|
|
{ .data = 3 },
|
|
{ .data = 4 },
|
|
{ .data = 5 },
|
|
};
|
|
sys_sfnode_t *node = NULL;
|
|
int ii;
|
|
|
|
sys_sflist_init(&test_list);
|
|
|
|
for (ii = 0; ii < 6; ii++) {
|
|
sys_sflist_append(&test_list, &data_node[ii].node);
|
|
}
|
|
|
|
ii = 0;
|
|
SYS_SFLIST_ITERATE_FROM_NODE(&test_list, node) {
|
|
ii++;
|
|
if (((struct data_node *)node)->data == 2) {
|
|
break;
|
|
}
|
|
}
|
|
zassert_equal(ii, 3, "");
|
|
|
|
ii = 0;
|
|
SYS_SFLIST_ITERATE_FROM_NODE(&test_list, node) {
|
|
ii++;
|
|
if (((struct data_node *)node)->data == 3) {
|
|
break;
|
|
}
|
|
}
|
|
zassert_equal(ii, 1, "");
|
|
|
|
ii = 0;
|
|
SYS_SFLIST_ITERATE_FROM_NODE(&test_list, node) {
|
|
ii++;
|
|
}
|
|
zassert_equal(ii, 2, "");
|
|
|
|
/* test sys_sflist_get_not_empty() and sys_sflist_get() APIs */
|
|
for (ii = 0; ii < 6; ii++) {
|
|
node = sys_sflist_get_not_empty(&test_list);
|
|
zassert_equal(((struct data_node *)node)->data, ii, "");
|
|
}
|
|
for (ii = 0; ii < 6; ii++) {
|
|
/* regenerate test_list since we just emptied it */
|
|
sys_sflist_append(&test_list, &data_node[ii].node);
|
|
}
|
|
for (ii = 0; ii < 6; ii++) {
|
|
node = sys_sflist_get(&test_list);
|
|
zassert_equal(((struct data_node *)node)->data, ii, "");
|
|
}
|
|
node = sys_sflist_get(&test_list);
|
|
zassert_equal(node, NULL, "");
|
|
|
|
/* test sys_sflist_append_list() */
|
|
sys_sflist_init(&append_list);
|
|
struct data_node data_node_append[6] = {
|
|
{ .data = 6 },
|
|
{ .data = 7 },
|
|
{ .data = 8 },
|
|
{ .data = 9 },
|
|
{ .data = 10 },
|
|
{ .data = 11 },
|
|
};
|
|
for (ii = 0; ii < 6; ii++) {
|
|
/* regenerate test_list, which we just emptied */
|
|
sys_sflist_append(&test_list, &data_node[ii].node);
|
|
/* Build append_list so that the node pointers are correct */
|
|
sys_sflist_append(&append_list, &data_node_append[ii].node);
|
|
}
|
|
sys_sflist_append_list(&test_list, &data_node_append[0].node,
|
|
&data_node_append[5].node);
|
|
for (ii = 0; ii < 12; ii++) {
|
|
node = sys_sflist_get(&test_list);
|
|
zassert_equal(((struct data_node *)node)->data, ii,
|
|
"expected %d got %d", ii,
|
|
((struct data_node *)node)->data);
|
|
}
|
|
|
|
/* test sys_sflist_merge_sflist */
|
|
sys_sflist_init(&test_list);
|
|
sys_sflist_init(&append_list);
|
|
for (ii = 0; ii < 6; ii++) {
|
|
/* regenerate both lists */
|
|
sys_sflist_append(&test_list, &data_node[ii].node);
|
|
sys_sflist_append(&append_list, &data_node_append[ii].node);
|
|
}
|
|
sys_sflist_merge_sflist(&test_list, &append_list);
|
|
for (ii = 0; ii < 12; ii++) {
|
|
node = sys_sflist_get(&test_list);
|
|
zassert_equal(((struct data_node *)node)->data, ii,
|
|
"expected %d got %d", ii,
|
|
((struct data_node *)node)->data);
|
|
}
|
|
zassert_true(sys_sflist_is_empty(&append_list),
|
|
"merged list is not empty");
|
|
|
|
/* tests for sys_sfnode_flags_get(), sys_sfnode_flags_set()
|
|
* sys_sfnode_init()
|
|
*/
|
|
sys_sflist_init(&test_list);
|
|
/* Only iterating 0..3 due to limited range of flag values */
|
|
for (ii = 0; ii < 4; ii++) {
|
|
sys_sfnode_init(&data_node[ii].node, ii);
|
|
sys_sflist_append(&test_list, &data_node[ii].node);
|
|
}
|
|
for (ii = 0; ii < 4; ii++) {
|
|
node = sys_sflist_get(&test_list);
|
|
zassert_equal(sys_sfnode_flags_get(node), ii,
|
|
"wrong flags value");
|
|
/* Place the nodes back on the list with the flags set
|
|
* in reverse order for the next test
|
|
*/
|
|
sys_sfnode_flags_set(node, 3 - ii);
|
|
sys_sflist_append(&test_list, node);
|
|
}
|
|
for (ii = 3; ii >= 0; ii--) {
|
|
node = sys_sflist_get(&test_list);
|
|
zassert_equal(sys_sfnode_flags_get(node), ii,
|
|
"wrong flags value");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|