Skip to content
Merged
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 tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set(DMOD_AUTHOR_NAME "Patryk Kubiak")
set(DMOD_STACK_SIZE 1024)
set(DMOD_PRIORITY 0)

dmod_add_executable(${DMOD_MODULE_NAME} ${DMOD_MODULE_VERSION}
dmod_add_test(${DMOD_MODULE_NAME} ${DMOD_MODULE_VERSION}
test_dm_sw_ring.c
)

Expand Down
281 changes: 92 additions & 189 deletions tests/test_dm_sw_ring.c
Original file line number Diff line number Diff line change
@@ -1,257 +1,160 @@
#define DMOD_ENABLE_REGISTRATION ON
#include "dmod.h"
#include "dmod_test.h"
#include "dm_sw_ring.h"
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

static int g_failures = 0;
// ============================================================================
// Shared test state
// ============================================================================

#define EXPECT_TRUE(expr) \
do \
{ \
if (!(expr)) \
{ \
DMOD_LOG_ERROR("Expectation failed: %s at %s:%d\n", #expr, __FILE__, __LINE__); \
g_failures++; \
} \
} while (0)
static const dm_sw_ring_flags_t g_flags =
dm_sw_ring_flags_drop_old_data | dm_sw_ring_flags_mutex_sync;

#define EXPECT_EQ_U32(actual, expected) \
do \
{ \
uint32_t _actual = (uint32_t)(actual); \
uint32_t _expected = (uint32_t)(expected); \
if (_actual != _expected) \
{ \
DMOD_LOG_ERROR("Expectation failed: %s == %s (actual=%u expected=%u) at %s:%d\n", \
#actual, #expected, _actual, _expected, __FILE__, __LINE__); \
g_failures++; \
} \
} while (0)
#define EXPECT_EQ_I32(actual, expected) \
do \
{ \
int32_t _actual = (int32_t)(actual); \
int32_t _expected = (int32_t)(expected); \
if (_actual != _expected) \
{ \
DMOD_LOG_ERROR("Expectation failed: %s == %s (actual=%d expected=%d) at %s:%d\n", \
#actual, #expected, _actual, _expected, __FILE__, __LINE__); \
g_failures++; \
} \
} while (0)
#define EXPECT_EQ_BOOL(actual, expected) \
do \
{ \
bool _actual = ((actual) ? true : false); \
bool _expected = ((expected) ? true : false); \
if (_actual != _expected) \
{ \
DMOD_LOG_ERROR("Expectation failed: %s == %s (actual=%d expected=%d) at %s:%d\n", \
#actual, #expected, (int)_actual, (int)_expected, __FILE__, __LINE__); \
g_failures++; \
} \
} while (0)
#define EXPECT_EQ_U8(actual, expected) \
do \
{ \
uint8_t _actual = (uint8_t)(actual); \
uint8_t _expected = (uint8_t)(expected); \
if (_actual != _expected) \
{ \
DMOD_LOG_ERROR("Expectation failed: %s == %s (actual=%u expected=%u) at %s:%d\n", \
#actual, #expected, _actual, _expected, __FILE__, __LINE__); \
g_failures++; \
} \
} while (0)
static dm_sw_ring_t g_ring = NULL;
static uint8_t g_io_buf[8];

typedef struct test_context
{
dm_sw_ring_t ring;
dm_sw_ring_flags_t ring_flags;
uint8_t io_buffer[8];
} test_context_t;

typedef void (*test_setup_fn)(test_context_t* context);
typedef void (*test_step_fn)(test_context_t* context);
typedef void (*test_teardown_fn)(test_context_t* context);
// ============================================================================
// Lifecycle hooks
// ============================================================================

static void setup_ring_capacity_4(test_context_t* context)
void dmod_test_setup(void)
{
context->ring = dm_sw_ring_create(4, context->ring_flags);
EXPECT_TRUE(context->ring != NULL);
g_ring = dm_sw_ring_create(4, g_flags);
memset(g_io_buf, 0, sizeof(g_io_buf));
}

static void teardown_ring(test_context_t* context)
void dmod_test_teardown(void)
{
if (context->ring != NULL)
if (g_ring != NULL)
{
dm_sw_ring_destroy(context->ring);
context->ring = NULL;
dm_sw_ring_destroy(g_ring);
g_ring = NULL;
}
}

static void run_test_step(const char* name, test_context_t* context, test_setup_fn setup, test_step_fn step, test_teardown_fn teardown)
{
int failures_before = g_failures;
DMOD_LOG_STEP_BEGIN("%s\n", name);
// ============================================================================
// Test steps
// ============================================================================

if (setup != NULL)
{
setup(context);
}
if (step != NULL && context->ring != NULL)
{
step(context);
}
if (teardown != NULL)
{
teardown(context);
}
DMOD_TEST_STEP(dm_sw_ring_create)
{
/* The ring created by setup is not needed for this test */
dm_sw_ring_destroy(g_ring);
g_ring = NULL;

DMOD_LOG_STEP((g_failures > failures_before) ? 1 : 0, "%s\n", name);
}
dm_sw_ring_t ring = dm_sw_ring_create(4, g_flags);
DMOD_TEST_EXPECT_NOT_NULL(ring);
DMOD_TEST_EXPECT_NULL(dm_sw_ring_create(0, g_flags));

static void test_create_step(test_context_t* context)
{
dm_sw_ring_t ring = dm_sw_ring_create(4, context->ring_flags);
EXPECT_TRUE(ring != NULL);
EXPECT_TRUE(dm_sw_ring_create(0, context->ring_flags) == NULL);
if (ring != NULL)
{
dm_sw_ring_destroy(ring);
}
}

static void test_destroy_step(test_context_t* context)
DMOD_TEST_STEP(dm_sw_ring_destroy)
{
EXPECT_TRUE(context->ring != NULL);
dm_sw_ring_destroy(context->ring);
context->ring = NULL;
DMOD_TEST_EXPECT_NOT_NULL(g_ring);
dm_sw_ring_destroy(g_ring);
g_ring = NULL; /* prevent double-free in teardown */
}

static void test_write_step(test_context_t* context)
DMOD_TEST_STEP(dm_sw_ring_write)
{
const uint8_t data[] = {10, 11, 12, 13, 14};
EXPECT_EQ_U32(dm_sw_ring_write(context->ring, NULL, 1), 0);
EXPECT_EQ_U32(dm_sw_ring_size(context->ring), 0);
EXPECT_EQ_U32(dm_sw_ring_write(context->ring, data, 5), 5);
EXPECT_EQ_U32(dm_sw_ring_size(context->ring), 4);

DMOD_TEST_EXPECT_EQ(dm_sw_ring_write(g_ring, NULL, 1), 0u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_size(g_ring), 0u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_write(g_ring, data, 5), 5u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_size(g_ring), 4u);
}

static void test_read_step(test_context_t* context)
DMOD_TEST_STEP(dm_sw_ring_read)
{
const uint8_t data[] = {1, 2, 3};
memset(context->io_buffer, 0, sizeof(context->io_buffer));
EXPECT_EQ_U32(dm_sw_ring_write(context->ring, data, 3), 3);
EXPECT_EQ_U32(dm_sw_ring_read(context->ring, NULL, 1), 0);
EXPECT_EQ_U32(dm_sw_ring_size(context->ring), 3);
EXPECT_EQ_U32(dm_sw_ring_read(context->ring, context->io_buffer, 2), 2);
EXPECT_EQ_U8(context->io_buffer[0], 1);
EXPECT_EQ_U8(context->io_buffer[1], 2);

DMOD_TEST_EXPECT_EQ(dm_sw_ring_write(g_ring, data, 3), 3u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_read(g_ring, NULL, 1), 0u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_size(g_ring), 3u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_read(g_ring, g_io_buf, 2), 2u);
DMOD_TEST_EXPECT_EQ(g_io_buf[0], 1u);
DMOD_TEST_EXPECT_EQ(g_io_buf[1], 2u);
}

static void test_capacity_step(test_context_t* context)
DMOD_TEST_STEP(dm_sw_ring_capacity)
{
EXPECT_EQ_U32(dm_sw_ring_capacity(context->ring), 4);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_capacity(g_ring), 4u);
}

static void test_size_step(test_context_t* context)
DMOD_TEST_STEP(dm_sw_ring_size)
{
const uint8_t data[] = {1, 2, 3};
EXPECT_EQ_U32(dm_sw_ring_size(context->ring), 0);
EXPECT_EQ_U32(dm_sw_ring_write(context->ring, data, 3), 3);
EXPECT_EQ_U32(dm_sw_ring_size(context->ring), 3);
EXPECT_EQ_U32(dm_sw_ring_discard(context->ring, 1), 1);
EXPECT_EQ_U32(dm_sw_ring_size(context->ring), 2);

DMOD_TEST_EXPECT_EQ(dm_sw_ring_size(g_ring), 0u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_write(g_ring, data, 3), 3u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_size(g_ring), 3u);
DMOD_TEST_EXPECT_EQ((uint32_t)dm_sw_ring_discard(g_ring, 1), 1u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_size(g_ring), 2u);
}

static void test_available_space_step(test_context_t* context)
DMOD_TEST_STEP(dm_sw_ring_available_space)
{
const uint8_t data[] = {1, 2, 3};
EXPECT_EQ_U32(dm_sw_ring_available_space(context->ring), 4);
EXPECT_EQ_U32(dm_sw_ring_write(context->ring, data, 3), 3);
EXPECT_EQ_U32(dm_sw_ring_available_space(context->ring), 1);

DMOD_TEST_EXPECT_EQ(dm_sw_ring_available_space(g_ring), 4u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_write(g_ring, data, 3), 3u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_available_space(g_ring), 1u);
}

static void test_peek_step(test_context_t* context)
DMOD_TEST_STEP(dm_sw_ring_peek)
{
const uint8_t data[] = {1, 2, 3, 4};
memset(context->io_buffer, 0, sizeof(context->io_buffer));
EXPECT_EQ_U32(dm_sw_ring_write(context->ring, data, 4), 4);
EXPECT_EQ_I32(dm_sw_ring_peek(context->ring, NULL, 1), -1);
EXPECT_EQ_I32(dm_sw_ring_peek(context->ring, context->io_buffer, 4), 4);
EXPECT_EQ_U8(context->io_buffer[0], 1);
EXPECT_EQ_U8(context->io_buffer[3], 4);
EXPECT_EQ_U32(dm_sw_ring_size(context->ring), 4);

DMOD_TEST_EXPECT_EQ(dm_sw_ring_write(g_ring, data, 4), 4u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_peek(g_ring, NULL, 1), -1);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_peek(g_ring, g_io_buf, 4), 4);
DMOD_TEST_EXPECT_EQ(g_io_buf[0], 1u);
DMOD_TEST_EXPECT_EQ(g_io_buf[3], 4u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_size(g_ring), 4u);
}

static void test_discard_step(test_context_t* context)
DMOD_TEST_STEP(dm_sw_ring_discard)
{
const uint8_t data[] = {4, 5, 6};
EXPECT_EQ_U32(dm_sw_ring_write(context->ring, data, 3), 3);
EXPECT_EQ_I32(dm_sw_ring_discard(context->ring, 0), 0);
EXPECT_EQ_I32(dm_sw_ring_discard(context->ring, 1), 1);
EXPECT_EQ_U32(dm_sw_ring_size(context->ring), 2);

DMOD_TEST_EXPECT_EQ(dm_sw_ring_write(g_ring, data, 3), 3u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_discard(g_ring, 0), 0);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_discard(g_ring, 1), 1);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_size(g_ring), 2u);
}

static void test_clear_step(test_context_t* context)
DMOD_TEST_STEP(dm_sw_ring_clear)
{
const uint8_t data[] = {1, 2, 3, 4};
EXPECT_EQ_U32(dm_sw_ring_write(context->ring, data, 4), 4);
EXPECT_EQ_I32(dm_sw_ring_clear(context->ring), 0);
EXPECT_EQ_U32(dm_sw_ring_size(context->ring), 0);

DMOD_TEST_EXPECT_EQ(dm_sw_ring_write(g_ring, data, 4), 4u);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_clear(g_ring), 0);
DMOD_TEST_EXPECT_EQ(dm_sw_ring_size(g_ring), 0u);
}

static void test_is_full_step(test_context_t* context)
DMOD_TEST_STEP(dm_sw_ring_is_full)
{
const uint8_t data[] = {1, 2, 3, 4};
EXPECT_EQ_BOOL(dm_sw_ring_is_full(context->ring), false);
EXPECT_EQ_U32(dm_sw_ring_write(context->ring, data, 4), 4);
EXPECT_EQ_BOOL(dm_sw_ring_is_full(context->ring), true);
}

static void test_is_empty_step(test_context_t* context)
{
const uint8_t data[] = {1};
EXPECT_EQ_BOOL(dm_sw_ring_is_empty(context->ring), true);
EXPECT_EQ_U32(dm_sw_ring_write(context->ring, data, 1), 1);
EXPECT_EQ_BOOL(dm_sw_ring_is_empty(context->ring), false);
EXPECT_EQ_U32(dm_sw_ring_read(context->ring, context->io_buffer, 1), 1);
EXPECT_EQ_BOOL(dm_sw_ring_is_empty(context->ring), true);
DMOD_TEST_EXPECT_FALSE(dm_sw_ring_is_full(g_ring));
DMOD_TEST_EXPECT_EQ(dm_sw_ring_write(g_ring, data, 4), 4u);
DMOD_TEST_EXPECT_TRUE(dm_sw_ring_is_full(g_ring));
}

int main(int argc, char** argv)
DMOD_TEST_STEP(dm_sw_ring_is_empty)
{
(void)argc;
(void)argv;

test_context_t context = {
.ring = NULL,
.ring_flags = dm_sw_ring_flags_drop_old_data | dm_sw_ring_flags_mutex_sync,
.io_buffer = {0}
};

run_test_step("dm_sw_ring_create", &context, NULL, test_create_step, NULL);
run_test_step("dm_sw_ring_destroy", &context, setup_ring_capacity_4, test_destroy_step, teardown_ring);
run_test_step("dm_sw_ring_write", &context, setup_ring_capacity_4, test_write_step, teardown_ring);
run_test_step("dm_sw_ring_read", &context, setup_ring_capacity_4, test_read_step, teardown_ring);
run_test_step("dm_sw_ring_capacity", &context, setup_ring_capacity_4, test_capacity_step, teardown_ring);
run_test_step("dm_sw_ring_size", &context, setup_ring_capacity_4, test_size_step, teardown_ring);
run_test_step("dm_sw_ring_available_space", &context, setup_ring_capacity_4, test_available_space_step, teardown_ring);
run_test_step("dm_sw_ring_peek", &context, setup_ring_capacity_4, test_peek_step, teardown_ring);
run_test_step("dm_sw_ring_discard", &context, setup_ring_capacity_4, test_discard_step, teardown_ring);
run_test_step("dm_sw_ring_clear", &context, setup_ring_capacity_4, test_clear_step, teardown_ring);
run_test_step("dm_sw_ring_is_full", &context, setup_ring_capacity_4, test_is_full_step, teardown_ring);
run_test_step("dm_sw_ring_is_empty", &context, setup_ring_capacity_4, test_is_empty_step, teardown_ring);

if (g_failures == 0)
{
DMOD_LOG_INFO("All dm_sw_ring API checks passed\n");
return 0;
}
const uint8_t data[] = {1};

DMOD_LOG_ERROR("dm_sw_ring API checks failed: %d\n", g_failures);
return 1;
DMOD_TEST_EXPECT_TRUE(dm_sw_ring_is_empty(g_ring));
DMOD_TEST_EXPECT_EQ(dm_sw_ring_write(g_ring, data, 1), 1u);
DMOD_TEST_EXPECT_FALSE(dm_sw_ring_is_empty(g_ring));
DMOD_TEST_EXPECT_EQ(dm_sw_ring_read(g_ring, g_io_buf, 1), 1u);
DMOD_TEST_EXPECT_TRUE(dm_sw_ring_is_empty(g_ring));
}

Loading