/*************************************************************************** * Copyright (C) 2026 Eclipse ThreadX contributors * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at * https://opensource.org/licenses/MIT. * * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). * The AI-generated portions may be considered public domain (CC0-1.0) * and not subject to the project's licence. The human contributor has * reviewed and verified that the code is correct. * * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ /**************************************************************************/ /** */ /** ThreadX Component */ /** */ /** FreeRTOS compatibility layer test harness */ /** */ /**************************************************************************/ /* This harness lets a test force a ThreadX object creation call to fail and then account for what the compatibility layer did with the resources it had already taken. The creation entry points of the layer take a byte pool allocation for the descriptor, sometimes a second one for backing storage, and then create one or more kernel objects; an error path that forgets to undo any of that is invisible to the caller, which only ever sees NULL. Interception is done with the linker's --wrap option rather than with hooks in the layer itself, so tx_freertos.c is compiled exactly as it ships. Note that tx_api.h maps the public API onto the error checking entry points, so the symbols that exist at link time, and therefore the ones wrapped, are the _txe_ variants. The wrap options live in the test CMakeLists. This mechanism is specific to GNU ld and lld, so the suite is Linux only. */ #ifndef TXFR_TEST_HARNESS_H #define TXFR_TEST_HARNESS_H #include "FreeRTOS.h" /* Identifies the kernel creation call a test wants to fail. */ typedef enum TXFR_INJECT_TARGET_ENUM { TXFR_INJECT_NONE = 0, TXFR_INJECT_SEMAPHORE_CREATE, TXFR_INJECT_MUTEX_CREATE, TXFR_INJECT_EVENT_FLAGS_CREATE, TXFR_INJECT_TIMER_CREATE, TXFR_INJECT_THREAD_CREATE, TXFR_INJECT_THREAD_RESUME } TXFR_INJECT_TARGET; /* Counts of the ThreadX primitives the layer reached for while accounting was active. The byte pool counts stand in for txfr_malloc() and txfr_free(), which cannot be wrapped: they are defined in tx_freertos.c and called from within it, so the compiler resolves those calls internally. */ typedef struct TXFR_COUNTERS_STRUCT { int byte_allocate; int byte_release; int semaphore_create; int semaphore_delete; int mutex_create; int mutex_delete; int event_flags_create; int event_flags_delete; int timer_create; int timer_delete; int thread_create; int thread_delete; /* Counted, but not part of the object totals checked below, since a resume creates nothing. */ int thread_resume; } TXFR_COUNTERS; /* Start accounting. Pass TXFR_INJECT_NONE to only count, or a target together with the 1 based index of the call to fail, counted from this call onward. */ void txfr_test_account_start(TXFR_INJECT_TARGET target, int fail_on_call); /* Stop accounting and copy out what was counted. */ void txfr_test_account_stop(TXFR_COUNTERS *p_counters); /* Record the outcome of one expectation. Prints a line per check and remembers whether anything failed. */ void txfr_test_check(const char *label, int condition); /* As above, with the observed and expected counts printed on a failure. */ void txfr_test_check_counts(const char *label, const TXFR_COUNTERS *p_counters, int expect_allocate, int expect_release, int expect_object_create, int expect_object_delete); /* Number of failed checks so far. */ int txfr_test_failures(void); /* Each test file defines this. It runs in thread context, since the byte pool operations under test are not callable from initialization. */ void txfr_test_body(void); #endif /* TXFR_TEST_HARNESS_H */