Building Blocks

Core of Rexo—data structures, required macros, and lower level API calls.

Most of these are abstracted away when using the runner, the framework's automatic registration feature, and the assertion macros.

Enumerators

rx_status

Return codes.

enum rx_status {
    RX_SUCCESS = 0,
    RX_ERROR = -1,
    RX_ERROR_ALLOCATION = -2,
    RX_ERROR_MAX_SIZE_EXCEEDED = -3
}

Error codes come in different categories that all evaluate to negative numbers.

rx_severity

Severity levels for test failures.

enum rx_severity { RX_NONFATAL = 0, RX_FATAL = 1 }

Nonfatal failures arise from RX_CHECK* assertions while RX_REQUIRE* trigger fatal failures.

See also the assertion macros.

rx_log_level

Logging level.

enum rx_log_level {
    RX_LOG_LEVEL_NONE = 0,
    RX_LOG_LEVEL_FATAL = 1,
    RX_LOG_LEVEL_ERROR = 3,
    RX_LOG_LEVEL_WARNING = 4,
    RX_LOG_LEVEL_INFO = 5,
    RX_LOG_LEVEL_DEBUG = 6,
    RX_LOG_LEVEL_ALL = RX_LOG_LEVEL_DEBUG
};

The purpose of each level is defined as follows:

leveldescriptionexample
fatalcritical failure that causes premature termination of the applicationlack of disk space, data corruption
errorfailure that doesn't require the application to be prematurely terminatedunable to open a file, allocation failure
warningsituation that is not ideal but that is not an actual failure per seuse of a deprecated API, poor use of an API
infoevent of general interest corresponding to normal application behaviouraddition of a database entry, statistics
debugdetailed information to help maintainers troubleshooting problemsallocation size, state of data
tracecontrol flow of the application to help maintainers pinpointing problemsentry/exit of functions, dump of argument values

Function Pointers

rx_set_up_fn

Function part of the fixture feature, to be called before the function defining the tests is run.

typedef enum rx_status (*rx_set_up_fn)(struct rx_context *, void *)

The struct rx_context * parameter is reserved for the implementation and shouldn't be directly accessed by the users.

The void * parameter is used to output any data initialized within this function. The pointer can be accessed within the function's definition using the RX_DATA macro.

When explicitly registering tests, the macros RX_PARAM_CONTEXT and RX_PARAM_DATA need to be used to define the parameter names.

The function is expected to return an error code if something went wrong, or RX_SUCCESS otherwise.

rx_tear_down_fn

Function part of the fixture feature, to be called after the function defining the tests is run.

typedef void (*rx_tear_down_fn)(struct rx_context *, void *)

The struct rx_context * parameter is reserved for the implementation and shouldn't be directly accessed by the users.

The void * parameter is used to output any data initialized within this function. The pointer can be accessed within the function's definition using the RX_DATA macro.

When explicitly registering tests, the macros RX_PARAM_CONTEXT and RX_PARAM_DATA need to be used to define the parameter names.

rx_run_fn

Function defining the tests to run.

typedef void (*rx_run_fn)(struct rx_context *, void *)

The struct rx_context * parameter is reserved for the implementation and shouldn't be directly accessed by the users.

The void * parameter is used to output any data initialized within this function. The pointer can be accessed within the function's definition using the RX_DATA macro.

When explicitly registering tests, the macros RX_PARAM_CONTEXT and RX_PARAM_DATA need to be used to define the parameter names.

Parameters

RX_PARAM_CONTEXT

Refers to the name expected for the context parameter.

#define RX_PARAM_CONTEXT

The context parameter is used for the functions rx_set_up_fn, rx_tear_down_fn, and rx_run_fn.

It is not to be directly used unless when explicitly registering tests. In this case, the macro RX_PARAM_CONTEXT is required to name the struct rx_context * parameter.

RX_PARAM_DATA

Refers to the name expected for the data parameter.

#define RX_PARAM_DATA

The context parameter is used for the functions rx_set_up_fn, rx_tear_down_fn, and rx_run_fn.

It is not to be directly used unless when explicitly registering tests. In this case, the macro RX_PARAM_DATA is required to name the void * parameter.

Data Accessors

RX_DATA

Access the data's pointer.

#define RX_DATA

This macro can be used within the definitions of the functions rx_set_up_fn, rx_tear_down_fn, and rx_run_fn.

Types

rx_uint32

