Skip to content

Commit d74ff9c

Browse files
add lists
1 parent 2e3fef0 commit d74ff9c

File tree

4 files changed

+173
-38
lines changed

4 files changed

+173
-38
lines changed

tests/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,5 @@ endfunction()
7979
# The public interface tests may be written in C++ for convenience.
8080
gen_test_matrix(test_helpers "src/test_helpers.c")
8181
gen_test_matrix(test_intrusive_header "src/test_intrusive_header.c")
82-
gen_test_matrix(test_intrusive_crc "src/test_intrusive_crc.c")
82+
gen_test_matrix(test_intrusive_misc "src/test_intrusive_misc.c")
8383
gen_test_matrix(test_intrusive_tx "src/test_intrusive_tx.c")

tests/src/test_intrusive_crc.c

Lines changed: 0 additions & 29 deletions
This file was deleted.

tests/src/test_intrusive_misc.c

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/// This software is distributed under the terms of the MIT License.
2+
/// Copyright (C) OpenCyphal Development Team <opencyphal.org>
3+
/// Copyright Amazon.com Inc. or its affiliates.
4+
/// SPDX-License-Identifier: MIT
5+
6+
#include <udpard.c> // NOLINT(bugprone-suspicious-include)
7+
#include <unity.h>
8+
9+
static void test_crc(void)
10+
{
11+
uint32_t crc = crc_add(CRC_INITIAL, 3, "123");
12+
crc = crc_add(crc, 6, "456789");
13+
TEST_ASSERT_EQUAL_UINT32(0x1CF96D7CUL, crc);
14+
TEST_ASSERT_EQUAL_UINT32(0xE3069283UL, crc ^ CRC_OUTPUT_XOR);
15+
crc = crc_add(crc, 4, "\x83\x92\x06\xE3"); // Least significant byte first.
16+
TEST_ASSERT_EQUAL_UINT32(CRC_RESIDUE_BEFORE_OUTPUT_XOR, crc);
17+
TEST_ASSERT_EQUAL_UINT32(CRC_RESIDUE_AFTER_OUTPUT_XOR, crc ^ CRC_OUTPUT_XOR);
18+
}
19+
20+
static void test_list(void)
21+
{
22+
typedef struct test_node_t
23+
{
24+
int value;
25+
udpard_list_member_t link;
26+
} test_node_t;
27+
28+
udpard_list_t list = {.head = NULL, .tail = NULL};
29+
30+
// Test 1: Empty list state
31+
TEST_ASSERT_NULL(list.head);
32+
TEST_ASSERT_NULL(list.tail);
33+
34+
// Test 2: Enlist single item
35+
test_node_t node1 = {.value = 1, .link = {.next = NULL, .prev = NULL}};
36+
enlist_head(&list, &node1.link);
37+
TEST_ASSERT_EQUAL(&node1.link, list.head);
38+
TEST_ASSERT_EQUAL(&node1.link, list.tail);
39+
TEST_ASSERT_NULL(node1.link.next);
40+
TEST_ASSERT_NULL(node1.link.prev);
41+
42+
// Test 3: Enlist second item (should become head)
43+
test_node_t node2 = {.value = 2, .link = {.next = NULL, .prev = NULL}};
44+
enlist_head(&list, &node2.link);
45+
TEST_ASSERT_EQUAL(&node2.link, list.head);
46+
TEST_ASSERT_EQUAL(&node1.link, list.tail);
47+
TEST_ASSERT_EQUAL(&node1.link, node2.link.next);
48+
TEST_ASSERT_NULL(node2.link.prev);
49+
TEST_ASSERT_NULL(node1.link.next);
50+
TEST_ASSERT_EQUAL(&node2.link, node1.link.prev);
51+
52+
// Test 4: Enlist third item (should become new head)
53+
test_node_t node3 = {.value = 3, .link = {.next = NULL, .prev = NULL}};
54+
enlist_head(&list, &node3.link);
55+
TEST_ASSERT_EQUAL(&node3.link, list.head);
56+
TEST_ASSERT_EQUAL(&node1.link, list.tail);
57+
TEST_ASSERT_EQUAL(&node2.link, node3.link.next);
58+
TEST_ASSERT_NULL(node3.link.prev);
59+
TEST_ASSERT_EQUAL(&node1.link, node2.link.next);
60+
TEST_ASSERT_EQUAL(&node3.link, node2.link.prev);
61+
62+
// Test 5: Delist middle item
63+
delist(&list, &node2.link);
64+
TEST_ASSERT_EQUAL(&node3.link, list.head);
65+
TEST_ASSERT_EQUAL(&node1.link, list.tail);
66+
TEST_ASSERT_EQUAL(&node1.link, node3.link.next);
67+
TEST_ASSERT_NULL(node3.link.prev);
68+
TEST_ASSERT_NULL(node1.link.next);
69+
TEST_ASSERT_EQUAL(&node3.link, node1.link.prev);
70+
TEST_ASSERT_NULL(node2.link.next);
71+
TEST_ASSERT_NULL(node2.link.prev);
72+
73+
// Test 6: Re-enlist previously delisted item (should become head)
74+
enlist_head(&list, &node2.link);
75+
TEST_ASSERT_EQUAL(&node2.link, list.head);
76+
TEST_ASSERT_EQUAL(&node1.link, list.tail);
77+
TEST_ASSERT_EQUAL(&node3.link, node2.link.next);
78+
TEST_ASSERT_NULL(node2.link.prev);
79+
80+
// Test 7: Move existing item to head (enlist_head can be used for moving)
81+
enlist_head(&list, &node1.link);
82+
TEST_ASSERT_EQUAL(&node1.link, list.head);
83+
TEST_ASSERT_EQUAL(&node3.link, list.tail);
84+
TEST_ASSERT_EQUAL(&node2.link, node1.link.next);
85+
TEST_ASSERT_NULL(node1.link.prev);
86+
TEST_ASSERT_EQUAL(&node3.link, node2.link.next);
87+
TEST_ASSERT_EQUAL(&node1.link, node2.link.prev);
88+
TEST_ASSERT_NULL(node3.link.next);
89+
TEST_ASSERT_EQUAL(&node2.link, node3.link.prev);
90+
91+
// Test 8: Delist head
92+
delist(&list, &node1.link);
93+
TEST_ASSERT_EQUAL(&node2.link, list.head);
94+
TEST_ASSERT_EQUAL(&node3.link, list.tail);
95+
TEST_ASSERT_NULL(node1.link.next);
96+
TEST_ASSERT_NULL(node1.link.prev);
97+
98+
// Test 9: Delist tail
99+
delist(&list, &node3.link);
100+
TEST_ASSERT_EQUAL(&node2.link, list.head);
101+
TEST_ASSERT_EQUAL(&node2.link, list.tail);
102+
TEST_ASSERT_NULL(node2.link.next);
103+
TEST_ASSERT_NULL(node2.link.prev);
104+
TEST_ASSERT_NULL(node3.link.next);
105+
TEST_ASSERT_NULL(node3.link.prev);
106+
107+
// Test 10: Delist last item
108+
delist(&list, &node2.link);
109+
TEST_ASSERT_NULL(list.head);
110+
TEST_ASSERT_NULL(list.tail);
111+
TEST_ASSERT_NULL(node2.link.next);
112+
TEST_ASSERT_NULL(node2.link.prev);
113+
114+
// Test 11: Delist from empty list (should be safe)
115+
delist(&list, &node1.link);
116+
TEST_ASSERT_NULL(list.head);
117+
TEST_ASSERT_NULL(list.tail);
118+
119+
// Test 12: LIST_MEMBER macro
120+
enlist_head(&list, &node1.link);
121+
enlist_head(&list, &node2.link);
122+
enlist_head(&list, &node3.link);
123+
test_node_t* owner = LIST_MEMBER(list.head, test_node_t, link);
124+
TEST_ASSERT_EQUAL(&node3, owner);
125+
TEST_ASSERT_EQUAL(3, owner->value);
126+
127+
// Test 13: LIST_TAIL macro
128+
test_node_t* tail_owner = LIST_TAIL(list, test_node_t, link);
129+
TEST_ASSERT_EQUAL(&node1, tail_owner);
130+
TEST_ASSERT_EQUAL(1, tail_owner->value);
131+
132+
// Test 14: LIST_MEMBER with NULL
133+
test_node_t* null_owner = LIST_MEMBER(NULL, test_node_t, link);
134+
TEST_ASSERT_NULL(null_owner);
135+
136+
// Test 15: Traverse list from head to tail
137+
test_node_t* current = LIST_MEMBER(list.head, test_node_t, link);
138+
TEST_ASSERT_EQUAL(3, current->value);
139+
current = LIST_MEMBER(current->link.next, test_node_t, link);
140+
TEST_ASSERT_EQUAL(2, current->value);
141+
current = LIST_MEMBER(current->link.next, test_node_t, link);
142+
TEST_ASSERT_EQUAL(1, current->value);
143+
current = LIST_MEMBER(current->link.next, test_node_t, link);
144+
TEST_ASSERT_NULL(current);
145+
146+
// Clean up
147+
delist(&list, &node1.link);
148+
delist(&list, &node2.link);
149+
delist(&list, &node3.link);
150+
TEST_ASSERT_NULL(list.head);
151+
TEST_ASSERT_NULL(list.tail);
152+
}
153+
154+
void setUp(void) {}
155+
156+
void tearDown(void) {}
157+
158+
int main(void)
159+
{
160+
UNITY_BEGIN();
161+
RUN_TEST(test_crc);
162+
RUN_TEST(test_list);
163+
return UNITY_END();
164+
}

