Skip to content

batteries/assert.hpp

batteries/assert.hpp🔗

Namespaces🔗

Name
batt

Defines🔗

Name
BATT_FAIL_CHECK_OUT
BATT_FAIL_CHECK_MESSAGE(left_str, left_val, op_str, right_str, right_val, file, line, fn_name)
BATT_NORETURN
BATT_UNREACHABLE()
BATT_THIS_FUNCTION
BATT_CHECK_RELATION(left, op, right)
BATT_CHECK_IMPLIES(p, q)
BATT_CHECK(x)
This is only a test...
BATT_CHECK_EQ(x, y)
BATT_CHECK_NE(x, y)
BATT_CHECK_GE(x, y)
BATT_CHECK_GT(x, y)
BATT_CHECK_LE(x, y)
BATT_CHECK_LT(x, y)
BATT_CHECK_FAIL()
BATT_CHECK_IN_RANGE(low, x, high)
BATT_ASSERT_DISABLED(ignored_inputs)
BATT_ASSERT(x)
BATT_ASSERT_EQ(x, y)
BATT_ASSERT_NE(x, y)
BATT_ASSERT_GE(x, y)
BATT_ASSERT_GT(x, y)
BATT_ASSERT_LE(x, y)
BATT_ASSERT_LT(x, y)
BATT_ASSERT_IMPLIES(p, q)
BATT_ASSERT_IN_RANGE(low, x, high)
BATT_ASSERT_NOT_NULLPTR(x)
BATT_CHECK_NOT_NULLPTR(x)
BATT_PANIC()
BATT_INSPECT(expr)
BATT_UNTESTED_LINE()
BATT_UNTESTED_COND(x)

Macro Documentation🔗

define BATT_FAIL_CHECK_OUT🔗

#define BATT_FAIL_CHECK_OUT()

define BATT_FAIL_CHECK_MESSAGE🔗

#define BATT_FAIL_CHECK_MESSAGE(left_str, left_val, op_str, right_str, right_val, file, line, fn_name)

define BATT_NORETURN🔗

#define BATT_NORETURN()

define BATT_UNREACHABLE🔗

#define BATT_UNREACHABLE()

define BATT_THIS_FUNCTION🔗

#define BATT_THIS_FUNCTION()

define BATT_CHECK_RELATION🔗

#define BATT_CHECK_RELATION(left, op, right)

define BATT_CHECK_IMPLIES🔗

#define BATT_CHECK_IMPLIES(p, q)

define BATT_CHECK🔗

#define BATT_CHECK(x)

This is only a test...

Parameters:

  • x The expression to test.

define BATT_CHECK_EQ🔗

#define BATT_CHECK_EQ(x, y)

define BATT_CHECK_NE🔗

#define BATT_CHECK_NE(x, y)

define BATT_CHECK_GE🔗

#define BATT_CHECK_GE(x, y)

define BATT_CHECK_GT🔗

#define BATT_CHECK_GT(x, y)

define BATT_CHECK_LE🔗

#define BATT_CHECK_LE(x, y)

define BATT_CHECK_LT🔗

#define BATT_CHECK_LT(x, y)

define BATT_CHECK_FAIL🔗

#define BATT_CHECK_FAIL()

define BATT_CHECK_IN_RANGE🔗

#define BATT_CHECK_IN_RANGE(low, x, high)

define BATT_ASSERT_DISABLED🔗

#define BATT_ASSERT_DISABLED(ignored_inputs)

define BATT_ASSERT🔗

#define BATT_ASSERT(x)

define BATT_ASSERT_EQ🔗

#define BATT_ASSERT_EQ(x, y)

define BATT_ASSERT_NE🔗

#define BATT_ASSERT_NE(x, y)

define BATT_ASSERT_GE🔗

#define BATT_ASSERT_GE(x, y)

define BATT_ASSERT_GT🔗

#define BATT_ASSERT_GT(x, y)

define BATT_ASSERT_LE🔗

#define BATT_ASSERT_LE(x, y)

define BATT_ASSERT_LT🔗

#define BATT_ASSERT_LT(x, y)

define BATT_ASSERT_IMPLIES🔗

#define BATT_ASSERT_IMPLIES(p, q)

define BATT_ASSERT_IN_RANGE🔗

#define BATT_ASSERT_IN_RANGE(low, x, high)

define BATT_ASSERT_NOT_NULLPTR🔗

#define BATT_ASSERT_NOT_NULLPTR(x)

define BATT_CHECK_NOT_NULLPTR🔗

#define BATT_CHECK_NOT_NULLPTR(x)

define BATT_PANIC🔗

#define BATT_PANIC()

define BATT_INSPECT🔗

#define BATT_INSPECT(expr)

define BATT_UNTESTED_LINE🔗