Type for 32-bit unsigned integers.

typedef TYPE rx_uint32;

The type is determined by the value of the RX_UINT32_TYPE macro. If the macro isn't set, unsigned int is used, which fits the common data models, that is ILP32 (most recent 32-bit systems), LP64 (Unix-like systems), and LLP64 (Windows).

rx_uint64

Type for 64-bit unsigned integers.

typedef TYPE rx_uint64;

The type is determined by the value of the RX_UINT64_TYPE macro. If the macro isn't set, unsigned long long is used, which fits the common data models, that is ILP32 (most recent 32-bit systems), LP64 (Unix-like systems), and LLP64 (Windows).

rx_size

Type to use in place of size_t.

typedef TYPE rx_size;

The type is determined by the value of the RX_SIZE_TYPE macro. If the macro isn't set, either rx_uint32 or rx_uint64 is used, depending on whether the environment is running on a 32-bit or 64-bit platform.

Structures

rx_test_case_config

Configuration object to apply to a test case.

struct rx_test_case_config {
    int skip;
    struct rx_fixture fixture;
}

In the event where a test case should be skipped by the runner, the skip option can be used.

Fixtures are defined through the fixture option, see the rx_fixture struct.

Filling the struct with the value 0 sets all the members to their default values.

rx_fixture_config

Configuration object to apply to a fixture.

struct rx_fixture_config {
    rx_set_up_fn set_up;
    rx_tear_down_fn tear_down;
}

The set_up and tear_down options respectively define the rx_set_up_fn and the rx_tear_down_fn functions.

Filling the struct with the value 0 sets all the members to their default values.

rx_fixture

Fixture defining function pointers to run before and after the function defining the test is run.

struct rx_fixture {
    rx_set_up_fn set_up;
    rx_tear_down_fn tear_down;
};

rx_test_case

Definition of a single test case.

struct rx_test_case {
    const char *suite_name;
    const char *name;
    rx_run_fn run;
    struct rx_test_case_config config;
};

The run function pointer needs to point to the function that contains the tests for the test case. See the rx_run_fn function.

Any configuration can be set through the config option. See the rx_test_case_config struct.

rx_failure

Information related to a test that failed.

struct rx_failure {
    const char *file;
    int line;
    enum rx_severity severity;
    const char *msg;
    const char *diagnostic_msg;
}

rx_summary

Report from running a test case.

struct rx_summary {
    const struct rx_test_case *test_case;
    int skipped;
    const char *error;
    rx_size assessed_count;
    rx_size failure_count;
    struct rx_failure *failures;
    rx_uint64 elapsed;
}

rx_context

Opaque data required internally by Rexo.

struct rx_context

Functions

rx_abort

Aborts the execution of the test case being currently run.

void
rx_abort(struct rx_context *context)

rx_handle_test_result

Handles the result of a single test.

enum rx_status
rx_handle_test_result(struct rx_context *context,
                      int result,
                      const char *file,
                      int line,
                      enum rx_severity severity,
                      const char *failure_msg,
                      const char *diagnostic_msg)

This records the result and any error or diagnostic messages related to it.

rx_summary_initialize

Initializes a summary.

enum rx_status
rx_summary_initialize(struct rx_summary *summary,
                      const struct rx_test_case *test_case)

The struct rx_summary must be already manually allocated beforehand.

rx_summary_terminate

Terminates a summary.

void
rx_summary_terminate(struct rx_summary *summary)

The struct rx_summary must be manually freed afterwards, if needed.

rx_summary_print

Prints a summary covering the result of running a single test case.

void
rx_summary_print(const struct rx_summary *summary)

The summary is printed out to stderr as it is not intended for further processing, but to only show the progress of each test case as the results come in.

rx_test_case_run

Runs a single test case.

enum rx_status
rx_test_case_run(struct rx_summary *summary,
                 const struct rx_test_case *test_case)

The run function set for the given test case is being executed with the results are being stored in the summary argument.

rx_enumerate_test_cases

Enumerates the test cases automatically registered.

void
rx_enumerate_test_cases(size_t *test_case_count,
                        struct rx_test_case *test_cases)

If test_cases is NULL, then the number of test cases available is returned in test_case_count. Otherwise, test_case_count must point to a variable set by the user to the number of elements in the test_cases array, and on return the variable is overwritten with the number of objects actually written to test_cases.

If test_case_count is less than the number of test cases available, at most test_case_count objects will be written.