summaryrefslogtreecommitdiff
path: root/test/freertos/regression/txfr_test_harness.h
blob: ffb6db0e3ed6db12b63258547eb524deb769a5cc (plain)
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 */