created macros for assertions and warnings. The assert macro prints the whole callstack on crash. The warning macro can just log a warning or call an assertion fail depending on the cmake flag STOP_ON_WARNING

This commit is contained in:
Francisco 2021-03-22 17:37:08 +00:00 committed by Francisco Paisana
parent 9d8d897d3e
commit b5692037a2
6 changed files with 108 additions and 42 deletions

View File

@ -81,6 +81,8 @@ option(ENABLE_TIMEPROF "Enable time profiling" ON)
option(FORCE_32BIT "Add flags to force 32 bit compilation" OFF)
option(ENABLE_SRSLOG_TRACING "Enable event tracing using srslog" OFF)
option(ASSERTS_ENABLED "Enable srsRAN asserts" ON)
option(STOP_ON_WARNING "Interrupt application on warning" OFF)
# Users that want to try this feature need to make sure the lto plugin is
# loaded by bintools (ar, nm, ...). Older versions of bintools will not do
@ -107,6 +109,14 @@ if (ENABLE_SRSLOG_TRACING)
add_definitions(-DENABLE_SRSLOG_EVENT_TRACE)
endif (ENABLE_SRSLOG_TRACING)
if (ASSERTS_ENABLED)
add_definitions(-DASSERTS_ENABLED)
endif()
if (STOP_ON_WARNING)
add_definitions(-DSTOP_ON_WARNING)
endif()
########################################################################
# Find dependencies
########################################################################

View File