tests/src/test_intrusive_tx.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,8 @@ static void test_tx_spool_single_frame_default_mtu(void)
218218
(udpard_bytes_t){ .size = UDPARD_MTU_DEFAULT_MAX_SINGLE_FRAME + 1, .data = payload },
219219
NULL);
220220
TEST_ASSERT_EQUAL(2 * 2ULL, alloc.allocated_fragments);
221-
TEST_ASSERT_EQUAL((sizeof(udpard_tx_item_t) + HEADER_SIZE_BYTES) * 2 + UDPARD_MTU_DEFAULT_MAX_SINGLE_FRAME + 1 +
222-
CRC_SIZE_BYTES,
221+
TEST_ASSERT_EQUAL(((sizeof(udpard_tx_item_t) + HEADER_SIZE_BYTES) * 2) + UDPARD_MTU_DEFAULT_MAX_SINGLE_FRAME +
222+
1 + CRC_SIZE_BYTES,
223223
alloc.allocated_bytes);
224224
TEST_ASSERT_EQUAL(2, chain.count);
225225
TEST_ASSERT_NOT_EQUAL(chain.head, chain.tail);
@@ -257,7 +257,7 @@ static void test_tx_spool_three_frames(void)
257257
(udpard_bytes_t){ .size = ethereal_strength_size, .data = ethereal_strength },
258258
&user_transfer_referent);
259259
TEST_ASSERT_EQUAL(3 * 2ULL, alloc.allocated_fragments);
260-
TEST_ASSERT_EQUAL(3 * (sizeof(udpard_tx_item_t) + HEADER_SIZE_BYTES) + ethereal_strength_size + 4U,
260+
TEST_ASSERT_EQUAL((3 * (sizeof(udpard_tx_item_t) + HEADER_SIZE_BYTES)) + ethereal_strength_size + 4U,
261261
alloc.allocated_bytes);
262262
TEST_ASSERT_EQUAL(3, chain.count);
263263
udpard_tx_item_t* const first = chain.head;
@@ -329,7 +329,7 @@ static void test_tx_spool_crc_spill_1_byte(void)
329329
(udpard_bytes_t){ .size = interstellar_war_size, .data = interstellar_war },
330330
NULL);
331331
TEST_ASSERT_EQUAL(2 * 2ULL, alloc.allocated_fragments);
332-
TEST_ASSERT_EQUAL(2 * (sizeof(udpard_tx_item_t) + HEADER_SIZE_BYTES) + interstellar_war_size + 4U,
332+
TEST_ASSERT_EQUAL((2 * (sizeof(udpard_tx_item_t) + HEADER_SIZE_BYTES)) + interstellar_war_size + 4U,
333333
alloc.allocated_bytes);
334334
TEST_ASSERT_EQUAL(2, chain.count);
335335
// First frame contains payload + first 3 bytes of CRC
@@ -926,7 +926,7 @@ static void test_tx_deadline_at_current_time(void)
926926
0x1122334455667788ULL,
927927
123,
928928
0xBADC0FFEE0DDF00DULL,
929-
(udpard_bytes_t){.size = test_payload_size, .data = test_payload},
929+
(udpard_bytes_t){ .size = test_payload_size, .data = test_payload },
930930
false,
931931
NULL);
932932
TEST_ASSERT_EQUAL(0, enqueued); // Should return 0 (rejected)
@@ -939,7 +939,7 @@ static void test_tx_deadline_at_current_time(void)
939939
0x1122334455667788ULL,
940940
123,
941941
0xBADC0FFEE0DDF00DULL,
942-
(udpard_bytes_t){.size = test_payload_size, .data = test_payload},
942+
(udpard_bytes_t){ .size = test_payload_size, .data = test_payload },
943943
false,
944944
NULL);
945945
TEST_ASSERT_EQUAL(1, enqueued); // Should succeed
@@ -949,10 +949,10 @@ static void test_tx_deadline_at_current_time(void)
949949
2000000, // now
950950
1999999, // deadline in the past
951951
0xFEDCBA9876543210ULL,
952-
(udpard_udpip_ep_t){.ip = 0xC0A80101, .port = 9999},
952+
(udpard_udpip_ep_t){ .ip = 0xC0A80101, .port = 9999 },
953953
udpard_prio_high,
954954
0x0BADC0DE0BADC0DEULL,
955-
(udpard_bytes_t){.size = test_payload_size, .data = test_payload},
955+
(udpard_bytes_t){ .size = test_payload_size, .data = test_payload },
956956
false,
957957
NULL);
958958
TEST_ASSERT_EQUAL(0, enqueued); // Should return 0 (rejected)

0 commit comments

Comments
 (0)