#define BATT_UNTESTED_LINE()

define BATT_UNTESTED_COND🔗

#define BATT_UNTESTED_COND(x)

Source code🔗

//######=###=##=#=#=#=#=#==#==#====#+==#+==============+==+==+==+=+==+=+=+=+=+=+=+
// Copyright 2021-2023 Anthony Paul Astolfi
//
#pragma once

#ifdef BOOST_STACKTRACE_USE_NOOP
#undef BOOST_STACKTRACE_USE_NOOP
#endif  // BOOST_STACKTRACE_USE_NOOP

#include <batteries/config.hpp>
//
#include <batteries/hint.hpp>
#include <batteries/int_types.hpp>
#include <batteries/logging.hpp>
#include <batteries/make_printable.hpp>
#include <batteries/stacktrace.hpp>
#include <batteries/type_traits.hpp>
#include <batteries/utility.hpp>

#include <iomanip>
#include <iostream>
#include <sstream>

#ifdef BATT_FAIL_CHECK_OUT
#error This macro is deprecated; use BATT_WITH_GLOG
#endif

#if BATT_WITH_GLOG
#define BATT_FAIL_CHECK_OUT BATT_LOG_ERROR()
#else
#define BATT_FAIL_CHECK_OUT std::cerr
#endif

namespace batt {

// =============================================================================
// ASSERT and CHECK macros with ostream-style message appending, stack trace on
// failure, branch prediction hinting, and human-friendly messages.
//
// BATT_ASSERT* statements are only enabled when NDEBUG is not defined.
// BATT_CHECK* statements are always enabled.
//
#define BATT_FAIL_CHECK_MESSAGE(left_str, left_val, op_str, right_str, right_val, file, line, fn_name)       \
    BATT_FAIL_CHECK_OUT << "FATAL: " << file << ":" << line << ": Assertion failed: " << left_str << " "     \
                        << op_str << " " << right_str << "\n (in `" << fn_name << "`)\n\n"                   \
                        << "  " << left_str << " == " << ::batt::make_printable(left_val) << ::std::endl     \
                        << ::std::endl                                                                       \
                        << "  " << right_str << " == " << ::batt::make_printable(right_val) << ::std::endl   \
                        << ::std::endl

//==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- -  -  -   -
#if defined(__GNUC__)
#define BATT_NORETURN __attribute__((noreturn))
#define BATT_UNREACHABLE __builtin_unreachable

#elif defined(__clang__)
#define BATT_NORETURN _Noreturn
#define BATT_UNREACHABLE __builtin_unreachable

#elif defined(_MSC_VER)
#define BATT_NORETURN [[noreturn]]
#define BATT_UNREACHABLE() __assume(0)

#else
#define BATT_NORETURN
#define BATT_UNREACHABLE() (void)0
#endif
//+++++++++++-+-+--+----- --- -- -  -  -   -

BATT_NORETURN void fail_check_exit();

std::atomic<bool>& fail_check_exit_entered();

std::atomic<bool>& fail_check_spin_lock();

template <typename... Ts>
inline bool ignore(Ts&&...)
{
    return false;
}

bool lock_fail_check_mutex();

#ifdef BATT_PLATFORM_IS_WINDOWS
#define BATT_THIS_FUNCTION __FUNCTION__
#else
#define BATT_THIS_FUNCTION __PRETTY_FUNCTION__
#endif

#define BATT_CHECK_RELATION(left, op, right)                                                                 \
    for (; !BATT_HINT_TRUE((left)op(right)) && BATT_HINT_TRUE(::batt::lock_fail_check_mutex());              \
         ::batt::fail_check_exit())                                                                          \
    BATT_FAIL_CHECK_MESSAGE(#left, (left), #op, #right, (right), __FILE__, __LINE__, BATT_THIS_FUNCTION)

#define BATT_CHECK_IMPLIES(p, q)                                                                             \
    for (; !BATT_HINT_TRUE(!(p) || (q)) && BATT_HINT_TRUE(::batt::lock_fail_check_mutex());                  \
         ::batt::fail_check_exit())                                                                          \
    BATT_FAIL_CHECK_MESSAGE(#p, (p), "implies", #q, (q), __FILE__, __LINE__, BATT_THIS_FUNCTION)

#define BATT_CHECK(x) BATT_CHECK_RELATION(bool{x}, ==, true)

#define BATT_CHECK_EQ(x, y) BATT_CHECK_RELATION(x, ==, y)
#define BATT_CHECK_NE(x, y) BATT_CHECK_RELATION(x, !=, y)
#define BATT_CHECK_GE(x, y) BATT_CHECK_RELATION(x, >=, y)
#define BATT_CHECK_GT(x, y) BATT_CHECK_RELATION(x, >, y)
#define BATT_CHECK_LE(x, y) BATT_CHECK_RELATION(x, <=, y)
#define BATT_CHECK_LT(x, y) BATT_CHECK_RELATION(x, <, y)
#define BATT_CHECK_FAIL() BATT_CHECK(false)

#define BATT_CHECK_IN_RANGE(low, x, high)                                                                    \
    [&](auto&& Actual_Value) {                                                                               \
        BATT_CHECK_LE(low, Actual_Value)                                                                     \
            << "Expression " << #x << " == " << Actual_Value << " is out-of-range";                          \
        BATT_CHECK_LT(Actual_Value, high)                                                                    \
            << "Expression " << #x << " == " << Actual_Value << " is out-of-range";                          \
    }(x)
#define BATT_ASSERT_DISABLED(ignored_inputs)                                                                 \
    if (false && ignored_inputs)                                                                             \
    BATT_FAIL_CHECK_OUT << ""

#if BATT_WITH_ASSERTS  //==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- -  -  -   -

#define BATT_ASSERT(x) BATT_CHECK(x)
#define BATT_ASSERT_EQ(x, y) BATT_CHECK_EQ(x, y)
#define BATT_ASSERT_NE(x, y) BATT_CHECK_NE(x, y)
#define BATT_ASSERT_GE(x, y) BATT_CHECK_GE(x, y)
#define BATT_ASSERT_GT(x, y) BATT_CHECK_GT(x, y)
#define BATT_ASSERT_LE(x, y) BATT_CHECK_LE(x, y)
#define BATT_ASSERT_LT(x, y) BATT_CHECK_LT(x, y)
#define BATT_ASSERT_IMPLIES(p, q) BATT_CHECK_IMPLIES(p, q)
#define BATT_ASSERT_IN_RANGE(low, x, high) BATT_CHECK_IN_RANGE(low, x, high)

#else  // !BATT_WITH_ASSERTS  ==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- -  -  -   -

#define BATT_ASSERT(x) BATT_ASSERT_DISABLED(::batt::ignore((x)))
#define BATT_ASSERT_EQ(x, y) BATT_ASSERT_DISABLED(::batt::ignore((x), (y), (x) == (y)))
#define BATT_ASSERT_NE(x, y) BATT_ASSERT_DISABLED(::batt::ignore((x), (y), (x) != (y)))
#define BATT_ASSERT_GE(x, y) BATT_ASSERT_DISABLED(::batt::ignore((x), (y), (x) >= (y)))
#define BATT_ASSERT_GT(x, y) BATT_ASSERT_DISABLED(::batt::ignore((x), (y), (x) > (y)))
#define BATT_ASSERT_LE(x, y) BATT_ASSERT_DISABLED(::batt::ignore((x), (y), (x) <= (y)))
#define BATT_ASSERT_LT(x, y) BATT_ASSERT_DISABLED(::batt::ignore((x), (y), (x) < (y)))
#define BATT_ASSERT_IMPLIES(p, q) BATT_ASSERT_DISABLED(::batt::ignore((p), (q), !(p), bool(q)))
#define BATT_ASSERT_IN_RANGE(low, x, high)                                                                   \
    BATT_ASSERT_DISABLED(::batt::ignore((low), (x), (high), (low) <= (x), (x) < (high)))

#endif  // (BATT_WITH_ASSERTS) ==#==========+==+=+=++=+++++++++++-+-+--+----- --- -- -  -  -   -

#define BATT_ASSERT_NOT_NULLPTR(x) BATT_ASSERT(x != nullptr)
#define BATT_CHECK_NOT_NULLPTR(x) BATT_CHECK(x != nullptr)

#define BATT_PANIC()                                                                                         \
    for (bool one_time = true; one_time; one_time = false, ::batt::fail_check_exit(), BATT_UNREACHABLE())    \
    BATT_FAIL_CHECK_OUT << "*** PANIC *** At:\n" << __FILE__ << ":" << __LINE__ << ":" << std::endl

//=#=#==#==#===============+=+=+=+=++=++++++++++++++-++-+--+-+----+---------------
// BATT_INSPECT(expr) : expand to debug-friendly stream insertion expression.
// TODO [tastolfi 2021-10-20] Update docs for assert.hpp to include BATT_INSPECT
//
#define BATT_INSPECT(expr) " " << #expr << " == " << (expr)

#define BATT_UNTESTED_LINE() BATT_PANIC() << "Add test point!"
#define BATT_UNTESTED_COND(x) BATT_CHECK(!(x)) << "Add test point!"

}  // namespace batt

#include <batteries/segv.hpp>

#if BATT_HEADER_ONLY
#include <batteries/assert_impl.hpp>
#endif  // BATT_HEADER_ONLY

Updated on 31 January 2025 at 21:21:05 UTC