Skip to content

Commit

Permalink
Add functions for more fine-grained stringification of assertion info…
Browse files Browse the repository at this point in the history
…rmation
  • Loading branch information
jeremy-rifkin committed Mar 10, 2024
1 parent dac8d7b commit 3e6061b
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 82 deletions.
86 changes: 86 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
- [Utilities](#utilities)
- [Configuration](#configuration)
- [Assertion information](#assertion-information)
- [Anatomy of Assertion Information](#anatomy-of-assertion-information)
- [Stringification](#stringification)
- [Custom Failure Handlers](#custom-failure-handlers-1)
- [Other configurations](#other-configurations)
Expand Down Expand Up @@ -540,6 +541,91 @@ namespace libassert {
}
```

### Anatomy of Assertion Information

```
Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
debug_assert(open(path, 0) >= 0, ...);
Where:
open(path, 0) => -1
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
Stack trace:
#1 demo.cpp:194 foo::baz()
#2 demo.cpp:172 void foo::bar<int>(std::pair<int, int>)
#3 demo.cpp:396 main
```

- `Debug Assertion failed`: `assertion_info.action()`
- `demo.cpp:194`: `assertion_info.file_name` and `assertion_info.line`
- `void foo::baz()`: `assertion_info.pretty_function`
- `Internal error with foobars`: `assertion_info.message`
- `debug_assert`: `assertion_info.macro_name`
- `open(path, 0) >= 0`: `assertion_info.expression_string`
- `...`: determined by `assertion_info.n_args` which has the total number of arguments passed to the assertion macro
- Where clause
- `open(path, 0)`: `assertion_info.binary_diagnostics.left_expression`
- `-1`: `assertion_info.binary_diagnostics.left_stringification`
- Same for the right side (omitted in this case because `0 => 0` isn't useful)
- Extra diagnostics
- `errno`: `assertion_info.extra_diagnostics[0].expression`
- `2 "No such file or directory"`: `assertion_info.extra_diagnostics[0].stringification`
- ... etc.
- Stack trace
- `assertion_info.get_stacktrace()`, or `assertion_info.get_raw_trace()` to get the trace without resolving it

**Helpers:**

`assertion_info.header()`:

```
Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
debug_assert(open(path, 0) >= 0, ...);
Where:
open(path, 0) => -1
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
```

`assertion_info.tagline()`:

```
Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
```

`assertion_info.statement()`:

```
debug_assert(open(path, 0) >= 0, ...);
```

`assertion_info.print_binary_diagnostics()`:

```
Where:
open(path, 0) => -1
```

`assertion_info.print_extra_diagnostics()`:

```
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
```

`assertion_info.print_stacktrace()`:

```
Stack trace:
#1 demo.cpp:194 foo::baz()
#2 demo.cpp:172 void foo::bar<int>(std::pair<int, int>)
#3 demo.cpp:396 main
```

## Stringification

Libassert provides a customization point for user-defined types?
Expand Down
48 changes: 37 additions & 11 deletions include/libassert/assert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>
#ifdef __cpp_lib_expected
#include <expected>
Expand Down Expand Up @@ -1070,7 +1071,7 @@ namespace libassert {

// collection of assertion data that can be put in static storage and all passed by a single pointer
struct LIBASSERT_EXPORT assert_static_parameters {
std::string_view name;
std::string_view macro_name;
assert_type type;
std::string_view expr_str;
source_location location;
Expand All @@ -1082,31 +1083,56 @@ namespace libassert {
std::string stringification;
};

namespace detail {
class path_handler {
public:
virtual ~path_handler() = default;
virtual std::string_view resolve_path(std::string_view) = 0;
virtual bool has_add_path() const;
virtual void add_path(std::string_view);
virtual void finalize();
};
}

struct LIBASSERT_EXPORT assertion_info {
std::string_view name;
std::string_view macro_name;
assert_type type;
std::string_view expression_string;
std::string_view file_name;
std::uint32_t line;
std::vector<std::string_view> args_strings;
std::string message;
std::string_view function;
std::optional<std::string> message;
std::optional<binary_diagnostics_descriptor> binary_diagnostics;
std::vector<extra_diagnostic> extra_diagnostics;
std::string_view pretty_function;
cpptrace::raw_trace raw_trace;
size_t sizeof_args;
size_t n_args;
private:
mutable std::variant<cpptrace::raw_trace, cpptrace::stacktrace> trace; // lazy, resolved when needed
mutable std::unique_ptr<detail::path_handler> path_handler;
detail::path_handler* get_path_handler() const; // will get and setup the path handler
public:
assertion_info() = delete;
assertion_info(
const assert_static_parameters* static_params,
cpptrace::raw_trace&& raw_trace,
size_t sizeof_args
size_t n_args
);
~assertion_info();
assertion_info(const assertion_info&) = delete;
assertion_info(assertion_info&&) = delete;
assertion_info(assertion_info&&);
assertion_info& operator=(const assertion_info&) = delete;
assertion_info& operator=(assertion_info&&) = delete;
assertion_info& operator=(assertion_info&&);

std::string_view action() const;

const cpptrace::raw_trace& get_raw_trace() const;
const cpptrace::stacktrace& get_stacktrace() const;

std::string header(int width = 0, const color_scheme& scheme = get_color_scheme()) const;
std::string tagline(const color_scheme& scheme = get_color_scheme()) const;
std::string statement(const color_scheme& scheme = get_color_scheme()) const;
std::string print_binary_diagnostics(int width = 0, const color_scheme& scheme = get_color_scheme()) const;
std::string print_extra_diagnostics(int width = 0, const color_scheme& scheme = get_color_scheme()) const;
std::string print_stacktrace(int width = 0, const color_scheme& scheme = get_color_scheme()) const;

[[nodiscard]] std::string to_string(int width = 0, const color_scheme& scheme = get_color_scheme()) const;
};
Expand Down Expand Up @@ -1196,7 +1222,7 @@ namespace libassert::detail {
sv_span,
const pretty_function_name_wrapper& t
) {
info.pretty_function = t.pretty_function;
info.function = t.pretty_function;
}

template<typename T>
Expand Down
Loading

0 comments on commit 3e6061b

Please sign in to comment.