Skip to content

Commit 4299320

Browse files
authored
Merge pull request #11 from shishir-dey/feature/better-unit-testing
Enable unit testing, register the tests with CTest, and allow the creation of multiple test executables
2 parents d34b628 + 9a67196 commit 4299320

File tree

4 files changed

+195
-90
lines changed

4 files changed

+195
-90
lines changed

CMakeLists.txt

+28-17
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ project(stm32-devops-template)
44

55
message("HOST=${HOST}")
66

7+
# Enable testing
8+
enable_testing()
9+
710
enable_language(C ASM)
811
set(CMAKE_C_STANDARD 99)
912
set(CMAKE_C_STANDARD_REQUIRED ON)
@@ -15,38 +18,46 @@ set(COMMON_SOURCES
1518
)
1619

1720
if( HOST )
18-
set(HOST_SOURCES
19-
test/test_linked_list.c
20-
lib/Unity/src/unity_internals.h
21-
lib/Unity/src/unity.h
22-
lib/Unity/src/unity.c
23-
)
21+
# Collect all test source files matching test/test_*.c
22+
file(GLOB TEST_SOURCES "test/test_*.c")
2423

25-
set(HOST_EXECUTABLE
26-
${PROJECT_NAME}.out
27-
)
24+
# Loop over each test source file
25+
foreach(TEST_SOURCE ${TEST_SOURCES})
2826

29-
add_executable(${HOST_EXECUTABLE}
30-
${HOST_SOURCES}
31-
${COMMON_SOURCES}
27+
# Get the file name without the directory and extension
28+
get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE)
29+
30+
# Create an executable for each test
31+
add_executable(${TEST_NAME}
32+
${TEST_SOURCE}
33+
${COMMON_SOURCES} # Common sources if needed
34+
lib/Unity/src/unity.c
3235
)
3336

