1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
/***************************************************************************
* 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 */
|