rcutils
master
C API providing common utilities and data structures.
|
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include "rcutils/macros.h"
#include "rcutils/visibility_control.h"
Go to the source code of this file.
Macros | |
#define | RCUTILS_FAULT_INJECTION_NEVER_FAIL -1 |
#define | RCUTILS_FAULT_INJECTION_FAIL_NOW 0 |
#define | RCUTILS_FAULT_INJECTION_MAYBE_RETURN_ERROR(return_value_on_error) |
This macro checks and decrements a static global variable atomic counter and returns return_value_on_error if 0. More... | |
#define | RCUTILS_FAULT_INJECTION_MAYBE_FAIL(failure_code) |
This macro checks and decrements a static global variable atomic counter and executes failure_code if the counter is 0 inside a scoped block (any variables declared in failure_code) will not be avaliable outside of this scoped block. More... | |
#define | RCUTILS_FAULT_INJECTION_TEST(code) |
#define | RCUTILS_NO_FAULT_INJECTION(code) |
Functions | |
bool | rcutils_fault_injection_is_test_complete (void) |
void | rcutils_fault_injection_set_count (int_least64_t count) |
Atomically set the fault injection counter. More... | |
int_least64_t | rcutils_fault_injection_get_count (void) |
Atomically get the fault injection counter value. More... | |
int_least64_t | _rcutils_fault_injection_maybe_fail (void) |
Implementation of fault injection decrementer. More... | |
#define RCUTILS_FAULT_INJECTION_NEVER_FAIL -1 |
#define RCUTILS_FAULT_INJECTION_FAIL_NOW 0 |
#define RCUTILS_FAULT_INJECTION_MAYBE_RETURN_ERROR | ( | return_value_on_error | ) |
This macro checks and decrements a static global variable atomic counter and returns return_value_on_error
if 0.
This macro is not a function itself, so when this macro returns it will cause the calling function to return with the return value.
Set the counter with RCUTILS_FAULT_INJECTION_SET_COUNT
. If the count is less than 0, then RCUTILS_FAULT_INJECTION_MAYBE_RETURN_ERROR
will not cause an early return.
This macro is thread-safe, and ensures that at most one invocation results in a failure for each time the fault injection counter is set with RCUTILS_FAULT_INJECTION_SET_COUNT
return_value_on_error | the value to return in the case of fault injected failure. |
#define RCUTILS_FAULT_INJECTION_MAYBE_FAIL | ( | failure_code | ) |
This macro checks and decrements a static global variable atomic counter and executes failure_code
if the counter is 0 inside a scoped block (any variables declared in failure_code) will not be avaliable outside of this scoped block.
This macro is not a function itself, so it will cause the calling function to execute the code from within an if loop.
Set the counter with RCUTILS_FAULT_INJECTION_SET_COUNT
. If the count is less than 0, then RCUTILS_FAULT_INJECTION_MAYBE_FAIL
will not execute the failure code.
This macro is thread-safe, and ensures that at most one invocation results in a failure for each time the fault injection counter is set with RCUTILS_FAULT_INJECTION_SET_COUNT
failure_code | the code to execute in the case of fault injected failure. |
#define RCUTILS_FAULT_INJECTION_TEST | ( | code | ) |
The fault injection macro for use with unit tests to check that code
can tolerate injected failures at all points along the execution path where the indicating macros RCUTILS_CAN_RETURN_WITH_ERROR_OF
and RCUTILS_CAN_FAIL_WITH
are located.
This macro is intended to be used within a gtest function macro like 'TEST', 'TEST_F', etc.
code
is executed within a do-while loop and therefore any variables declared within are in their own scope block.
Here's a simple example: RCUTILS_FAULT_INJECTION_TEST( rcl_ret_t ret = rcl_init(argc, argv, options, context); if (RCL_RET_OK == ret) { ret = rcl_shutdown(context); } });
In this example, you will need have conditional execution based on the return value of rcl_init
. If it failed, then it wouldn't make sense to call rcl_shutdown. In your own test, there might be similar logic that requires conditional checks. The goal of writing this test is less about checking the behavior is consistent, but instead that failures do not cause program crashes, memory errors, or unnecessary memory leaks.
#define RCUTILS_NO_FAULT_INJECTION | ( | code | ) |
A convenience macro built around rcutils_fault_injection_set_count() to pause fault injection during code
execution. This macro is intended to be used within RCUTILS_FAULT_INJECTION_TEST() blocks.
code
is executed within a do-while loop and therefore any variables declared within are in their own scope block.
Here's a simple example: RCUTILS_FAULT_INJECTION_TEST({ rcl_ret_t ret = rcl_init(argc, argv, options, context); if (RCL_RET_OK == ret) { RCUTILS_NO_FAULT_INJECTION({ ret = rcl_shutdown(context); }); } });
In this example, on successful rcl_init(), rcl_shutdown() is called while ensuring that it will not fail due to fault injection.
bool rcutils_fault_injection_is_test_complete | ( | void | ) |
void rcutils_fault_injection_set_count | ( | int_least64_t | count | ) |
Atomically set the fault injection counter.
This is typically not the preferred method of interacting directly with the fault injection logic, instead use RCUTILS_FAULT_INJECTION_TEST
instead.
This function may also be used for pausing code inside of a RCUTILS_FAULT_INJECTION_TEST
with something like the following:
RCUTILS_FAULT_INJECTION_TEST({ ... // code to run with fault injection int64_t count = rcutils_fault_injection_get_count(); rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); ... // code to run without fault injection rcutils_fault_injection_set_count(count); ... // code to run with fault injection });
count | The count to set the fault injection counter to. If count is negative, then fault injection errors will be disabled. The counter is globally initialized to RCUTILS_FAULT_INJECTION_NEVER_FAIL. |
int_least64_t rcutils_fault_injection_get_count | ( | void | ) |
Atomically get the fault injection counter value.
This function is typically not used directly but instead indirectly inside an RCUTILS_FAULT_INJECTION_TEST
int_least64_t _rcutils_fault_injection_maybe_fail | ( | void | ) |
Implementation of fault injection decrementer.
This is included inside of macros, so it needs to be exported as a public function, but it should not be used directly.