lib: assign a unique ID to each pre/postcond. and report it on failure
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 21 Apr 2020 15:15:42 +0000 (11:15 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 23 Apr 2020 03:45:20 +0000 (23:45 -0400)
commit1778c2a4134647150b199b2b57130817144446b0
tree95cfb61394a013bef7ed218d93ea04a7a39e6a7c
parente020d1340a9b5ebd7d7dbf00a2c34d2fe512a495
lib: assign a unique ID to each pre/postcond. and report it on failure

This patch changes the libbabeltrace2 pre/postcondition assertion macros
so that each precondition and postcondion has a unique ID within the
library.

The macros report (log with a FATAL level) the condition ID on assertion
failure as such (logging prefixes removed):

    Babeltrace 2 library precondition not satisfied.
    ------------------------------------------------------------------------
    Condition ID: `pre:field-class-integer-set-field-value-range:valid-n`.
    Function: bt_field_class_integer_set_field_value_range().
    ------------------------------------------------------------------------
    Error is:
    Unsupported size for integer field class's field value range
    (minimum is 1, maximum is 64): size=65
    Aborting...

The main goal of this change is to make it easier to test library
precondition and postcondition assertions: now you only need to confirm
that the log indicates the expected condition ID, making the details
("Unsupported size for [...]" in the example above) unimportant.

The condition IDs could also exist in the documentation so as to make it
easier to search for libbabeltrace2 pre/postcondition documentation when
failing to satisfy one.

The general condition ID format is:

    TYPE:FUNC:SUFFIX

with

`TYPE`:
    `pre` or `post`.

`FUNC`:
    Name of the API function (precondition) or user function type
    (postcondition) without the `bt_` prefix and with `_` replaced with
    `-`.

`SUFFIX`:
    With the scope of the function: unique, specific precondition or
    postcondition ID.

The BT_ASSERT_PRE_FROM_FUNC() macro (and its developer mode counterpart)
accepts a function name and an ID suffix.

The BT_ASSERT_PRE() macro (and its developer mode counterpart) only
accepts an ID suffix: it uses BT_ASSERT_PRE_FROM_FUNC() with `__func__`
as the function name.

All the other precondition assertion macros follow the same scheme:
`_FROM_FUNC` suffix for a specific function, no suffix for the current
function.

Many precondition assertion macros in `assert-cond.h` build a complete
ID suffix based on a part of it. For example, BT_ASSERT_PRE_NON_NULL()
accepts an object ID, so that

    BT_ASSERT_PRE_NON_NULL("description", descr, "Description");

has the condition ID, when used from the hypothetical public function
bt_do_xyz(), `pre:do-xyz:not-null:description`.

It is imperative that the used API function name is always the one the
user called. Knowing this, internal, static functions _cannot_ use
BT_ASSERT_PRE() because the reported function name would be the internal
one. Not only is this confusing for the library user, it could also
change in the future.

This patch uses two strategies to deal with this constraint depending
on the intended execution path of the public function:

Slow path:
    The common (internal) function accepts an `api_func` parameter which
    is the ultimate public API function name.

    The common function only uses precondition assertion macros which
    end with `_FROM_FUNC`.

    A public function which calls this common function passes `__func__`
    as its `api_func` parameter.

Fast path:
    We define (locally) a new macro which uses the required precondition
    assertion macros (the variants without `_FROM_FUNC`).

    A public function which calls the common function uses the custom
    macro.

Postconditions are checked when a user function returns. Therefore, the
function name in that case is the user function type name.
BT_ASSERT_POST() accepts a function name and an ID suffix.

_BT_ASSERT_COND() calls the internal bt_lib_assert_cond_failed() which
formats the condition ID, prints it and the function name, prints the
details, and aborts.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: I8bfab8c90cd1c18215fc0738f0b9504130f48b45
Reviewed-on: https://review.lttng.org/c/babeltrace/+/3435
42 files changed:
doc/api/libbabeltrace2/dox/api-fund.dox
src/common/assert.h
src/common/macros.h
src/lib/Makefile.am
src/lib/assert-cond-base.h
src/lib/assert-cond.c [new file with mode: 0644]
src/lib/assert-cond.h
src/lib/current-thread.c
src/lib/error.c
src/lib/graph/component-class.c
src/lib/graph/component-filter.c
src/lib/graph/component-sink.c
src/lib/graph/component-source.c
src/lib/graph/component.c
src/lib/graph/component.h
src/lib/graph/graph.c
src/lib/graph/iterator.c
src/lib/graph/message-iterator-class.c
src/lib/graph/message/discarded-items.c
src/lib/graph/message/event.c
src/lib/graph/message/message-iterator-inactivity.c
src/lib/graph/message/packet.c
src/lib/graph/message/stream.c
src/lib/graph/mip.c
src/lib/graph/query-executor.c
src/lib/integer-range-set.c
src/lib/plugin/plugin.c
src/lib/trace-ir/clock-class.c
src/lib/trace-ir/clock-snapshot.c
src/lib/trace-ir/event-class.c
src/lib/trace-ir/field-class.c
src/lib/trace-ir/field-path.c
src/lib/trace-ir/field.c
src/lib/trace-ir/packet.c
src/lib/trace-ir/resolve-field-path.c
src/lib/trace-ir/resolve-field-path.h
src/lib/trace-ir/stream-class.c
src/lib/trace-ir/stream.c
src/lib/trace-ir/trace-class.c
src/lib/trace-ir/trace.c
src/lib/util.c
src/lib/value.c
This page took 0.028149 seconds and 4 git commands to generate.