Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ deps += $(LIB_OBJS:%.o=%.o.d)
APPS := coop echo hello mqueues semaphore mutex cond \
pipes pipes_small pipes_struct prodcons progress \
rtsched suspend test64 timer timer_kill \
cpubench test_libc
cpubench test_utils

# Output files for __link target
IMAGE_BASE := $(BUILD_DIR)/image
Expand Down
53 changes: 52 additions & 1 deletion app/test_libc.c → app/test_utils.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/* LibC Test Suite - Comprehensive tests for standard library functions.
/* Utility Test Suite - Comprehensive tests for utilities and helpers.
*
* Current Coverage:
* - vsnprintf/snprintf: Buffer overflow protection
* * C99 semantics, truncation behavior, ISR safety
* * Format specifiers: %s, %d, %u, %x, %p, %c, %%
* * Edge cases: size=0, size=1, truncation, null termination
*
* - list operations: pushback node, remove node
*
* Future Tests (Planned):
* - String functions: strlen, strcmp, strcpy, strncpy, memcpy, memset
* - Memory allocation: malloc, free, realloc
Expand Down Expand Up @@ -298,6 +300,51 @@ void test_mixed_formats(void)
ASSERT_TEST(buf[test_strlen(buf)] == '\0', "Mixed format null termination");
}

/* Test 11: List node helpers behavior */
void test_list_node_pushback_and_remove(void)
{
list_node_t node1 = {0};
list_node_t node2 = {0};

node1.next = &node2; /* make node1 artificially “linked” */
list_t *list = list_create();

/* Check node push back normally - unlinked and linked */
list_pushback_node(list, &node1);
ASSERT_TEST(list_is_empty(list), "Linked node pushback fail");

node1.next = NULL;
list_pushback_node(list, &node1);
ASSERT_TEST(list->length == 1, "Unlinked node pushback success ");
ASSERT_TEST(list->head->next == &node1 && node1.next == list->tail,
"List consistent after pushback first node ");

/* Check node push back order */
node2.next = NULL;
list_pushback_node(list, &node2);
ASSERT_TEST(list->length == 2 && list->head->next == &node1 &&
node1.next == &node2 && node2.next == list->tail,
"Insertion order preserved ");

/* Remove last node */
list_remove_node(list, &node2);
ASSERT_TEST(
list->length == 1 && node2.next == NULL && node1.next == list->tail,
"Removing last node must keep list structure consistent");

/* Remove non-existing node (second time) */
list_remove_node(list, &node2);
ASSERT_TEST(
list->length == 1 && node2.next == NULL && node1.next == list->tail,
"Removing non-existing node must not change the list");

/* Remove only node */
list_remove_node(list, &node1);
ASSERT_TEST(list->length == 0 && list->head->next == list->tail,
"Removing only node ");
ASSERT_TEST(list_is_empty(list), "Empty list check ");
}

void test_runner(void)
{
printf("\n=== LibC Test Suite ===\n");
Expand All @@ -314,6 +361,10 @@ void test_runner(void)
test_isr_safety();
test_mixed_formats();


printf("\n=== List Test Suite ===\n");
test_list_node_pushback_and_remove();

printf("\n=== Test Summary ===\n");
printf("Tests run: %d\n", tests_run);
printf("Tests passed: %d\n", tests_passed);
Expand Down
37 changes: 37 additions & 0 deletions include/lib/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,24 @@ static inline list_node_t *list_pushback(list_t *list, void *data)
return node;
}

/* Pushback list node into list */
static inline void list_pushback_node(list_t *list, list_node_t *target)
{
if (unlikely(!list || !target || target->next))
return;

target->next = list->tail;

/* Insert before tail sentinel */
list_node_t *prev = list->head;
while (prev->next != list->tail)
prev = prev->next;

prev->next = target;
list->length++;
return;
}

static inline void *list_pop(list_t *list)
{
if (unlikely(list_is_empty(list)))
Expand Down Expand Up @@ -134,6 +152,25 @@ static inline void *list_remove(list_t *list, list_node_t *target)
return data;
}

/* Remove a node from list without freeing */
static inline void list_remove_node(list_t *list, list_node_t *target)
{
if (unlikely(!list || !target || list_is_empty(list)))
return;

list_node_t *prev = list->head;
while (prev->next != list->tail && prev->next != target)
prev = prev->next;

if (unlikely(prev->next != target))
return; /* node not found */

prev->next = target->next;
target->next = NULL;
list->length--;
return;
}

/* Iteration */

/* Callback should return non-NULL to stop early, NULL to continue */
Expand Down
Loading