@ -14,15 +14,15 @@
#define SRSRAN_ID_MAP_H
#include "expected.h"
#include "srsran/common/srsran_assert.h"
#include <array>
#include <cassert>
namespace srsran {
template <typename K, typename T, size_t N>
class static_circular_map
{
static_assert(std::is_integral<K>::value, "Map key must be an integer");
static_assert(std::is_integral<K>::value and std::is_unsigned<K>::value, "Map key must be an unsigned integer");
using obj_t = std::pair<K, T>;
using obj_storage_t = typename std::aligned_storage<sizeof(obj_t), alignof(obj_t)>::type;
@ -48,22 +48,22 @@ public:
obj_t& operator*()
{
assert(idx < ptr->buffer.size() && "Index out-of-bounds");
srsran_assert(idx < ptr->buffer.size(), "Iterator out-of-bounds (%zd >= %zd)", idx, ptr->buffer.size());
return ptr->get_obj_(idx);
}
obj_t* operator->()
{
assert(idx < ptr->buffer.size() && "Index out-of-bounds");
srsran_assert(idx < ptr->buffer.size(), "Iterator out-of-bounds (%zd >= %zd)", idx, ptr->buffer.size());
return &ptr->get_obj_(idx);
}
const obj_t* operator*() const
{
assert(idx < ptr->buffer.size() && "Index out-of-bounds");
srsran_assert(idx < ptr->buffer.size(), "Iterator out-of-bounds (%zd >= %zd)", idx, ptr->buffer.size());
return ptr->buffer[idx];
}
const obj_t* operator->() const
{
assert(idx < ptr->buffer.size() && "Index out-of-bounds");
srsran_assert(idx < ptr->buffer.size(), "Iterator out-of-bounds (%zd >= %zd)", idx, ptr->buffer.size());
return ptr->buffer[idx];
}
@ -189,7 +189,7 @@ public:
iterator erase(iterator it)
{
assert(it.idx < N);
srsran_assert(it.idx < N, "Iterator out-of-bounds (%zd >= %zd)", it.idx, N);
iterator next = it;
++next;
it->~obj_t();
@ -207,12 +207,12 @@ public:
T& operator[](K id)
{
assert(contains(id));
srsran_assert(contains(id), "Accessing non-existent ID=%zd", (size_t)id);
return get_obj_(id % N).second;
}
const T& operator[](K id) const
{
assert(contains(id));
srsran_assert(contains(id), "Accessing non-existent ID=%zd", (size_t)id);
return get_obj_(id % N).second;
}

View File

@ -0,0 +1,60 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_ASSERT_H
#define SRSRAN_ASSERT_H
#include "srsran/common/standard_streams.h"
#include "srsran/srslog/srslog.h"
#ifdef ASSERTS_ENABLED
#define srsran_unlikely(expr) __builtin_expect(!!(expr), 0)
#define srsran_assert(condition, fmt, ...) \
do { \
if (srsran_unlikely(not(condition))) { \
srslog::fetch_basic_logger("ALL").error("%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
srsran::console_stderr("%s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
srslog::flush(); \
std::abort(); \
} \
} while (0)
#ifdef STOP_ON_WARNING
#define srsran_warning(condition, fmt, ...) srsran_assert(condition, fmt, ##__VA_ARGS__)
#else // STOP_ON_WARNING
#define srsran_warning(condition, fmt, ...) \
do { \
if (srsran_unlikely(not(condition))) { \
srslog::fetch_basic_logger("ALL").warning("%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
} \
} while (0)
#endif // STOP_ON_WARNING
#else // ASSERTS_ENABLED
#define srslte_assert(condition, fmt, ...) \
do { \
} while (0)
#define srsran_warning(condition, fmt, ...) \
do { \
} while (0)
#endif
#endif // SRSRAN_ASSERT_H

View File

@ -17,6 +17,8 @@
#ifdef __cplusplus
#include "srsran/common/crash_handler.h"
#include "srsran/common/srsran_assert.h"
#include "srsran/common/standard_streams.h"
#include "srsran/srslog/srslog.h"
#include <atomic>
@ -128,27 +130,24 @@ private:
std::vector<std::string> entries;
};
inline void test_init(int argc, char** argv)
{
// Setup a backtrace pretty printer
srsran_debug_handle_crash(argc, argv);
srslog::fetch_basic_logger("ALL").set_level(srslog::basic_levels::info);
// Start the log backend.
srslog::init();
}
} // namespace srsran
#define TESTERROR(fmt, ...) \
do { \
srslog::fetch_basic_logger("TEST").error(fmt, ##__VA_ARGS__); \
return SRSRAN_ERROR; \
} while (0)
#define CONDERROR(cond, fmt, ...) srsran_assert(not(cond), fmt, ##__VA_ARGS__)
#define TESTWARN(fmt, ...) \
do { \
srslog::fetch_basic_logger("TEST").warning(fmt, ##__VA_ARGS__); \
} while (0)
#define TESTERROR(fmt, ...) CONDERROR(true, fmt, ##__VA_ARGS__)
#define CONDERROR(cond, fmt, ...) \
do { \
if (cond) { \
TESTERROR(fmt, ##__VA_ARGS__); \
} \
} while (0)
#define TESTASSERT(cond) CONDERROR((not(cond)), "[%s][Line %d] Fail at \"%s\"", __FUNCTION__, __LINE__, (#cond))
#define TESTASSERT(cond) srsran_assert((cond), "Fail at \"%s\"", (#cond))
#else // if C

View File

@ -10,8 +10,8 @@
*
*/
#include "srsran/common/test_common.h"
#include "srsran/adt/circular_map.h"
#include "srsran/common/test_common.h"
namespace srsran {
@ -87,13 +87,12 @@ int test_id_map_wraparound()
} // namespace srsran
int main()
int main(int argc, char** argv)
{
auto& test_log = srslog::fetch_basic_logger("TEST");
test_log.set_level(srslog::basic_levels::info);
// Start the log backend.
srslog::init();
srsran::test_init(argc, argv);
TESTASSERT(srsran::test_id_map() == SRSRAN_SUCCESS);
TESTASSERT(srsran::test_id_map_wraparound() == SRSRAN_SUCCESS);

View File

@ -28,12 +28,11 @@ int test_pusch_collisions(const sf_output_res_t& sf_out, uint32_t enb_cc_idx, co
auto try_ul_fill = [&](prb_interval alloc, const char* ch_str, bool strict = true) {
CONDERROR(alloc.stop() > nof_prb, "Allocated RBs %s out-of-bounds", fmt::format("{}", alloc).c_str());
CONDERROR(alloc.empty(), "Allocations must have at least one PRB");
if (strict and ul_allocs.any(alloc.start(), alloc.stop())) {
TESTERROR("Collision Detected of %s alloc=%s and cumulative_mask=0x%s",
ch_str,
fmt::format("{}", alloc).c_str(),
fmt::format("{:x}", ul_allocs).c_str());
}
CONDERROR(strict and ul_allocs.any(alloc.start(), alloc.stop()),
"Collision Detected of %s alloc=%s and cumulative_mask=0x%s",
ch_str,
fmt::format("{}", alloc).c_str(),
fmt::format("{:x}", ul_allocs).c_str());
ul_allocs.fill(alloc.start(), alloc.stop(), true);
return SRSRAN_SUCCESS;
};
@ -102,12 +101,11 @@ int test_pdsch_collisions(const sf_output_res_t& sf_out, uint32_t enb_cc_idx, co
return SRSRAN_ERROR;
}
CONDERROR(alloc_mask.none(), "DL allocation must occupy at least one RBG.");
if ((dl_allocs & alloc_mask).any()) {
TESTERROR("Detected collision in the DL %s allocation (%s intersects %s)",
channel,
fmt::format("{}", dl_allocs).c_str(),
fmt::format("{}", alloc_mask).c_str());
}
CONDERROR((dl_allocs & alloc_mask).any(),
"Detected collision in the DL %s allocation (%s intersects %s)",
channel,
fmt::format("{}", dl_allocs).c_str(),
fmt::format("{}", alloc_mask).c_str());
dl_allocs |= alloc_mask;
return SRSRAN_SUCCESS;
};