34-
target_compile_definitions(${HOST_EXECUTABLE} PRIVATE
37+
# Set compile definitions if needed
38+
target_compile_definitions(${TEST_NAME} PRIVATE
3539
)
3640

37-
target_include_directories(${HOST_EXECUTABLE} PRIVATE
41+
# Include directories
42+
target_include_directories(${TEST_NAME} PRIVATE
3843
lib/linked_list
3944
lib/Unity/src
4045
)
4146

42-
target_compile_options(${HOST_EXECUTABLE} PRIVATE
47+
# Set compile options
48+
target_compile_options(${TEST_NAME} PRIVATE
4349
-Wall
44-
4550
$<$<CONFIG:Debug>:-Og>
4651
)
4752

48-
target_link_options(${HOST_EXECUTABLE} PRIVATE
53+
# Set link options if needed
54+
target_link_options(${TEST_NAME} PRIVATE
4955
)
56+
57+
# Register the test with ctest
58+
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
59+
60+
endforeach()
5061
else()
5162
set(TARGET_SOURCES
5263
src/main.c

lib/linked_list/linked_list.c

+65-39
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,75 @@
1-
#include <stdlib.h>
21
#include "linked_list.h"
2+
#include <stddef.h>
33

4-
/// @brief Initialize a new linked list
5-
/// @return Pointer to the new list
6-
Node *InitList()
4+
static node_t* head = NULL;
5+
6+
status_t ll_init(node_t* initial_node)
77
{
8-
Node *list = malloc(sizeof(Node));
9-
list->data = NULL;
10-
list->next = NULL;
11-
return list;
8+
if (initial_node == NULL) {
9+
return FAILURE;
10+
}
11+
head = initial_node;
12+
head->data = NULL;
13+
head->next = NULL;
14+
return SUCCESS;
1215
}
1316

14-
/// @brief Add a new node to the list
15-
/// @param list Pointer to the list
16-
/// @param data Pointer to the data to add
17-
void AddNode(Node *list, void *data)
17+
status_t ll_insert_at_head(node_t* new_node)
1818
{
19-
if (list->data == NULL)
20-
{
21-
list->data = data;
22-
list->next = NULL;
23-
}
24-
else
25-
{
26-
Node *node = list;
27-
while (node->next != NULL)
28-
{
29-
node = node->next;
30-
}
31-
node->next = malloc(sizeof(Node));
32-
node->next->data = data;
33-
node->next->next = NULL;
19+
if (new_node == NULL) {
20+
return FAILURE;
3421
}
22+
new_node->next = head;
23+
head = new_node;
24+
return SUCCESS;
3525
}
3626

37-
/// @brief Delete the list
38-
/// @param list Pointer to the list
39-
void DeleteList(Node *list)
27+
status_t ll_insert_at_tail(node_t* new_node)
4028
{
41-
Node *current = list;
42-
while (current != NULL)
43-
{
44-
Node *next = current->next;
45-
free(current);
46-
current = next;
47-
}
48-
*list = (Node){NULL, NULL};
49-
}
29+
if (new_node == NULL) {
30+
return FAILURE;
31+
}
32+
33+
if (head == NULL) {
34+
head = new_node;
35+
head->next = NULL;
36+
return SUCCESS;
37+
}
38+
39+
node_t* current = head;
40+
while (current->next != NULL) {
41+
current = current->next;
42+
}
43+
current->next = new_node;
44+
new_node->next = NULL;
45+
return SUCCESS;
46+
}
47+
48+
status_t ll_delete_at_head()
49+
{
50+
if (head == NULL) {
51+
return FAILURE;
52+
}
53+
54+
head = head->next;
55+
return SUCCESS;
56+
}
57+
58+
status_t ll_delete_at_tail()
59+
{
60+
if (head == NULL) {
61+
return FAILURE;
62+
}
63+
64+
if (head->next == NULL) {
65+
head = NULL;
66+
return SUCCESS;
67+
}
68+
69+
node_t* current = head;
70+
while (current->next->next != NULL) {
71+
current = current->next;
72+
}
73+
current->next = NULL;
74+
return SUCCESS;
75+
}

lib/linked_list/linked_list.h

+46-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,54 @@
11
#ifndef LINKED_LIST_H
22
#define LINKED_LIST_H
33

4-
struct _Node
5-
{
6-
void *data;
7-
struct _Node *next;
4+
struct _Node {
5+
void* data;
6+
struct _Node* next;
87
};
98

10-
typedef struct _Node Node;
9+
typedef struct _Node node_t;
1110

12-
Node *InitList();
13-
void AddNode(Node *list, void *data);
14-
void DeleteList(Node *list);
11+
typedef enum {
12+
SUCCESS,
13+
FAILURE
14+
} status_t;
15+
16+
/**
17+
* @brief Initializes the linked list with an initial node.
18+
*
19+
* @param initial_node Pointer to the initial node to be added to the list.
20+
* @return status_t SUCCESS if initialization is successful, FAILURE otherwise.
21+
*/
22+
status_t ll_init(node_t* initial_node);
23+
24+
/**
25+
* @brief Inserts a new node at the head of the linked list.
26+
*
27+
* @param new_node Pointer to the new node to be inserted at the head.
28+
* @return status_t SUCCESS if insertion is successful, FAILURE otherwise.
29+
*/
30+
status_t ll_insert_at_head(node_t* new_node);
31+
32+
/**
33+
* @brief Inserts a new node at the tail of the linked list.
34+
*
35+
* @param new_node Pointer to the new node to be inserted at the tail.
36+
* @return status_t SUCCESS if insertion is successful, FAILURE otherwise.
37+
*/
38+
status_t ll_insert_at_tail(node_t* new_node);
39+
40+
/**
41+
* @brief Deletes the node at the head of the linked list.
42+
*
43+
* @return status_t SUCCESS if deletion is successful, FAILURE if the list is empty.
44+
*/
45+
status_t ll_delete_at_head();
46+
47+
/**
48+
* @brief Deletes the node at the tail of the linked list.
49+
*
50+
* @return status_t SUCCESS if deletion is successful, FAILURE if the list is empty.
51+
*/
52+
status_t ll_delete_at_tail();
1553

1654
#endif

test/test_linked_list.c

+56-26
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,78 @@
11
#include "../lib/Unity/src/unity.h"
22
#include "../lib/linked_list/linked_list.h"
33

4+
// Global node variables
5+
node_t test_node_initial;
6+
node_t test_node1;
7+
node_t test_node2;
8+
49
void setUp(void)
510
{
11+
ll_init(&test_node_initial);
612
}
713

814
void tearDown(void)
915
{
1016
}
1117

12-
void testLinkedListAddNode(void)
18+
void resetTest(void)
1319
{
14-
Node *list = InitList();
15-
TEST_ASSERT_NULL(list->data);
16-
TEST_ASSERT_NULL(list->next);
17-
AddNode(list, "test");
18-
TEST_ASSERT_EQUAL_STRING("test", list->data);
19-
TEST_ASSERT_NULL(list->next);
20-
AddNode(list, "test2");
21-
TEST_ASSERT_EQUAL_STRING("test2", list->next->data);
22-
TEST_ASSERT_NULL(list->next->next);
23-
DeleteList(list);
20+
tearDown();
21+
setUp();
2422
}
2523

26-
void testLinkedListDeleteList(void)
24+
void test_ll_init(void)
2725
{
28-
Node *list = InitList();
29-
AddNode(list, 1);
30-
AddNode(list, 2);
31-
AddNode(list, 3);
32-
DeleteList(list);
33-
TEST_ASSERT_NULL(list->data);
26+
TEST_ASSERT_EQUAL(SUCCESS, ll_init(&test_node_initial));
3427
}
3528

36-
void resetTest(void)
29+
void test_ll_insert_at_head(void)
3730
{
38-
tearDown();
39-
setUp();
31+
resetTest();
32+
test_node1.data = "test";
33+
test_node1.next = NULL;
34+
TEST_ASSERT_EQUAL(SUCCESS, ll_insert_at_head(&test_node1));
35+
}
36+
37+
void test_ll_insert_at_tail(void)
38+
{
39+
resetTest();
40+
test_node1.data = "test1";
41+
test_node1.next = NULL;
42+
test_node2.data = "test2";
43+
test_node2.next = NULL;
44+
TEST_ASSERT_EQUAL(SUCCESS, ll_insert_at_tail(&test_node1));
45+
TEST_ASSERT_EQUAL(SUCCESS, ll_insert_at_tail(&test_node2));
46+
}
47+
48+
void test_ll_delete_at_head(void)
49+
{
50+
resetTest();
51+
test_node1.data = "test";
52+
test_node1.next = NULL;
53+
ll_insert_at_head(&test_node1);
54+
TEST_ASSERT_EQUAL(SUCCESS, ll_delete_at_head());
55+
}
56+
57+
void test_ll_delete_at_tail(void)
58+
{
59+
resetTest();
60+
test_node1.data = "test1";
61+
test_node1.next = NULL;
62+
test_node2.data = "test2";
63+
test_node2.next = NULL;
64+
ll_insert_at_tail(&test_node1);
65+
ll_insert_at_tail(&test_node2);
66+
TEST_ASSERT_EQUAL(SUCCESS, ll_delete_at_tail());
4067
}
4168

4269
int main(void)
4370
{
44-
UnityBegin("test_linked_list.c");
45-
RUN_TEST(testLinkedListAddNode, 33);
46-
RUN_TEST(testLinkedListDeleteList, 44);
47-
UnityEnd();
48-
}
71+
UNITY_BEGIN();
72+
RUN_TEST(test_ll_init);
73+
RUN_TEST(test_ll_insert_at_head);
74+
RUN_TEST(test_ll_insert_at_tail);
75+
RUN_TEST(test_ll_delete_at_head);
76+
RUN_TEST(test_ll_delete_at_tail);
77+
return UNITY_END();
78+
}

0 commit comments

Comments
 (0)