Skip to content

Commit 6a5daad

Browse files
committed
Updating comments
Signed-off-by: Stephen Brawner <brawner@gmail.com>
1 parent b03d89e commit 6a5daad

File tree

1 file changed

+49
-27
lines changed

1 file changed

+49
-27
lines changed

include/rcutils/testing/fault_injection.h

+49-27
Original file line numberDiff line numberDiff line change
@@ -36,29 +36,22 @@ bool
3636
rcutils_fault_injection_is_test_complete(void);
3737

3838
/**
39-
* \def RCUTILS_FAULT_INJECTION_SET_COUNT
4039
* \brief Atomically set the fault injection counter.
4140
*
42-
* There will be at most one fault injected failure per call to RCUTILS_FAULT_INJECTION_SET_COUNT.
43-
* To test all reachable fault injection locations, call this macro inside a loop and set the count
44-
* to an incrementing count variable.
41+
* This is typically not the preferred method of interacting directly with the fault injection
42+
* logic, instead use `RCUTILS_FAULT_INJECTION_TEST` instead.
4543
*
46-
* for (int i = 0; i < SUFFICIENTLY_LARGE_ITERATION_COUNT; ++i) {
47-
* RCUTILS_FAULT_INJECTION_SET_COUNT(i);
48-
* ... // Call function under test
49-
* }
50-
* ASSERT_LT(RCUTILS_FAULT_INJECTION_NEVER_FAIL, RCUTILS_FAULT_INJECTION_GET_COUNT());
44+
* This function may also be used for pausing code inside of a `RCUTILS_FAULT_INJECTION_TEST` with
45+
* something like the following:
5146
*
52-
* Where SUFFICIENTLY_LARGE_ITERATION_COUNT is a value larger than the maximum expected calls to
53-
* `RCUTILS_FAULT_INJECTION_MAYBE_RETURN_ERROR`. This last assertion just ensures that your choice for
54-
* SUFFICIENTLY_LARGE_ITERATION_COUNT was large enough. To avoid having to choose this count
55-
* yourself, you can use a do-while loop.
56-
*
57-
* int i = 0;
58-
* do {
59-
* RCUTILS_FAULT_INJECTION_SET_COUNT(i++);
60-
* ... // Call function under test
61-
* } while (RCUTILS_FAULT_INJECTION_GET_COUNT() <= RCUTILS_FAULT_INJECTION_NEVER_FAIL);
47+
* RCUTILS_FAULT_INJECTION_TEST({
48+
* ... // code to run with fault injection
49+
* int64_t count = rcutils_fault_injection_get_count();
50+
* rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL);
51+
* ... // code to run without fault injection
52+
* rcutils_fault_injection_set_count(count);
53+
* ... // code to run with fault injection
54+
* });
6255
*
6356
* \param count The count to set the fault injection counter to. If count is negative, then fault
6457
* injection errors will be disabled. The counter is globally initialized to
@@ -69,20 +62,22 @@ void
6962
rcutils_fault_injection_set_count(int count);
7063

7164
/**
72-
* \def RCUTILS_FAULT_INJECTION_GET_COUNT
7365
* \brief Atomically get the fault injection counter value
7466
*
75-
* Use this macro after running the code under test to check whether the counter reached a negative
76-
* value. This is helpful so you can verify that you ran the fault injection test in a loop a
77-
* sufficient number of times. Likewise, if the code under test returned with an error, but the
78-
* count value was greater or equal to 0, then the failure was not caused by the fault injection
79-
* counter.
67+
* This function is typically not used directly but instead indirectly inside an
68+
* `RCUTILS_FAULT_INJECTION_TEST`
8069
*/
8170
RCUTILS_PUBLIC
8271
RCUTILS_WARN_UNUSED
8372
int_least64_t
8473
rcutils_fault_injection_get_count(void);
8574

75+
/**
76+
* \brief Implementation of fault injection decrementer
77+
*
78+
* This is included inside of macros, so it needs to be exported as a public function, but it
79+
* should not be used directly.
80+
*/
8681
RCUTILS_PUBLIC
8782
RCUTILS_WARN_UNUSED
8883
int_least64_t
@@ -114,8 +109,8 @@ _rcutils_fault_injection_maybe_fail(void);
114109
/**
115110
* \def RCUTILS_FAULT_INJECTION_MAYBE_FAIL
116111
* \brief This macro checks and decrements a static global variable atomic counter and executes
117-
* `failure_code` if the counter is 0 inside a scoped block (any variables declared in failure_code)
118-
* will not be avaliable outside of this scoped block.
112+
* `failure_code` if the counter is 0 inside a scoped block (any variables declared in
113+
* failure_code) will not be avaliable outside of this scoped block.
119114
*
120115
* This macro is not a function itself, so it will cause the calling function to execute the code
121116
* from within an if loop.
@@ -135,6 +130,33 @@ _rcutils_fault_injection_maybe_fail(void);
135130
failure_code; \
136131
}
137132

133+
/**
134+
* \def RCUTILS_FAULT_INJECTION_TEST
135+
*
136+
* The fault injection macro for use with unit tests to check that `code` can tolerate injected
137+
* failures at all points along the execution path where the indicating macros
138+
* `RCUTILS_CAN_RETURN_WITH_ERROR_OF` and `RCUTILS_CAN_FAIL_WITH` are located.
139+
*
140+
* This macro is intended to be used within a gtest function macro like 'TEST', 'TEST_F', etc.
141+
*
142+
* `code` is executed within a do-while loop and therefore any variables declared within are in
143+
* their own scope block.
144+
*
145+
* Here's a simple example:
146+
* RCUTILS_FAULT_INJECTION_TEST(
147+
* rcl_ret_t ret = rcl_init(argc, argv, options, context);
148+
* if (RCL_RET_OK == ret)
149+
* {
150+
* ret = rcl_shutdown(context);
151+
* }
152+
* });
153+
*
154+
* In this example, you will need have conditional execution based on the return value of
155+
* `rcl_init`. If it failed, then it wouldn't make sense to call rcl_shutdown. In your own test,
156+
* there might be similar logic that requires conditional checks. The goal of writing this test
157+
* is less about checking the behavior is consistent, but instead that failures do not cause
158+
* program crashes, memory errors, or unnecessary memory leaks.
159+
*/
138160
#define RCUTILS_FAULT_INJECTION_TEST(code) \
139161
do { \
140162
int fault_injection_count = 0; \

0 commit comments

Comments
 (0)