390 lines
11 KiB
C
390 lines
11 KiB
C
#include "check.h"
|
|
#include "../../src/femtotcp.c"
|
|
#include <stdlib.h> /* for random() */
|
|
|
|
/* pseudo random number generator to mock the random number generator */
|
|
uint32_t ipstack_getrandom(void)
|
|
{
|
|
unsigned int seed = 0xDAC0FFEE;
|
|
srandom(seed);
|
|
return random();
|
|
}
|
|
|
|
uint8_t mem[8 * 1024];
|
|
uint32_t memsz = 8 * 1024;
|
|
|
|
START_TEST(test_fifo_init)
|
|
{
|
|
struct fifo f;
|
|
fifo_init(&f, mem, memsz);
|
|
ck_assert_int_eq(fifo_len(&f), 0);
|
|
ck_assert_int_eq(fifo_space(&f), memsz);
|
|
ck_assert_int_eq(fifo_len(&f), 0);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_fifo_push_and_pop) {
|
|
struct fifo f;
|
|
struct pkt_desc *desc, *desc2;
|
|
uint8_t data[] = {1, 2, 3, 4, 5};
|
|
|
|
fifo_init(&f, mem, memsz);
|
|
|
|
ck_assert_int_eq(fifo_space(&f), memsz);
|
|
// Test push
|
|
ck_assert_int_eq(fifo_push(&f, data, sizeof(data)), 0);
|
|
|
|
// Test peek
|
|
desc = fifo_peek(&f);
|
|
ck_assert_ptr_nonnull(desc);
|
|
ck_assert_int_eq(desc->len, sizeof(data));
|
|
ck_assert_mem_eq(f.data + desc->pos + sizeof(struct pkt_desc), data, sizeof(data));
|
|
desc2 = fifo_peek(&f);
|
|
ck_assert_ptr_nonnull(desc2);
|
|
ck_assert_ptr_eq(desc, desc2);
|
|
ck_assert_int_eq(fifo_len(&f), desc->len + sizeof(struct pkt_desc));
|
|
|
|
|
|
// Test pop
|
|
desc = fifo_pop(&f);
|
|
ck_assert_int_eq(fifo_space(&f), memsz);
|
|
ck_assert_ptr_nonnull(desc);
|
|
ck_assert_int_eq(desc->len, sizeof(data));
|
|
ck_assert_mem_eq(f.data + desc->pos + sizeof(struct pkt_desc), data, sizeof(data));
|
|
ck_assert_int_eq(fifo_len(&f), 0);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_fifo_push_and_pop_multiple) {
|
|
struct fifo f;
|
|
uint8_t data[] = {1, 2, 3, 4, 5};
|
|
uint8_t data2[] = {6, 7, 8, 9, 10};
|
|
|
|
fifo_init(&f, mem, memsz);
|
|
ck_assert_int_eq(fifo_space(&f), memsz);
|
|
|
|
// Test push
|
|
ck_assert_int_eq(fifo_push(&f, data, sizeof(data)), 0);
|
|
ck_assert_int_eq(fifo_len(&f), sizeof(data) + sizeof(struct pkt_desc));
|
|
ck_assert_int_eq(fifo_space(&f), f.size - (sizeof(data) + sizeof(struct pkt_desc)));
|
|
ck_assert_int_eq(fifo_push(&f, data2, sizeof(data2)), 0);
|
|
|
|
// Test pop
|
|
struct pkt_desc *desc = fifo_pop(&f);
|
|
ck_assert_ptr_nonnull(desc);
|
|
ck_assert_int_eq(desc->len, sizeof(data));
|
|
ck_assert_mem_eq(f.data + desc->pos + sizeof(struct pkt_desc), data, sizeof(data));
|
|
|
|
desc = fifo_pop(&f);
|
|
ck_assert_ptr_nonnull(desc);
|
|
ck_assert_int_eq(desc->len, sizeof(data2));
|
|
ck_assert_mem_eq(f.data + desc->pos + sizeof(struct pkt_desc), data2, sizeof(data2));
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_fifo_pop_success) {
|
|
struct fifo f;
|
|
uint8_t data[] = {1, 2, 3, 4};
|
|
fifo_init(&f, mem, memsz);
|
|
fifo_push(&f, data, sizeof(data)); // Add data to FIFO
|
|
|
|
struct pkt_desc *desc = fifo_pop(&f);
|
|
ck_assert_ptr_nonnull(desc); // Ensure we got a valid descriptor
|
|
ck_assert_int_eq(desc->len, sizeof(data)); // Check length
|
|
ck_assert_mem_eq(f.data + desc->pos + sizeof(struct pkt_desc), data, sizeof(data)); // Check data
|
|
}
|
|
|
|
START_TEST(test_fifo_pop_empty) {
|
|
struct fifo f;
|
|
fifo_init(&f, mem, memsz);
|
|
|
|
struct pkt_desc *desc = fifo_pop(&f);
|
|
ck_assert_ptr_eq(desc, NULL); // Ensure pop returns NULL on empty FIFO
|
|
}
|
|
|
|
START_TEST(test_fifo_push_full) {
|
|
struct fifo f;
|
|
uint8_t data[8 * 1024] = {1, 2, 3, 4};
|
|
int ret;
|
|
fifo_init(&f, mem, memsz);
|
|
fifo_push(&f, data, sizeof(data)); // Add data to FIFO
|
|
|
|
ret = fifo_push(&f, data, sizeof(data));
|
|
ck_assert_int_eq(ret, -1); // Ensure push returns -1 when FIFO is full
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_fifo_push_wrap) {
|
|
struct fifo f;
|
|
uint8_t buffer[100];
|
|
uint8_t data[] = {1, 2, 3, 4};
|
|
int ret;
|
|
fifo_init(&f, buffer, sizeof(buffer));
|
|
fifo_push(&f, data, sizeof(data)); // Add data to FIFO
|
|
|
|
// Pop the data to make space
|
|
struct pkt_desc *desc = fifo_pop(&f);
|
|
ck_assert_ptr_nonnull(desc);
|
|
|
|
// Push data to wrap around the buffer
|
|
ret = fifo_push(&f, data, sizeof(data));
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(desc->len, sizeof(data));
|
|
ck_assert_mem_eq(f.data + desc->pos + sizeof(struct pkt_desc), data, sizeof(data));
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_fifo_push_wrap_multiple) {
|
|
struct fifo f;
|
|
uint8_t data[] = {1, 2, 3, 4};
|
|
uint8_t data2[] = {5, 6, 7, 8, 9};
|
|
int ret;
|
|
fifo_init(&f, mem, memsz);
|
|
fifo_push(&f, data, sizeof(data)); // Add data to FIFO
|
|
|
|
// Pop the data to make space
|
|
struct pkt_desc *desc = fifo_pop(&f);
|
|
ck_assert_ptr_nonnull(desc);
|
|
|
|
// Push data to wrap around the buffer
|
|
ret = fifo_push(&f, data, sizeof(data));
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(desc->len, sizeof(data));
|
|
ck_assert_mem_eq(f.data + desc->pos + sizeof(struct pkt_desc), data, sizeof(data));
|
|
|
|
// Push more data to wrap around the buffer
|
|
ret = fifo_push(&f, data2, sizeof(data2));
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(fifo_len(&f), sizeof(data2) + sizeof(data) + 2 * sizeof(struct pkt_desc));
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_fifo_next_success) {
|
|
struct fifo f;
|
|
uint8_t data1[] = {1, 2, 3, 4};
|
|
uint8_t data2[] = {5, 6, 7, 8, 9};
|
|
|
|
fifo_init(&f, mem, memsz);
|
|
|
|
// Add two packets to the FIFO
|
|
fifo_push(&f, data1, sizeof(data1));
|
|
fifo_push(&f, data2, sizeof(data2));
|
|
ck_assert_int_eq(fifo_len(&f), sizeof(data1) + sizeof(data2) + 2 * sizeof(struct pkt_desc));
|
|
|
|
// Get the first packet descriptor
|
|
struct pkt_desc *desc = fifo_peek(&f);
|
|
ck_assert_ptr_nonnull(desc);
|
|
|
|
// Get the next packet descriptor using fifo_next
|
|
struct pkt_desc *next_desc = fifo_next(&f, desc);
|
|
ck_assert_ptr_nonnull(next_desc); // Ensure next descriptor is valid
|
|
ck_assert_int_eq(next_desc->len, sizeof(data2)); // Check length of next packet
|
|
}
|
|
|
|
START_TEST(test_fifo_next_empty_fifo) {
|
|
struct fifo f;
|
|
fifo_init(&f, mem, memsz);
|
|
|
|
// Start with an empty FIFO
|
|
struct pkt_desc *desc = NULL;
|
|
struct pkt_desc *next_desc = fifo_next(&f, desc);
|
|
ck_assert_ptr_eq(next_desc, NULL); // Ensure next returns NULL on empty FIFO
|
|
}
|
|
|
|
START_TEST(test_fifo_next_end_of_fifo) {
|
|
struct fifo f;
|
|
uint8_t data[] = {1, 2, 3, 4};
|
|
|
|
fifo_init(&f, mem, memsz);
|
|
fifo_push(&f, data, sizeof(data));
|
|
|
|
struct pkt_desc *desc = fifo_peek(&f); // Get first packet
|
|
fifo_pop(&f); // Simulate removing the packet
|
|
struct pkt_desc *next_desc = fifo_next(&f, desc);
|
|
ck_assert_ptr_eq(next_desc, NULL); // Should return NULL as there are no more packets
|
|
}
|
|
END_TEST
|
|
START_TEST(test_queue_init) {
|
|
struct queue q;
|
|
queue_init(&q, mem, memsz, 0x12345678);
|
|
ck_assert_int_eq(q.size, memsz);
|
|
ck_assert_ptr_eq(q.data, mem);
|
|
ck_assert_int_eq(q.head, 0);
|
|
ck_assert_int_eq(q.tail, 0);
|
|
ck_assert_int_eq(q.seq_base, 0x12345678);
|
|
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_queue_space_empty) {
|
|
struct queue q;
|
|
|
|
queue_init(&q, mem, memsz, 0x12345678);
|
|
ck_assert_int_eq(queue_space(&q), memsz); // Full space should be available
|
|
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_queue_len_empty) {
|
|
struct queue q;
|
|
|
|
queue_init(&q, mem, memsz, 0x12345678);
|
|
ck_assert_int_eq(queue_len(&q), 0); // No bytes should be in use
|
|
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_queue_partial_fill) {
|
|
struct queue q;
|
|
queue_init(&q, mem, memsz, 0x12345678);
|
|
q.head = 256; // Simulate adding 256 bytes of data
|
|
ck_assert_int_eq(queue_space(&q), memsz - 256);
|
|
ck_assert_int_eq(queue_len(&q), 256);
|
|
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_queue_wrap_around) {
|
|
struct queue q;
|
|
queue_init(&q, mem, memsz, 0x12345678);
|
|
q.head = 800;
|
|
q.tail = 200; // Head has wrapped around, so 600 bytes are filled
|
|
ck_assert_int_eq(queue_space(&q), q.size - 600);
|
|
ck_assert_int_eq(queue_len(&q), 600); // 600 bytes filled
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_queue_insert_empty) {
|
|
struct queue q;
|
|
queue_init(&q, mem, memsz, 0x12345678);
|
|
uint8_t data[] = {1, 2, 3, 4};
|
|
|
|
int res = queue_insert(&q, data, 0, sizeof(data));
|
|
ck_assert_int_eq(res, 0);
|
|
ck_assert_int_eq(queue_len(&q), sizeof(data));
|
|
ck_assert_int_eq(q.head, sizeof(data));
|
|
ck_assert_mem_eq(q.data, data, sizeof(data));
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_queue_insert_sequential) {
|
|
struct queue q;
|
|
queue_init(&q, mem, memsz, 0x12345678);
|
|
uint8_t data1[] = {1, 2};
|
|
uint8_t data2[] = {3, 4};
|
|
|
|
int res1 = queue_insert(&q, data1, 0, sizeof(data1));
|
|
int res2 = queue_insert(&q, data2, 2, sizeof(data2));
|
|
ck_assert_int_eq(res1, 0);
|
|
ck_assert_int_eq(res2, 0);
|
|
ck_assert_int_eq(queue_len(&q), sizeof(data1) + sizeof(data2));
|
|
ck_assert_mem_eq(q.data, data1, sizeof(data1));
|
|
ck_assert_mem_eq(q.data + 2, data2, sizeof(data2));
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_queue_pop) {
|
|
struct queue q;
|
|
queue_init(&q, mem, memsz, 0x12345678);
|
|
uint8_t data[] = {5, 6, 7, 8};
|
|
uint8_t out[4];
|
|
|
|
queue_insert(&q, data, 0, sizeof(data));
|
|
int len = queue_pop(&q, out, sizeof(out));
|
|
ck_assert_int_eq(len, sizeof(out));
|
|
ck_assert_mem_eq(out, data, sizeof(data));
|
|
ck_assert_int_eq(queue_len(&q), 0);
|
|
ck_assert_int_eq(q.tail, 4);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_queue_pop_wraparound) {
|
|
struct queue q;
|
|
queue_init(&q, mem, memsz, 0x12345678);
|
|
uint8_t data[] = {9, 10, 11, 12};
|
|
uint8_t out[4];
|
|
|
|
q.head = memsz - 1;
|
|
q.tail = memsz - 1;
|
|
queue_insert(&q, data, 0, sizeof(data));
|
|
int len = queue_pop(&q, out, sizeof(out));
|
|
ck_assert_int_eq(len, sizeof(out));
|
|
ck_assert_mem_eq(out, data, sizeof(data));
|
|
ck_assert_int_eq(queue_len(&q), 0);
|
|
}
|
|
END_TEST
|
|
|
|
|
|
Suite *femto_suite(void)
|
|
{
|
|
Suite *s;
|
|
TCase *tc_core, *tc_proto;
|
|
|
|
s = suite_create("FemtoTCP");
|
|
tc_core = tcase_create("Core");
|
|
tc_proto = tcase_create("Protocols");
|
|
|
|
tcase_add_test(tc_core, test_fifo_init);
|
|
suite_add_tcase(s, tc_core);
|
|
suite_add_tcase(s, tc_proto);
|
|
|
|
tcase_add_test(tc_core, test_fifo_push_and_pop);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_fifo_push_and_pop_multiple);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_fifo_pop_success);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_fifo_pop_empty);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_fifo_push_full);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_fifo_push_wrap);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_fifo_push_wrap_multiple);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_fifo_next_success);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_fifo_next_empty_fifo);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_fifo_next_end_of_fifo);
|
|
suite_add_tcase(s, tc_core);
|
|
|
|
tcase_add_test(tc_core, test_queue_init);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_queue_space_empty);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_queue_len_empty);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_queue_partial_fill);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_queue_wrap_around);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_queue_insert_empty);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_queue_insert_sequential);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_queue_pop);
|
|
suite_add_tcase(s, tc_core);
|
|
tcase_add_test(tc_core, test_queue_pop_wraparound);
|
|
suite_add_tcase(s, tc_core);
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
|
|
int main(void)
|
|
{
|
|
int n_fail = 0;
|
|
Suite *s;
|
|
SRunner *sr;
|
|
|
|
s = femto_suite();
|
|
sr = srunner_create(s);
|
|
|
|
srunner_run_all(sr, CK_NORMAL);
|
|
n_fail = srunner_ntests_failed(sr);
|
|
srunner_free(sr);
|
|
return (n_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
|
|
}
|