35#include "lexleo_cmocka.h"
43typedef struct fake_logger_backend_t {
50 const char *last_message;
54} fake_logger_backend_t;
56static void fake_logger_backend_reset(fake_logger_backend_t *b) {
59 b->destroy_called = 0;
60 b->last_backend = NULL;
61 b->last_message = NULL;
65static logger_status_t fake_logger_log(
void *backend,
const char *message) {
66 fake_logger_backend_t *b = (fake_logger_backend_t *)backend;
69 b->last_backend = backend;
70 b->last_message = message;
77static void fake_logger_destroy(
void *backend) {
78 fake_logger_backend_t *b = (fake_logger_backend_t *)backend;
81 b->last_backend = backend;
87 .
log = fake_logger_log,
88 .destroy = fake_logger_destroy
119 assert_ptr_equal(ret.
mem, dummy_p);
295 size_t fail_call_idx;
298 out_expect_t out_expect;
299} test_logger_lifecycle_case_t;
317 fake_logger_backend_t backend;
319 const test_logger_lifecycle_case_t *tc;
320} test_logger_lifecycle_fixture_t;
329static int setup_logger_lifecycle(
void **state)
331 const test_logger_lifecycle_case_t *tc =
332 (
const test_logger_lifecycle_case_t *)(*state);
334 test_logger_lifecycle_fixture_t *fx =
335 (test_logger_lifecycle_fixture_t *)malloc(
sizeof(*fx));
343 fake_memory_fail_only_on_call(tc->fail_call_idx);
349 fake_logger_backend_reset(&fx->backend);
358static int teardown_logger_lifecycle(
void **state)
360 test_logger_lifecycle_fixture_t *fx =
361 (test_logger_lifecycle_fixture_t *)(*state);
367 assert_true(fake_memory_no_leak());
368 assert_true(fake_memory_no_invalid_free());
369 assert_true(fake_memory_no_double_free());
382static void test_logger_lifecycle(
void **state)
384 test_logger_lifecycle_fixture_t *fx =
385 (test_logger_lifecycle_fixture_t *)(*state);
386 const test_logger_lifecycle_case_t *tc = fx->tc;
394 void *backend_arg = &fx->backend;
404 vtbl_local = fake_logger_vtbl;
405 vtbl_local.
log = NULL;
406 vtbl_arg = &vtbl_local;
409 vtbl_local = fake_logger_vtbl;
411 vtbl_arg = &vtbl_local;
415 if (tc->out_expect == OUT_EXPECT_UNCHANGED && out_arg != NULL) {
416 fx->out = (
logger_t *)(uintptr_t)0xDEADC0DEu;
419 logger_t *out_arg_snapshot = fx->out;
422 ret =
logger_create(out_arg, vtbl_arg, backend_arg, env_arg);
425 assert_non_null(fx->out);
428 assert_null(fx->out);
431 assert_null(fx->out);
435 assert_int_equal(ret, tc->expected_ret);
437 switch (tc->out_expect) {
438 case OUT_CHECK_NONE:
break;
439 case OUT_EXPECT_NULL: assert_null(fx->out);
break;
440 case OUT_EXPECT_NON_NULL: assert_non_null(fx->out);
break;
441 case OUT_EXPECT_UNCHANGED:
442 assert_ptr_equal(out_arg_snapshot, fx->out);
453static const test_logger_lifecycle_case_t CASE_LOGGER_LIFECYCLE_OUT_NULL = {
454 .name =
"logger_lifecycle_out_null",
460 .out_expect = OUT_CHECK_NONE
463static const test_logger_lifecycle_case_t CASE_LOGGER_LIFECYCLE_VTBL_NULL = {
464 .name =
"logger_lifecycle_vtbl_null",
470 .out_expect = OUT_EXPECT_UNCHANGED
473static const test_logger_lifecycle_case_t CASE_LOGGER_LIFECYCLE_VTBL_LOG_NULL = {
474 .name =
"logger_lifecycle_vtbl_log_null",
480 .out_expect = OUT_EXPECT_UNCHANGED
483static const test_logger_lifecycle_case_t CASE_LOGGER_LIFECYCLE_VTBL_DESTROY_NULL = {
484 .name =
"logger_lifecycle_vtbl_destroy_null",
490 .out_expect = OUT_EXPECT_UNCHANGED
493static const test_logger_lifecycle_case_t CASE_LOGGER_LIFECYCLE_BACKEND_NULL = {
494 .name =
"logger_lifecycle_backend_null",
500 .out_expect = OUT_EXPECT_UNCHANGED
503static const test_logger_lifecycle_case_t CASE_LOGGER_LIFECYCLE_ENV_NULL = {
504 .name =
"logger_lifecycle_env_null",
510 .out_expect = OUT_EXPECT_UNCHANGED
513static const test_logger_lifecycle_case_t CASE_LOGGER_LIFECYCLE_ENV_MEM_NULL = {
514 .name =
"logger_lifecycle_mem_null",
520 .out_expect = OUT_EXPECT_UNCHANGED
523static const test_logger_lifecycle_case_t CASE_LOGGER_LIFECYCLE_OOM_1 = {
524 .name =
"logger_lifecycle_oom_1",
530 .out_expect = OUT_EXPECT_UNCHANGED
533static const test_logger_lifecycle_case_t CASE_LOGGER_LIFECYCLE_OK = {
534 .name =
"logger_lifecycle_ok",
540 .out_expect = OUT_EXPECT_NON_NULL
543static const test_logger_lifecycle_case_t CASE_LOGGER_LIFECYCLE_DESTROY_IDEMPOTENT = {
544 .name =
"logger_lifecycle_destroy_idempotent",
550 .out_expect = OUT_EXPECT_NULL
557#define LOGGER_LIFECYCLE_CASES(X) \
558X(CASE_LOGGER_LIFECYCLE_OUT_NULL) \
559X(CASE_LOGGER_LIFECYCLE_VTBL_NULL) \
560X(CASE_LOGGER_LIFECYCLE_VTBL_LOG_NULL) \
561X(CASE_LOGGER_LIFECYCLE_VTBL_DESTROY_NULL) \
562X(CASE_LOGGER_LIFECYCLE_BACKEND_NULL) \
563X(CASE_LOGGER_LIFECYCLE_ENV_NULL) \
564X(CASE_LOGGER_LIFECYCLE_ENV_MEM_NULL) \
565X(CASE_LOGGER_LIFECYCLE_OOM_1) \
566X(CASE_LOGGER_LIFECYCLE_OK) \
567X(CASE_LOGGER_LIFECYCLE_DESTROY_IDEMPOTENT)
569#define LOGGER_MAKE_LIFECYCLE_TEST(case_sym) \
570LEXLEO_MAKE_TEST(logger_lifecycle, case_sym)
572static const struct CMUnitTest logger_lifecycle_tests[] = {
573 LOGGER_LIFECYCLE_CASES(LOGGER_MAKE_LIFECYCLE_TEST)
576#undef LOGGER_LIFECYCLE_CASES
577#undef LOGGER_MAKE_LIFECYCLE_TEST
638} test_logger_log_case_t;
652 fake_logger_backend_t backend;
653 const test_logger_log_case_t *tc;
654} test_logger_log_fixture_t;
663static int setup_logger_log(
void **state)
665 const test_logger_log_case_t *tc =
666 (
const test_logger_log_case_t *)(*state);
667 test_logger_log_fixture_t *fx =
668 (test_logger_log_fixture_t *)malloc(
sizeof(*fx));
674 fake_logger_backend_reset(&fx->backend);
680 logger_create(&fx->logger, &fake_logger_vtbl, &fx->backend, &fx->env),
692static int teardown_logger_log(
void **state)
694 test_logger_log_fixture_t *fx =
695 (test_logger_log_fixture_t *)(*state);
699 assert_true(fake_memory_no_invalid_free());
700 assert_true(fake_memory_no_double_free());
701 assert_true(fake_memory_no_leak());
715static void test_logger_log(
void **state)
717 test_logger_log_fixture_t *fx =
718 (test_logger_log_fixture_t *)(*state);
719 const test_logger_log_case_t *tc = fx->tc;
724 const char *message_arg =
"test message";
739 assert_int_equal(ret, tc->expected_ret);
742 assert_int_equal(fx->backend.log_called, 1);
743 assert_int_equal(fx->backend.destroy_called, 0);
744 assert_ptr_equal(fx->backend.last_backend, &fx->backend);
745 assert_ptr_equal(fx->backend.last_message, message_arg);
753static const test_logger_log_case_t CASE_LOGGER_LOG_L_NULL = {
754 .name =
"logger_log_l_null",
761static const test_logger_log_case_t CASE_LOGGER_LOG_MESSAGE_NULL = {
762 .name =
"logger_log_message_null",
770static const test_logger_log_case_t CASE_LOGGER_LOG_FORWARD_IO_ERROR_OK = {
771 .name =
"logger_log_forward_io_error_ok",
782#define LOGGER_LOG_CASES(X) \
783X(CASE_LOGGER_LOG_L_NULL) \
784X(CASE_LOGGER_LOG_MESSAGE_NULL) \
785X(CASE_LOGGER_LOG_FORWARD_IO_ERROR_OK)
787#define LOGGER_MAKE_LOG_TEST(case_sym) \
788LEXLEO_MAKE_TEST(logger_log, case_sym)
790static const struct CMUnitTest logger_log_tests[] = {
791 LOGGER_LOG_CASES(LOGGER_MAKE_LOG_TEST)
794#undef LOGGER_LOG_CASES
795#undef LOGGER_MAKE_LOG_TEST
803 static const struct CMUnitTest logger_unit_non_parametric_tests[] = {
808 failed += cmocka_run_group_tests(logger_unit_non_parametric_tests, NULL, NULL);
809 failed += cmocka_run_group_tests(logger_lifecycle_tests, NULL, NULL);
810 failed += cmocka_run_group_tests(logger_log_tests, NULL, NULL);
Borrower-facing runtime operations for the logger port.
logger_status_t logger_log(logger_t *l, const char *message)
Emit a log message through a logger.
Adapter-side API for constructing and binding logger_t objects.
logger_status_t logger_create(logger_t **out, const logger_vtbl_t *vtbl, void *backend, const logger_env_t *env)
Create a generic logger handle from adapter-provided backend bindings.
Composition Root helpers for the logger port.
logger_env_t logger_default_env(const osal_mem_ops_t *mem_ops)
Build a default logger_env_t from injected memory operations.
Lifecycle services for logger_t handles.
void logger_destroy(logger_t **l)
Destroy a logger handle.
void * osal_memset(void *s, int c, size_t n)
const osal_mem_ops_t * osal_mem_test_fake_ops(void)
Runtime environment for the logger port.
const osal_mem_ops_t * mem
Memory operations used by the logger port.
Private handle structure for a logger_t.
Adapter dispatch table bound to a logger_t instance.
logger_status_t(* log)(void *backend, const char *message)
void(* destroy)(void *backend)
logger_log_scenario_t
Scenarios for logger_log().
@ LOGGER_LOG_SCENARIO_FORWARD_IO_ERROR_OK
@ LOGGER_LOG_SCENARIO_L_NULL
@ LOGGER_LOG_SCENARIO_MESSAGE_NULL
static void test_logger_default_env(void **state)
Test logger_default_env().
logger_lifecycle_scenario_t
Scenarios for logger_create() / logger_destroy().
@ LOGGER_LIFECYCLE_SCENARIO_OK
@ LOGGER_LIFECYCLE_SCENARIO_BACKEND_NULL
@ LOGGER_LIFECYCLE_SCENARIO_ENV_NULL
@ LOGGER_LIFECYCLE_SCENARIO_OOM
@ LOGGER_LIFECYCLE_SCENARIO_VTBL_LOG_NULL
@ LOGGER_LIFECYCLE_SCENARIO_VTBL_DESTROY_NULL
@ LOGGER_LIFECYCLE_SCENARIO_DESTROY_IDEMPOTENT
@ LOGGER_LIFECYCLE_SCENARIO_ENV_MEM_NULL
@ LOGGER_LIFECYCLE_SCENARIO_OUT_NULL
@ LOGGER_LIFECYCLE_SCENARIO_VTBL_NULL