Apply srsLTE formatting rules to srsLog. They were previously formatted with different rules when the project lived in the external rapo.

master
faluco 4 years ago committed by faluco
parent 873f375ecc
commit 1ccb62af3d

@ -35,13 +35,13 @@ struct metrics_container {
template <typename T, typename Arg> template <typename T, typename Arg>
void write(Arg&& arg) void write(Arg&& arg)
{ {
constexpr std::size_t index = detail::get_type_index_in_tuple<T, Ts...>(); constexpr std::size_t index = detail::get_type_index_in_tuple<T, Ts...>();
std::get<index>(metrics).value = std::forward<Arg>(arg); std::get<index>(metrics).value = std::forward<Arg>(arg);
} }
/// Returns the value of metric T. /// Returns the value of metric T.
template <typename T> template <typename T>
auto read() const -> const decltype(T::value)& auto read() const -> const decltype(T::value) &
{ {
constexpr std::size_t index = detail::get_type_index_in_tuple<T, Ts...>(); constexpr std::size_t index = detail::get_type_index_in_tuple<T, Ts...>();
return std::get<index>(metrics).value; return std::get<index>(metrics).value;
@ -69,7 +69,7 @@ struct metrics_container {
auto at(std::size_t i) -> typename T::value_type& auto at(std::size_t i) -> typename T::value_type&
{ {
constexpr std::size_t index = detail::get_type_index_in_tuple<T, Ts...>(); constexpr std::size_t index = detail::get_type_index_in_tuple<T, Ts...>();
auto& elem = std::get<index>(metrics); auto& elem = std::get<index>(metrics);
assert(i < elem.size() && "Invalid index"); assert(i < elem.size() && "Invalid index");
return elem[i]; return elem[i];
} }
@ -80,7 +80,7 @@ struct metrics_container {
auto at(std::size_t i) const -> const typename T::value_type& auto at(std::size_t i) const -> const typename T::value_type&
{ {
constexpr std::size_t index = detail::get_type_index_in_tuple<T, Ts...>(); constexpr std::size_t index = detail::get_type_index_in_tuple<T, Ts...>();
const auto& elem = std::get<index>(metrics); const auto& elem = std::get<index>(metrics);
assert(i < elem.size() && "Invalid index"); assert(i < elem.size() && "Invalid index");
return elem[i]; return elem[i];
} }
@ -124,18 +124,13 @@ struct metric {
static const char* units() { return Units::units(); } static const char* units() { return Units::units(); }
/// Returns the formatting kind of the metric. /// Returns the formatting kind of the metric.
static metric_kind kind() static metric_kind kind() { return metric_kind_selector<metric<Ty, Name, Units> >::kind; }
{
return metric_kind_selector<metric<Ty, Name, Units>>::kind;
}
}; };
/// Template specialization that tags metrics with arithmetic values (integers /// Template specialization that tags metrics with arithmetic values (integers
/// and floating point) as numeric. /// and floating point) as numeric.
template <typename Ty, typename Name, typename Units> template <typename Ty, typename Name, typename Units>
struct metric_kind_selector< struct metric_kind_selector<metric<Ty, Name, Units>, typename std::enable_if<std::is_arithmetic<Ty>::value>::type> {
metric<Ty, Name, Units>,
typename std::enable_if<std::is_arithmetic<Ty>::value>::type> {
static const metric_kind kind = metric_kind::numeric; static const metric_kind kind = metric_kind::numeric;
}; };
@ -168,8 +163,7 @@ namespace detail {
/// eg: using my_metric_t = srslog::build_metric_set_type<m1_t, set1_t, m2_t>; /// eg: using my_metric_t = srslog::build_metric_set_type<m1_t, set1_t, m2_t>;
/// NOTE: Adding duplicated types into the list is not allowed. /// NOTE: Adding duplicated types into the list is not allowed.
template <typename Name, typename... Ts> template <typename Name, typename... Ts>
using build_metric_set_type = using build_metric_set_type = metric_set<Name, typename std::decay<Ts>::type...>;
metric_set<Name, typename std::decay<Ts>::type...>;
} // namespace detail } // namespace detail
@ -191,18 +185,17 @@ using build_context_type = context<typename std::decay<Ts>::type...>;
/// c) units: MB/s /// c) units: MB/s
/// d) name: Throughput /// d) name: Throughput
/// DECLARE_METRIC("Throughput", my_metric_t, float, "MB/s"); /// DECLARE_METRIC("Throughput", my_metric_t, float, "MB/s");
#define DECLARE_METRIC(_name_rep, _type, _value_type, _units) \ #define DECLARE_METRIC(_name_rep, _type, _value_type, _units) \
namespace metric_info { \ namespace metric_info { \
struct _type##__units { \ struct _type##__units { \
static const char* units() { return _units; } \ static const char* units() { return _units; } \
}; \ }; \
struct _type##__name_rep { \ struct _type##__name_rep { \
static const char* name() { return _name_rep; } \ static const char* name() { return _name_rep; } \
}; \ }; \
} \ } \
using _type = srslog::metric<typename std::decay<_value_type>::type, \ using _type = srslog:: \
metric_info::_type##__name_rep, \ metric<typename std::decay<_value_type>::type, metric_info::_type##__name_rep, metric_info::_type##__units>
metric_info::_type##__units>
/// This macro defines a new metric set type using the following attributes: /// This macro defines a new metric set type using the following attributes:
/// a) name: encoded as a string. /// a) name: encoded as a string.
@ -216,14 +209,13 @@ using build_context_type = context<typename std::decay<Ts>::type...>;
/// b) name: my_set /// b) name: my_set
/// b) type list: metric1_t, metric2_t, set2_t /// b) type list: metric1_t, metric2_t, set2_t
/// DECLARE_METRIC_SET("my_set", my_set_t, metric1_t, metric2_t, set2_t); /// DECLARE_METRIC_SET("my_set", my_set_t, metric1_t, metric2_t, set2_t);
#define DECLARE_METRIC_SET(_name_rep, _type, ...) \ #define DECLARE_METRIC_SET(_name_rep, _type, ...) \
namespace metric_set_info { \ namespace metric_set_info { \
struct _type##__name_rep { \ struct _type##__name_rep { \
static const char* name() { return _name_rep; } \ static const char* name() { return _name_rep; } \
}; \ }; \
} \ } \
using _type = srslog::detail:: \ using _type = srslog::detail::build_metric_set_type<metric_set_info::_type##__name_rep, __VA_ARGS__>
build_metric_set_type<metric_set_info::_type##__name_rep, __VA_ARGS__>
/// This macro defines a list of metric sets of the same type: /// This macro defines a list of metric sets of the same type:
/// a) name: encoded as a string. /// a) name: encoded as a string.
@ -236,14 +228,13 @@ using build_context_type = context<typename std::decay<Ts>::type...>;
/// b) name: my_list /// b) name: my_list
/// b) underlying type: std::vector<set1_t> /// b) underlying type: std::vector<set1_t>
/// DECLARE_METRIC_LIST("my_list", my_list_t, std::vector<set1_t>); /// DECLARE_METRIC_LIST("my_list", my_list_t, std::vector<set1_t>);
#define DECLARE_METRIC_LIST(_name_rep, _type, _list_type) \ #define DECLARE_METRIC_LIST(_name_rep, _type, _list_type) \
namespace list_info { \ namespace list_info { \
struct _type##__name_rep { \ struct _type##__name_rep { \
static const char* name() { return _name_rep; } \ static const char* name() { return _name_rep; } \
}; \ }; \
} \ } \
using _type = srslog::metric_list<list_info::_type##__name_rep, \ using _type = srslog::metric_list<list_info::_type##__name_rep, typename std::decay<_list_type>::type>
typename std::decay<_list_type>::type>
} // namespace srslog } // namespace srslog

@ -25,19 +25,18 @@ namespace detail {
/// This command flushes all the messages pending in the backend. /// This command flushes all the messages pending in the backend.
struct flush_backend_cmd { struct flush_backend_cmd {
shared_variable<bool>& completion_flag; shared_variable<bool>& completion_flag;
std::vector<sink*> sinks; std::vector<sink*> sinks;
}; };
/// This structure packs all the required data required to create a log entry in /// This structure packs all the required data required to create a log entry in
/// the backend. /// the backend.
//:TODO: replace this object using a real command pattern when we have a raw //: TODO: replace this object using a real command pattern when we have a raw
// memory queue for passing entries. // memory queue for passing entries.
struct log_entry { struct log_entry {
sink* s; sink* s;
std::function<void(log_entry_metadata&& metadata, fmt::memory_buffer& buffer)> std::function<void(log_entry_metadata&& metadata, fmt::memory_buffer& buffer)> format_func;
format_func; log_entry_metadata metadata;
log_entry_metadata metadata; std::unique_ptr<flush_backend_cmd> flush_cmd;
std::unique_ptr<flush_backend_cmd> flush_cmd;
}; };
} // namespace detail } // namespace detail

@ -24,7 +24,7 @@ using small_str_buffer = fmt::basic_memory_buffer<char, 64>;
namespace detail { namespace detail {
/// This structure gives the user a way to log generic information as a context. /// This structure gives the user a way to log generic information as a context.
//:TODO: legacy struct, will get replaced by the new context framework. //: TODO: legacy struct, will get replaced by the new context framework.
struct log_context { struct log_context {
/// Generic context value. /// Generic context value.
uint32_t value; uint32_t value;

@ -30,7 +30,7 @@ struct in_place_type_t {
template <typename T> template <typename T>
struct is_in_place_type_t : std::false_type {}; struct is_in_place_type_t : std::false_type {};
template <typename T> template <typename T>
struct is_in_place_type_t<in_place_type_t<T>> : std::true_type {}; struct is_in_place_type_t<in_place_type_t<T> > : std::true_type {};
/// This is a very minimalist and non compliant implementation of std::any which /// This is a very minimalist and non compliant implementation of std::any which
/// is included in C++17. /// is included in C++17.
@ -39,7 +39,7 @@ struct is_in_place_type_t<in_place_type_t<T>> : std::true_type {};
class any class any
{ {
public: public:
//:TODO: Clang 3.8 does not compile when default constructing a const object //: TODO: Clang 3.8 does not compile when default constructing a const object
// due to DR253. Declare the defaulted constructor out of the class. // due to DR253. Declare the defaulted constructor out of the class.
any(); any();
@ -54,15 +54,12 @@ public:
/// b) is move constructible. /// b) is move constructible.
/// c) is not an specialization of in_place_type_t. /// c) is not an specialization of in_place_type_t.
/// Otherwise the rest of special member functions are considered. /// Otherwise the rest of special member functions are considered.
template < template <typename T,
typename T, typename std::enable_if<!std::is_same<typename std::decay<T>::type, any>{} &&
typename std::enable_if< std::is_move_constructible<typename std::decay<T>::type>{} &&
!std::is_same<typename std::decay<T>::type, any>{} && !is_in_place_type_t<typename std::decay<T>::type>{},
std::is_move_constructible<typename std::decay<T>::type>{} && int>::type = 0>
!is_in_place_type_t<typename std::decay<T>::type>{}, explicit any(T&& t) : storage(new storage_impl<typename std::decay<T>::type>(std::forward<T>(t)))
int>::type = 0>
explicit any(T&& t) :
storage(new storage_impl<typename std::decay<T>::type>(std::forward<T>(t)))
{} {}
/// Constructs an object of type decayed T directly into the internal storage /// Constructs an object of type decayed T directly into the internal storage
@ -73,12 +70,9 @@ public:
/// Otherwise the rest of special member functions are considered. /// Otherwise the rest of special member functions are considered.
template <typename T, template <typename T,
typename... Args, typename... Args,
typename std::enable_if< typename std::enable_if<std::is_constructible<typename std::decay<T>::type, Args...>{}, int>::type = 0>
std::is_constructible<typename std::decay<T>::type, Args...>{},
int>::type = 0>
explicit any(in_place_type_t<T>, Args&&... args) : explicit any(in_place_type_t<T>, Args&&... args) :
storage(new storage_impl<typename std::decay<T>::type>( storage(new storage_impl<typename std::decay<T>::type>(std::forward<Args>(args)...))
std::forward<Args>(args)...))
{} {}
any(any&& other) : storage(std::move(other.storage)) {} any(any&& other) : storage(std::move(other.storage)) {}
@ -140,7 +134,7 @@ private:
std::unique_ptr<type_interface> storage; std::unique_ptr<type_interface> storage;
}; };
//:TODO: declared out of line, see TODO above. //: TODO: declared out of line, see TODO above.
inline any::any() = default; inline any::any() = default;
/// Constructs an any object containing an object of type T, passing the /// Constructs an any object containing an object of type T, passing the
@ -160,8 +154,7 @@ inline T* any_cast(any* operand)
if (!operand || !operand->storage) if (!operand || !operand->storage)
return nullptr; return nullptr;
using U = using U = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
if (operand->storage->type() != &any::type_tag<U>::tag) if (operand->storage->type() != &any::type_tag<U>::tag)
return nullptr; return nullptr;
@ -177,8 +170,7 @@ inline const T* any_cast(const any* operand)
if (!operand || !operand->storage) if (!operand || !operand->storage)
return nullptr; return nullptr;
using U = using U = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
if (operand->storage->type() != &any::type_tag<U>::tag) if (operand->storage->type() != &any::type_tag<U>::tag)
return nullptr; return nullptr;

@ -24,16 +24,12 @@ namespace detail {
class memory_buffer class memory_buffer
{ {
const char* const buffer; const char* const buffer;
const size_t length; const size_t length;
public: public:
memory_buffer(const char* buffer, size_t length) : memory_buffer(const char* buffer, size_t length) : buffer(buffer), length(length) {}
buffer(buffer), length(length)
{}
explicit memory_buffer(const std::string& s) : explicit memory_buffer(const std::string& s) : buffer(s.data()), length(s.size()) {}
buffer(s.data()), length(s.size())
{}
/// Returns a pointer to the start of the memory block. /// Returns a pointer to the start of the memory block.
const char* data() const { return buffer; } const char* data() const { return buffer; }

@ -19,7 +19,7 @@ namespace srslog {
namespace detail { namespace detail {
//:TODO: these are temp helpers that will be replaced by std utils. //: TODO: these are temp helpers that will be replaced by std utils.
/// Abstraction of a pthread mutex. /// Abstraction of a pthread mutex.
class mutex class mutex
@ -41,7 +41,7 @@ public:
bool try_lock() { return (::pthread_mutex_trylock(&m) == 0); } bool try_lock() { return (::pthread_mutex_trylock(&m) == 0); }
/// Accessor to the raw mutex structure. /// Accessor to the raw mutex structure.
pthread_mutex_t* raw() { return &m; } pthread_mutex_t* raw() { return &m; }
const pthread_mutex_t* raw() const { return &m; } const pthread_mutex_t* raw() const { return &m; }
private: private:
@ -66,7 +66,7 @@ public:
template <typename T> template <typename T>
class shared_variable class shared_variable
{ {
T value; T value;
mutable mutex m; mutable mutex m;
public: public:
@ -118,10 +118,7 @@ public:
/// Blocks the calling thread on this condition variable up to the specified /// Blocks the calling thread on this condition variable up to the specified
/// timeout. Returns true on timeout expiration, otherwise false. /// timeout. Returns true on timeout expiration, otherwise false.
bool wait(timespec ts) bool wait(timespec ts) { return (::pthread_cond_timedwait(&cond_var, m.raw(), &ts) == ETIMEDOUT); }
{
return (::pthread_cond_timedwait(&cond_var, m.raw(), &ts) == ETIMEDOUT);
}
/// Builds an absolute time timespec structure adding the specified time out /// Builds an absolute time timespec structure adding the specified time out
/// in ms. /// in ms.
@ -141,7 +138,7 @@ public:
} }
private: private:
mutable mutex m; mutable mutex m;
pthread_cond_t cond_var; pthread_cond_t cond_var;
}; };
@ -152,11 +149,7 @@ class cond_var_scoped_lock
condition_variable& cond_var; condition_variable& cond_var;
public: public:
explicit cond_var_scoped_lock(condition_variable& cond_var) : explicit cond_var_scoped_lock(condition_variable& cond_var) : cond_var(cond_var) { cond_var.lock(); }
cond_var(cond_var)
{
cond_var.lock();
}
cond_var_scoped_lock(const cond_var_scoped_lock&) = delete; cond_var_scoped_lock(const cond_var_scoped_lock&) = delete;
cond_var_scoped_lock& operator=(const cond_var_scoped_lock&) = delete; cond_var_scoped_lock& operator=(const cond_var_scoped_lock&) = delete;

@ -28,8 +28,7 @@ template <std::size_t...>
struct index_sequence {}; struct index_sequence {};
template <std::size_t N, std::size_t... Next> template <std::size_t N, std::size_t... Next>
struct index_sequence_helper struct index_sequence_helper : public index_sequence_helper<N - 1U, N - 1U, Next...> {};
: public index_sequence_helper<N - 1U, N - 1U, Next...> {};
template <std::size_t... Next> template <std::size_t... Next>
struct index_sequence_helper<0U, Next...> { struct index_sequence_helper<0U, Next...> {
@ -47,20 +46,19 @@ template <typename T, typename Tuple>
struct tuple_index; struct tuple_index;
template <typename T, typename... Ts> template <typename T, typename... Ts>
struct tuple_index<T, std::tuple<T, Ts...>> { struct tuple_index<T, std::tuple<T, Ts...> > {
static constexpr std::size_t value = 0; static constexpr std::size_t value = 0;
}; };
template <typename T, typename U, typename... Ts> template <typename T, typename U, typename... Ts>
struct tuple_index<T, std::tuple<U, Ts...>> { struct tuple_index<T, std::tuple<U, Ts...> > {
static constexpr std::size_t value = static constexpr std::size_t value = 1 + tuple_index<T, std::tuple<Ts...> >::value;
1 + tuple_index<T, std::tuple<Ts...>>::value;
}; };
template <typename T, typename... Ts> template <typename T, typename... Ts>
constexpr std::size_t get_type_index_in_tuple() constexpr std::size_t get_type_index_in_tuple()
{ {
return tuple_index<T, std::tuple<Ts...>>::value; return tuple_index<T, std::tuple<Ts...> >::value;
} }
} // namespace detail } // namespace detail

@ -21,7 +21,7 @@ namespace srslog {
namespace detail { namespace detail {
//:TODO: this is a temp work queue. //: TODO: this is a temp work queue.
/// Thread safe generic data type work queue. /// Thread safe generic data type work queue.
template <typename T, size_t capacity = SRSLOG_QUEUE_CAPACITY> template <typename T, size_t capacity = SRSLOG_QUEUE_CAPACITY>

@ -33,7 +33,7 @@ public:
virtual ~sink() = default; virtual ~sink() = default;
/// Returns the formatter used by this sink. /// Returns the formatter used by this sink.
log_formatter& get_formatter() { return *formatter; } log_formatter& get_formatter() { return *formatter; }
const log_formatter& get_formatter() const { return *formatter; } const log_formatter& get_formatter() const { return *formatter; }
/// Writes the provided memory buffer into the sink. /// Writes the provided memory buffer into the sink.

@ -39,8 +39,7 @@ log_channel& fetch_log_channel(const std::string& id);
/// Returns an instance of a log_channel with the specified id that writes to /// Returns an instance of a log_channel with the specified id that writes to
/// the specified sink. /// the specified sink.
/// NOTE: Any '#' characters in the id will get removed. /// NOTE: Any '#' characters in the id will get removed.
log_channel& log_channel& fetch_log_channel(const std::string& id, sink& s, log_channel_config config);
fetch_log_channel(const std::string& id, sink& s, log_channel_config config);
/// Creates a new log channel instance with the specified id string and sink, /// Creates a new log channel instance with the specified id string and sink,
/// then registers it in the log channel repository so that it can be later /// then registers it in the log channel repository so that it can be later
@ -80,16 +79,13 @@ inline T* find_logger(const std::string& id)
/// specified id string. All logger channels will write into the default sink. /// specified id string. All logger channels will write into the default sink.
/// The context value of the logger can be printed on each log entry by setting /// The context value of the logger can be printed on each log entry by setting
/// to true the should_print_context argument. /// to true the should_print_context argument.
basic_logger& fetch_basic_logger(const std::string& id, basic_logger& fetch_basic_logger(const std::string& id, bool should_print_context = true);
bool should_print_context = true);
/// Returns an instance of a basic logger (see basic_logger type) with the /// Returns an instance of a basic logger (see basic_logger type) with the
/// specified id string. All logger channels will write into the specified sink. /// specified id string. All logger channels will write into the specified sink.
/// The context value of the logger can be printed on each log entry by setting /// The context value of the logger can be printed on each log entry by setting
/// to true the should_print_context argument. /// to true the should_print_context argument.
basic_logger& fetch_basic_logger(const std::string& id, basic_logger& fetch_basic_logger(const std::string& id, sink& s, bool should_print_context = true);
sink& s,
bool should_print_context = true);
/// Returns a logger instance with the specified id string, type and channel /// Returns a logger instance with the specified id string, type and channel
/// references. /// references.
@ -98,11 +94,11 @@ template <typename T, typename... Args>
inline T& fetch_logger(const std::string& id, Args&&... args) inline T& fetch_logger(const std::string& id, Args&&... args)
{ {
static_assert(detail::is_logger<T>::value, "T should be a logger type"); static_assert(detail::is_logger<T>::value, "T should be a logger type");
if (auto *logger = find_logger<T>(id)) { if (auto* logger = find_logger<T>(id)) {
return *logger; return *logger;
} }
auto logger = detail::make_any<T>(id, std::forward<Args>(args)...); auto logger = detail::make_any<T>(id, std::forward<Args>(args)...);
detail::any* p = detail::fetch_logger(id, std::move(logger)); detail::any* p = detail::fetch_logger(id, std::move(logger));
return *detail::any_cast<T>(p); return *detail::any_cast<T>(p);
} }
@ -115,9 +111,7 @@ inline T& fetch_logger(const std::string& id, Args&&... args)
/// the specified sink. Returns a pointer to the newly created logger, otherwise /// the specified sink. Returns a pointer to the newly created logger, otherwise
/// when a logger is already registered with the same id it returns nullptr. /// when a logger is already registered with the same id it returns nullptr.
/// NOTE: Deprecated, use fetch_basic_logger instead. /// NOTE: Deprecated, use fetch_basic_logger instead.
basic_logger* create_basic_logger(const std::string& id, basic_logger* create_basic_logger(const std::string& id, sink& s, bool should_print_context = true);
sink& s,
bool should_print_context = true);
/// Creates a new logger instance with the specified id string, type and channel /// Creates a new logger instance with the specified id string, type and channel
/// references, registering it into the logger repository so that it can be /// references, registering it into the logger repository so that it can be
@ -130,8 +124,8 @@ template <typename T, typename... Args>
inline T* create_logger(const std::string& id, Args&&... args) inline T* create_logger(const std::string& id, Args&&... args)
{ {
static_assert(detail::is_logger<T>::value, "T should be a logger type"); static_assert(detail::is_logger<T>::value, "T should be a logger type");
auto logger = detail::make_any<T>(id, std::forward<Args>(args)...); auto logger = detail::make_any<T>(id, std::forward<Args>(args)...);
detail::any* p = detail::fetch_logger(id, std::move(logger)); detail::any* p = detail::fetch_logger(id, std::move(logger));
return detail::any_cast<T>(p); return detail::any_cast<T>(p);
} }
@ -172,26 +166,23 @@ sink* find_sink(const std::string& id);
/// Returns an instance of a sink that writes to the stdout stream. You may use /// Returns an instance of a sink that writes to the stdout stream. You may use
/// different ids if you need to create multiple stdout sinks with different /// different ids if you need to create multiple stdout sinks with different
/// formatters. /// formatters.
sink& fetch_stdout_sink( sink& fetch_stdout_sink(const std::string& id = "stdout",
const std::string& id = "stdout", std::unique_ptr<log_formatter> f = get_default_log_formatter());
std::unique_ptr<log_formatter> f = get_default_log_formatter());
/// Returns an instance of a sink that writes to the stderr stream. You may use /// Returns an instance of a sink that writes to the stderr stream. You may use
/// different ids if you need to create multiple stderr sinks with different /// different ids if you need to create multiple stderr sinks with different
/// formatters. /// formatters.
sink& fetch_stderr_sink( sink& fetch_stderr_sink(const std::string& id = "stderr",
const std::string& id = "stderr", std::unique_ptr<log_formatter> f = get_default_log_formatter());
std::unique_ptr<log_formatter> f = get_default_log_formatter());
/// Returns an instance of a sink that writes into a file in the specified path. /// Returns an instance of a sink that writes into a file in the specified path.
/// Specifying a max_size value different to zero will make the sink create a /// Specifying a max_size value different to zero will make the sink create a
/// new file each time the current file exceeds this value. The units of /// new file each time the current file exceeds this value. The units of
/// max_size are bytes. /// max_size are bytes.
/// NOTE: Any '#' characters in the path will get removed. /// NOTE: Any '#' characters in the path will get removed.
sink& fetch_file_sink( sink& fetch_file_sink(const std::string& path,
const std::string& path, size_t max_size = 0,
size_t max_size = 0, std::unique_ptr<log_formatter> f = get_default_log_formatter());
std::unique_ptr<log_formatter> f = get_default_log_formatter());
/// Installs a custom user defined sink in the framework getting associated to /// Installs a custom user defined sink in the framework getting associated to
/// the specified id. Returns true on success, otherwise false. /// the specified id. Returns true on success, otherwise false.

@ -26,9 +26,9 @@ extern "C" {
/** /**
* Common types. * Common types.
*/ */
typedef int srslog_bool; typedef int srslog_bool;
typedef struct srslog_opaque_sink srslog_sink; typedef struct srslog_opaque_sink srslog_sink;
typedef struct srslog_opaque_log_channel srslog_log_channel; typedef struct srslog_opaque_log_channel srslog_log_channel;
typedef struct srslog_opaque_basic_logger srslog_logger; typedef struct srslog_opaque_basic_logger srslog_logger;
/** /**
@ -66,8 +66,7 @@ srslog_log_channel* srslog_find_log_channel(const char* id);
/** /**
* Controls whether the specified channel accepts incoming log entries. * Controls whether the specified channel accepts incoming log entries.
*/ */
void srslog_set_log_channel_enabled(srslog_log_channel* channel, void srslog_set_log_channel_enabled(srslog_log_channel* channel, srslog_bool enabled);
srslog_bool enabled);
/** /**
* Returns 1 if the specified channel is accepting incoming log entries, * Returns 1 if the specified channel is accepting incoming log entries,

@ -39,7 +39,7 @@ void srslog::event_trace_init()
static constexpr char default_file_name[] = "event_trace.log"; static constexpr char default_file_name[] = "event_trace.log";
// Create the default event trace channel. // Create the default event trace channel.
//:TODO: handle name reservation. //: TODO: handle name reservation.
sink* s = create_file_sink(default_file_name); sink* s = create_file_sink(default_file_name);
assert(s && "Default event file sink is reserved"); assert(s && "Default event file sink is reserved");
tracer = create_log_channel("event_trace_channel", *s); tracer = create_log_channel("event_trace_channel", *s);

@ -26,7 +26,7 @@ namespace srslog {
template <typename K, typename V> template <typename K, typename V>
class object_repository class object_repository
{ {
mutable detail::mutex m; mutable detail::mutex m;
std::unordered_map<K, V> repo; std::unordered_map<K, V> repo;
public: public:
@ -35,7 +35,7 @@ public:
V* insert(const K& key, V&& value) V* insert(const K& key, V&& value)
{ {
detail::scoped_lock lock(m); detail::scoped_lock lock(m);
const auto& insertion = repo.emplace(key, std::move(value)); const auto& insertion = repo.emplace(key, std::move(value));
if (!insertion.second) if (!insertion.second)
return nullptr; return nullptr;
return &insertion.first->second; return &insertion.first->second;
@ -48,7 +48,7 @@ public:
V& emplace(Args&&... args) V& emplace(Args&&... args)
{ {
detail::scoped_lock lock(m); detail::scoped_lock lock(m);
auto insertion = repo.emplace(std::forward<Args>(args)...); auto insertion = repo.emplace(std::forward<Args>(args)...);
return insertion.first->second; return insertion.first->second;
} }
@ -57,13 +57,13 @@ public:
V* find(const K& key) V* find(const K& key)
{ {
detail::scoped_lock lock(m); detail::scoped_lock lock(m);
auto it = repo.find(key); auto it = repo.find(key);
return (it != repo.end()) ? &it->second : nullptr; return (it != repo.end()) ? &it->second : nullptr;
} }
const V* find(const K& key) const const V* find(const K& key) const
{ {
detail::scoped_lock lock(m); detail::scoped_lock lock(m);
const auto it = repo.find(key); const auto it = repo.find(key);
return (it != repo.cend()) ? &it->second : nullptr; return (it != repo.cend()) ? &it->second : nullptr;
} }

@ -24,9 +24,7 @@ namespace srslog {
class file_sink : public sink class file_sink : public sink
{ {
public: public:
file_sink(std::string name, file_sink(std::string name, size_t max_size, std::unique_ptr<log_formatter> f) :
size_t max_size,
std::unique_ptr<log_formatter> f) :
sink(std::move(f)), sink(std::move(f)),
max_size((max_size == 0) ? 0 : std::max<size_t>(max_size, 4 * 1024)), max_size((max_size == 0) ? 0 : std::max<size_t>(max_size, 4 * 1024)),
base_filename(std::move(name)) base_filename(std::move(name))
@ -72,8 +70,7 @@ private:
/// Creates a new file and increments the file index counter. /// Creates a new file and increments the file index counter.
detail::error_string create_file() detail::error_string create_file()
{ {
return handler.create( return handler.create(file_utils::build_filename_with_index(base_filename, file_index++));
file_utils::build_filename_with_index(base_filename, file_index++));
} }
/// Handles the file rotation feature when it is activated. /// Handles the file rotation feature when it is activated.
@ -90,11 +87,11 @@ private:
} }
private: private:
const size_t max_size; const size_t max_size;
const std::string base_filename; const std::string base_filename;
file_utils::file handler; file_utils::file handler;
size_t current_size = 0; size_t current_size = 0;
uint32_t file_index = 0; uint32_t file_index = 0;
}; };
} // namespace srslog } // namespace srslog

@ -31,8 +31,7 @@ inline std::string format_error(const std::string& error, int error_code)
} }
/// Splits the specified path into a filename and its extension (if present). /// Splits the specified path into a filename and its extension (if present).
inline std::pair<std::string, std::string> inline std::pair<std::string, std::string> split_filename_extension(const std::string& filename)
split_filename_extension(const std::string& filename)
{ {
// Search for the last dot. // Search for the last dot.
auto dot_pos = filename.find_last_of('.'); auto dot_pos = filename.find_last_of('.');
@ -41,8 +40,7 @@ split_filename_extension(const std::string& filename)
// a) No dot found: my_file // a) No dot found: my_file
// b) Dot found at the beginning: .my_file // b) Dot found at the beginning: .my_file
// c) Dot found at the end: my_file. // c) Dot found at the end: my_file.
if (dot_pos == std::string::npos || dot_pos == 0 || if (dot_pos == std::string::npos || dot_pos == 0 || dot_pos == filename.size() - 1) {
dot_pos == filename.size() - 1) {
return {filename, ""}; return {filename, ""};
} }
@ -61,8 +59,7 @@ split_filename_extension(const std::string& filename)
} }
/// Builds a file name formatting the input base name and file index. /// Builds a file name formatting the input base name and file index.
inline std::string build_filename_with_index(const std::string& basename, inline std::string build_filename_with_index(const std::string& basename, size_t index)
size_t index)
{ {
if (index == 0) { if (index == 0) {
return basename; return basename;
@ -77,7 +74,7 @@ inline std::string build_filename_with_index(const std::string& basename,
class file class file
{ {
std::string path; std::string path;
std::FILE* handle = nullptr; std::FILE* handle = nullptr;
public: public:
~file() { close(); } ~file() { close(); }
@ -101,19 +98,15 @@ public:
return {}; return {};
} }
return format_error( return format_error(fmt::format("Unable to create log file \"{}\"", new_path), errno);
fmt::format("Unable to create log file \"{}\"", new_path), errno);
} }
/// Writes the provided memory buffer into an open file, otherwise does /// Writes the provided memory buffer into an open file, otherwise does
/// nothing. /// nothing.
detail::error_string write(detail::memory_buffer buffer) detail::error_string write(detail::memory_buffer buffer)
{ {
if (handle && if (handle && std::fwrite(buffer.data(), sizeof(char), buffer.size(), handle) != buffer.size()) {
std::fwrite(buffer.data(), sizeof(char), buffer.size(), handle) != auto err_str = format_error(fmt::format("Unable to write log file \"{}\"", path), errno);
buffer.size()) {
auto err_str = format_error(
fmt::format("Unable to write log file \"{}\"", path), errno);
close(); close();
return err_str; return err_str;
} }
@ -125,9 +118,7 @@ public:
detail::error_string flush() detail::error_string flush()
{ {
if (handle && ::fflush(handle) == EOF) { if (handle && ::fflush(handle) == EOF) {
auto err_str = format_error( auto err_str = format_error(fmt::format("Error encountered while flushing log file \"{}\"", path), errno);
fmt::format("Error encountered while flushing log file \"{}\"", path),
errno);
close(); close();
return err_str; return err_str;
} }

@ -25,8 +25,7 @@ class stream_sink : public sink
{ {
public: public:
stream_sink(sink_stream_type s, std::unique_ptr<log_formatter> f) : stream_sink(sink_stream_type s, std::unique_ptr<log_formatter> f) :
sink(std::move(f)), sink(std::move(f)), handle((s == sink_stream_type::stdout) ? stdout : stderr)
handle((s == sink_stream_type::stdout) ? stdout : stderr)
{} {}
stream_sink(const stream_sink& other) = delete; stream_sink(const stream_sink& other) = delete;

@ -155,7 +155,7 @@ sink& srslog::fetch_file_sink(const std::string& path, size_t max_size, std::uni
return *s; return *s;
} }
//:TODO: GCC5 or lower versions emits an error if we use the new() expression //: TODO: GCC5 or lower versions emits an error if we use the new() expression
// directly, use redundant piecewise_construct instead. // directly, use redundant piecewise_construct instead.
auto& s = srslog_instance::get().get_sink_repo().emplace( auto& s = srslog_instance::get().get_sink_repo().emplace(
std::piecewise_construct, std::piecewise_construct,
@ -362,7 +362,7 @@ sink* srslog::create_stderr_sink(const std::string& name)
sink* srslog::create_file_sink(const std::string& path, size_t max_size) sink* srslog::create_file_sink(const std::string& path, size_t max_size)
{ {
//:TODO: GCC5 or lower versions emits an error if we use the new() expression //: TODO: GCC5 or lower versions emits an error if we use the new() expression
// directly, use redundant piecewise_construct instead. // directly, use redundant piecewise_construct instead.
return srslog_instance::get() return srslog_instance::get()
.get_sink_repo() .get_sink_repo()

@ -56,8 +56,7 @@ srslog_log_channel* srslog_find_log_channel(const char* id)
return c_cast<srslog_log_channel>(find_log_channel(id)); return c_cast<srslog_log_channel>(find_log_channel(id));
} }
void srslog_set_log_channel_enabled(srslog_log_channel* channel, void srslog_set_log_channel_enabled(srslog_log_channel* channel, srslog_bool enabled)
srslog_bool enabled)
{ {
assert(channel && "Expected a valid channel"); assert(channel && "Expected a valid channel");
c_cast<log_channel>(channel)->set_enabled(enabled); c_cast<log_channel>(channel)->set_enabled(enabled);

@ -27,19 +27,17 @@ class srslog_instance
srslog_instance() srslog_instance()
{ {
// stdout and stderr sinks are always present. // stdout and stderr sinks are always present.
auto& stdout_sink = sink_repo.emplace( auto& stdout_sink =
std::piecewise_construct, sink_repo.emplace(std::piecewise_construct,
std::forward_as_tuple("stdout"), std::forward_as_tuple("stdout"),
std::forward_as_tuple(new stream_sink( std::forward_as_tuple(new stream_sink(sink_stream_type::stdout,
sink_stream_type::stdout, std::unique_ptr<log_formatter>(new text_formatter))));
std::unique_ptr<log_formatter>(new text_formatter))));
default_sink = stdout_sink.get(); default_sink = stdout_sink.get();
sink_repo.emplace(std::piecewise_construct, sink_repo.emplace(std::piecewise_construct,
std::forward_as_tuple("stderr"), std::forward_as_tuple("stderr"),
std::forward_as_tuple(new stream_sink( std::forward_as_tuple(new stream_sink(sink_stream_type::stderr,
sink_stream_type::stderr, std::unique_ptr<log_formatter>(new text_formatter))));
std::unique_ptr<log_formatter>(new text_formatter))));
// Initialize the default formatter pointer with a text formatter. // Initialize the default formatter pointer with a text formatter.
{ {
@ -61,28 +59,25 @@ public:
/// Logger repository accessor. /// Logger repository accessor.
using logger_repo_type = object_repository<std::string, detail::any>; using logger_repo_type = object_repository<std::string, detail::any>;
logger_repo_type& get_logger_repo() { return logger_repo; } logger_repo_type& get_logger_repo() { return logger_repo; }
const logger_repo_type& get_logger_repo() const { return logger_repo; } const logger_repo_type& get_logger_repo() const { return logger_repo; }
/// Log channel repository accessor. /// Log channel repository accessor.
using channel_repo_type = object_repository<std::string, log_channel>; using channel_repo_type = object_repository<std::string, log_channel>;
channel_repo_type& get_channel_repo() { return channel_repo; } channel_repo_type& get_channel_repo() { return channel_repo; }
const channel_repo_type& get_channel_repo() const { return channel_repo; } const channel_repo_type& get_channel_repo() const { return channel_repo; }
/// Sink repository accessor. /// Sink repository accessor.
using sink_repo_type = object_repository<std::string, std::unique_ptr<sink>>; using sink_repo_type = object_repository<std::string, std::unique_ptr<sink> >;
sink_repo_type& get_sink_repo() { return sink_repo; } sink_repo_type& get_sink_repo() { return sink_repo; }
const sink_repo_type& get_sink_repo() const { return sink_repo; } const sink_repo_type& get_sink_repo() const { return sink_repo; }
/// Backend accessor. /// Backend accessor.
detail::log_backend& get_backend() { return backend; } detail::log_backend& get_backend() { return backend; }
const detail::log_backend& get_backend() const { return backend; } const detail::log_backend& get_backend() const { return backend; }
/// Installs the specified error handler into the backend. /// Installs the specified error handler into the backend.
void set_error_handler(error_handler callback) void set_error_handler(error_handler callback) { backend.set_error_handler(std::move(callback)); }
{
backend.set_error_handler(std::move(callback));
}
/// Set the specified sink as the default one. /// Set the specified sink as the default one.
void set_default_sink(sink& s) { default_sink = &s; } void set_default_sink(sink& s) { default_sink = &s; }
@ -107,12 +102,12 @@ public:
private: private:
/// NOTE: The order of declaration of each member is important here for proper /// NOTE: The order of declaration of each member is important here for proper
/// destruction. /// destruction.
sink_repo_type sink_repo; sink_repo_type sink_repo;
log_backend_impl backend; log_backend_impl backend;
channel_repo_type channel_repo; channel_repo_type channel_repo;
logger_repo_type logger_repo; logger_repo_type logger_repo;
detail::shared_variable<sink*> default_sink{nullptr}; detail::shared_variable<sink*> default_sink{nullptr};
mutable detail::mutex formatter_mutex; mutable detail::mutex formatter_mutex;
std::unique_ptr<log_formatter> default_formatter; std::unique_ptr<log_formatter> default_formatter;
}; };

@ -49,7 +49,7 @@ struct movable_object {
static bool when_constructed_with_lvalue_then_any_has_value() static bool when_constructed_with_lvalue_then_any_has_value()
{ {
copyable_object value(5); copyable_object value(5);
detail::any a(value); detail::any a(value);
ASSERT_EQ(a.has_value(), true); ASSERT_EQ(a.has_value(), true);
@ -65,7 +65,7 @@ static bool when_constructed_with_lvalue_then_any_has_value()
static bool when_constructed_with_rvalue_then_any_has_value() static bool when_constructed_with_rvalue_then_any_has_value()
{ {
movable_object value(5); movable_object value(5);
detail::any a(std::move(value)); detail::any a(std::move(value));
ASSERT_EQ(a.has_value(), true); ASSERT_EQ(a.has_value(), true);
@ -80,8 +80,8 @@ static bool when_constructed_with_rvalue_then_any_has_value()
static bool when_constructed_with_make_any_then_any_has_int() static bool when_constructed_with_make_any_then_any_has_int()
{ {
int value = 5; int value = 5;
auto a = detail::make_any<int>(value); auto a = detail::make_any<int>(value);
ASSERT_EQ(a.has_value(), true); ASSERT_EQ(a.has_value(), true);
@ -96,7 +96,7 @@ static bool when_constructed_with_make_any_then_any_has_int()
static bool when_move_constructing_from_any_then_contents_are_transferred() static bool when_move_constructing_from_any_then_contents_are_transferred()
{ {
int value = 5; int value = 5;
detail::any a(value); detail::any a(value);
detail::any b(std::move(a)); detail::any b(std::move(a));
@ -114,7 +114,7 @@ static bool when_move_constructing_from_any_then_contents_are_transferred()
static bool when_move_assigning_from_any_then_contents_are_transferred() static bool when_move_assigning_from_any_then_contents_are_transferred()
{ {
int value = 5; int value = 5;
detail::any a(value); detail::any a(value);
detail::any b(3.0); detail::any b(3.0);
@ -143,9 +143,9 @@ static bool when_any_is_reset_then_value_is_lost()
static bool when_swapping_any_then_values_are_exchanged() static bool when_swapping_any_then_values_are_exchanged()
{ {
int i = 5; int i = 5;
detail::any a(i); detail::any a(i);
double d = 3.14; double d = 3.14;
detail::any b(d); detail::any b(d);
swap(a, b); swap(a, b);
@ -158,7 +158,7 @@ static bool when_swapping_any_then_values_are_exchanged()
static bool when_null_is_passed_to_any_cast_then_null_is_returned() static bool when_null_is_passed_to_any_cast_then_null_is_returned()
{ {
detail::any* p = nullptr; detail::any* p = nullptr;
const detail::any* cp = nullptr; const detail::any* cp = nullptr;
ASSERT_EQ(detail::any_cast<int>(p), nullptr); ASSERT_EQ(detail::any_cast<int>(p), nullptr);
ASSERT_EQ(detail::any_cast<int>(cp), nullptr); ASSERT_EQ(detail::any_cast<int>(cp), nullptr);
@ -168,7 +168,7 @@ static bool when_null_is_passed_to_any_cast_then_null_is_returned()
static bool when_empty_any_is_passed_to_any_cast_then_null_is_returned() static bool when_empty_any_is_passed_to_any_cast_then_null_is_returned()
{ {
detail::any a; detail::any a;
const detail::any b; const detail::any b;
ASSERT_EQ(detail::any_cast<int>(&a), nullptr); ASSERT_EQ(detail::any_cast<int>(&a), nullptr);
ASSERT_EQ(detail::any_cast<int>(&b), nullptr); ASSERT_EQ(detail::any_cast<int>(&b), nullptr);

@ -77,7 +77,7 @@ static bool when_context_is_built_then_metric_units_are_valid()
static bool when_metric_is_set_through_context_then_value_is_stored() static bool when_metric_is_set_through_context_then_value_is_stored()
{ {
ctx_t ctx = build_context(); ctx_t ctx = build_context();
float value = 10; float value = 10;
ctx.get<myset1>().write<snr_t>(value); ctx.get<myset1>().write<snr_t>(value);
@ -97,7 +97,7 @@ using ctx2_t = srslog::build_context_type<vector_metrics>;
static bool when_context_with_list_is_set_value_is_retrieved_correctly() static bool when_context_with_list_is_set_value_is_retrieved_correctly()
{ {
ctx2_t ctx("test"); ctx2_t ctx("test");
float val = 2; float val = 2;
ctx.get<vector_metrics>().emplace_back(); ctx.get<vector_metrics>().emplace_back();
ctx.at<vector_metrics>(0).write<m1_t>(val); ctx.at<vector_metrics>(0).write<m1_t>(val);

@ -22,10 +22,7 @@ static constexpr char log_filename[] = "file_sink_test.log";
static bool when_data_is_written_to_file_then_contents_are_valid() static bool when_data_is_written_to_file_then_contents_are_valid()
{ {
file_test_utils::scoped_file_deleter deleter(log_filename); file_test_utils::scoped_file_deleter deleter(log_filename);
file_sink file( file_sink file(log_filename, 0, std::unique_ptr<log_formatter>(new test_dummies::log_formatter_dummy));
log_filename,
0,
std::unique_ptr<log_formatter>(new test_dummies::log_formatter_dummy));
std::vector<std::string> entries; std::vector<std::string> entries;
for (unsigned i = 0; i != 10; ++i) { for (unsigned i = 0; i != 10; ++i) {
@ -37,8 +34,7 @@ static bool when_data_is_written_to_file_then_contents_are_valid()
file.flush(); file.flush();
ASSERT_EQ(file_test_utils::file_exists(log_filename), true); ASSERT_EQ(file_test_utils::file_exists(log_filename), true);
ASSERT_EQ(file_test_utils::compare_file_contents(log_filename, entries), ASSERT_EQ(file_test_utils::compare_file_contents(log_filename, entries), true);
true);
return true; return true;
} }
@ -49,10 +45,7 @@ class file_sink_subclass : public file_sink
{ {
public: public:
file_sink_subclass(std::string name, size_t max_size) : file_sink_subclass(std::string name, size_t max_size) :
file_sink( file_sink(std::move(name), max_size, std::unique_ptr<log_formatter>(new test_dummies::log_formatter_dummy))
std::move(name),
max_size,
std::unique_ptr<log_formatter>(new test_dummies::log_formatter_dummy))
{} {}
uint32_t get_num_of_files() const { return get_file_index(); } uint32_t get_num_of_files() const { return get_file_index(); }
@ -60,14 +53,10 @@ public:
static bool when_data_written_exceeds_size_threshold_then_new_file_is_created() static bool when_data_written_exceeds_size_threshold_then_new_file_is_created()
{ {
std::string filename0 = std::string filename0 = file_utils::build_filename_with_index(log_filename, 0);
file_utils::build_filename_with_index(log_filename, 0); std::string filename1 = file_utils::build_filename_with_index(log_filename, 1);
std::string filename1 = std::string filename2 = file_utils::build_filename_with_index(log_filename, 2);
file_utils::build_filename_with_index(log_filename, 1); file_test_utils::scoped_file_deleter deleter = {filename0, filename1, filename2};
std::string filename2 =
file_utils::build_filename_with_index(log_filename, 2);
file_test_utils::scoped_file_deleter deleter = {
filename0, filename1, filename2};
file_sink_subclass file(log_filename, 5001); file_sink_subclass file(log_filename, 5001);
@ -112,8 +101,7 @@ static bool when_data_written_exceeds_size_threshold_then_new_file_is_created()
int main() int main()
{ {
TEST_FUNCTION(when_data_is_written_to_file_then_contents_are_valid); TEST_FUNCTION(when_data_is_written_to_file_then_contents_are_valid);
TEST_FUNCTION( TEST_FUNCTION(when_data_written_exceeds_size_threshold_then_new_file_is_created);
when_data_written_exceeds_size_threshold_then_new_file_is_created);
return 0; return 0;
} }

@ -47,8 +47,7 @@ inline bool file_exists(const std::string& path)
/// Reads the contents of the file specified in path and returns true if they /// Reads the contents of the file specified in path and returns true if they
/// match with the data in entries, otherwise returns false. /// match with the data in entries, otherwise returns false.
inline bool compare_file_contents(const std::string& path, inline bool compare_file_contents(const std::string& path, const std::vector<std::string>& entries)
const std::vector<std::string>& entries)
{ {
std::ifstream file(path, std::ios::binary); std::ifstream file(path, std::ios::binary);
if (!file.is_open()) { if (!file.is_open()) {

@ -16,14 +16,12 @@
using namespace srslog; using namespace srslog;
static constexpr char log_filename[] = "file_utils_test.log"; static constexpr char log_filename[] = "file_utils_test.log";
static constexpr char log_filename2[] = "file_utils_test2.log"; static constexpr char log_filename2[] = "file_utils_test2.log";
static bool filename_extension_split_test() static bool filename_extension_split_test()
{ {
auto checker = [](const std::string& base, auto checker = [](const std::string& base, const std::string& file, const std::string& ext) {
const std::string& file,
const std::string& ext) {
auto result = file_utils::split_filename_extension(base); auto result = file_utils::split_filename_extension(base);
return (result.first == file && result.second == ext); return (result.first == file && result.second == ext);
}; };
@ -48,10 +46,8 @@ static bool filename_with_index_build_test()
ASSERT_EQ(file_utils::build_filename_with_index("filename", 0), "filename"); ASSERT_EQ(file_utils::build_filename_with_index("filename", 0), "filename");
ASSERT_EQ(file_utils::build_filename_with_index("filename", 1), "filename.1"); ASSERT_EQ(file_utils::build_filename_with_index("filename", 1), "filename.1");
ASSERT_EQ(file_utils::build_filename_with_index("filename.txt", 0), ASSERT_EQ(file_utils::build_filename_with_index("filename.txt", 0), "filename.txt");
"filename.txt"); ASSERT_EQ(file_utils::build_filename_with_index("filename.txt", 1), "filename.1.txt");
ASSERT_EQ(file_utils::build_filename_with_index("filename.txt", 1),
"filename.1.txt");
return true; return true;
} }
@ -69,7 +65,7 @@ static bool when_default_constructing_file_then_no_file_is_created()
static bool when_created_method_is_called_then_file_is_created() static bool when_created_method_is_called_then_file_is_created()
{ {
file_test_utils::scoped_file_deleter deleter(log_filename); file_test_utils::scoped_file_deleter deleter(log_filename);
file_utils::file f; file_utils::file f;
auto err_str = f.create(log_filename); auto err_str = f.create(log_filename);
ASSERT_EQ(err_str.get_error().empty(), true); ASSERT_EQ(err_str.get_error().empty(), true);
@ -82,11 +78,10 @@ static bool when_created_method_is_called_then_file_is_created()
return true; return true;
} }
static bool static bool when_created_method_is_called_twice_then_file_is_closed_and_created()
when_created_method_is_called_twice_then_file_is_closed_and_created()
{ {
file_test_utils::scoped_file_deleter deleter = {log_filename, log_filename2}; file_test_utils::scoped_file_deleter deleter = {log_filename, log_filename2};
file_utils::file f; file_utils::file f;
auto err_str = f.create(log_filename); auto err_str = f.create(log_filename);
ASSERT_EQ(err_str.get_error().empty(), true); ASSERT_EQ(err_str.get_error().empty(), true);
@ -125,7 +120,7 @@ static bool when_flush_method_is_called_with_no_file_then_nothing_happens()
static bool when_data_is_written_to_file_then_contents_are_valid() static bool when_data_is_written_to_file_then_contents_are_valid()
{ {
file_test_utils::scoped_file_deleter deleter(log_filename); file_test_utils::scoped_file_deleter deleter(log_filename);
file_utils::file f; file_utils::file f;
auto err_str = f.create(log_filename); auto err_str = f.create(log_filename);
ASSERT_EQ(err_str.get_error().empty(), true); ASSERT_EQ(err_str.get_error().empty(), true);
@ -137,8 +132,7 @@ static bool when_data_is_written_to_file_then_contents_are_valid()
err_str = f.flush(); err_str = f.flush();
ASSERT_EQ(err_str.get_error().empty(), true); ASSERT_EQ(err_str.get_error().empty(), true);
ASSERT_EQ(file_test_utils::compare_file_contents(log_filename, {"test\n"}), ASSERT_EQ(file_test_utils::compare_file_contents(log_filename, {"test\n"}), true);
true);
return true; return true;
} }
@ -146,7 +140,7 @@ static bool when_data_is_written_to_file_then_contents_are_valid()
static bool when_file_is_opened_and_closed_then_members_are_reset() static bool when_file_is_opened_and_closed_then_members_are_reset()
{ {
file_test_utils::scoped_file_deleter deleter(log_filename); file_test_utils::scoped_file_deleter deleter(log_filename);
file_utils::file f; file_utils::file f;
auto err_str = f.create(log_filename); auto err_str = f.create(log_filename);
ASSERT_EQ(err_str.get_error().empty(), true); ASSERT_EQ(err_str.get_error().empty(), true);
@ -166,8 +160,7 @@ int main()
TEST_FUNCTION(filename_with_index_build_test); TEST_FUNCTION(filename_with_index_build_test);
TEST_FUNCTION(when_default_constructing_file_then_no_file_is_created); TEST_FUNCTION(when_default_constructing_file_then_no_file_is_created);
TEST_FUNCTION(when_created_method_is_called_then_file_is_created); TEST_FUNCTION(when_created_method_is_called_then_file_is_created);
TEST_FUNCTION( TEST_FUNCTION(when_created_method_is_called_twice_then_file_is_closed_and_created);
when_created_method_is_called_twice_then_file_is_closed_and_created);
TEST_FUNCTION(when_write_method_is_called_with_no_file_then_nothing_happens); TEST_FUNCTION(when_write_method_is_called_with_no_file_then_nothing_happens);
TEST_FUNCTION(when_flush_method_is_called_with_no_file_then_nothing_happens); TEST_FUNCTION(when_flush_method_is_called_with_no_file_then_nothing_happens);
TEST_FUNCTION(when_data_is_written_to_file_then_contents_are_valid); TEST_FUNCTION(when_data_is_written_to_file_then_contents_are_valid);

@ -34,10 +34,10 @@ using test_logger = build_logger_type<test_logger_channels, test_logger_levels>;
static bool when_logger_is_created_then_id_matches_expected_value() static bool when_logger_is_created_then_id_matches_expected_value()
{ {
test_dummies::backend_dummy backend; test_dummies::backend_dummy backend;
test_dummies::sink_dummy s; test_dummies::sink_dummy s;
log_channel error("err", s, backend); log_channel error("err", s, backend);
log_channel warning("warning", s, backend); log_channel warning("warning", s, backend);
log_channel info("info", s, backend); log_channel info("info", s, backend);
test_logger logger(logger_id, error, warning, info); test_logger logger(logger_id, error, warning, info);
@ -49,10 +49,10 @@ static bool when_logger_is_created_then_id_matches_expected_value()
static bool when_level_is_set_to_error_then_info_and_warning_is_disabled() static bool when_level_is_set_to_error_then_info_and_warning_is_disabled()
{ {
test_dummies::backend_dummy backend; test_dummies::backend_dummy backend;
test_dummies::sink_dummy s; test_dummies::sink_dummy s;
log_channel error("err", s, backend); log_channel error("err", s, backend);
log_channel warning("warning", s, backend); log_channel warning("warning", s, backend);
log_channel info("info", s, backend); log_channel info("info", s, backend);
test_logger logger(logger_id, error, warning, info); test_logger logger(logger_id, error, warning, info);
logger.set_level(test_logger_levels::error); logger.set_level(test_logger_levels::error);
@ -67,10 +67,10 @@ static bool when_level_is_set_to_error_then_info_and_warning_is_disabled()
static bool when_level_is_set_to_warning_then_info_is_disabled() static bool when_level_is_set_to_warning_then_info_is_disabled()
{ {
test_dummies::backend_dummy backend; test_dummies::backend_dummy backend;
test_dummies::sink_dummy s; test_dummies::sink_dummy s;
log_channel error("err", s, backend); log_channel error("err", s, backend);
log_channel warning("warning", s, backend); log_channel warning("warning", s, backend);
log_channel info("info", s, backend); log_channel info("info", s, backend);
test_logger logger(logger_id, error, warning, info); test_logger logger(logger_id, error, warning, info);
logger.set_level(test_logger_levels::warning); logger.set_level(test_logger_levels::warning);
@ -85,10 +85,10 @@ static bool when_level_is_set_to_warning_then_info_is_disabled()
static bool when_level_is_set_to_info_then_all_are_enabled() static bool when_level_is_set_to_info_then_all_are_enabled()
{ {
test_dummies::backend_dummy backend; test_dummies::backend_dummy backend;
test_dummies::sink_dummy s; test_dummies::sink_dummy s;
log_channel error("err", s, backend); log_channel error("err", s, backend);
log_channel warning("warning", s, backend); log_channel warning("warning", s, backend);
log_channel info("info", s, backend); log_channel info("info", s, backend);
test_logger logger(logger_id, error, warning, info); test_logger logger(logger_id, error, warning, info);
logger.set_level(test_logger_levels::info); logger.set_level(test_logger_levels::info);
@ -103,10 +103,10 @@ static bool when_level_is_set_to_info_then_all_are_enabled()
static bool when_level_is_set_to_none_then_all_are_disabled() static bool when_level_is_set_to_none_then_all_are_disabled()
{ {
test_dummies::backend_dummy backend; test_dummies::backend_dummy backend;
test_dummies::sink_dummy s; test_dummies::sink_dummy s;
log_channel error("err", s, backend); log_channel error("err", s, backend);
log_channel warning("warning", s, backend); log_channel warning("warning", s, backend);
log_channel info("info", s, backend); log_channel info("info", s, backend);
test_logger logger(logger_id, error, warning, info); test_logger logger(logger_id, error, warning, info);
logger.set_level(test_logger_levels::none); logger.set_level(test_logger_levels::none);

@ -19,11 +19,9 @@ using namespace srslog;
static constexpr char test_id1[] = "Test1"; static constexpr char test_id1[] = "Test1";
static constexpr char test_id2[] = "Test2"; static constexpr char test_id2[] = "Test2";
//:TODO: older compilers may not have defined this C++11 trait. //: TODO: older compilers may not have defined this C++11 trait.
#if (defined(__clang__) && (__clang_major__ >= 5)) || \ #if (defined(__clang__) && (__clang_major__ >= 5)) || (defined(__GNUG__) && (__GNUC__ >= 5))
(defined(__GNUG__) && (__GNUC__ >= 5)) static_assert(std::is_trivially_copyable<detail::memory_buffer>::value, "Expected to be trivially copyable");
static_assert(std::is_trivially_copyable<detail::memory_buffer>::value,
"Expected to be trivially copyable");
#endif #endif
static bool when_srslog_is_created_then_stdout_and_stderr_sinks_exist() static bool when_srslog_is_created_then_stdout_and_stderr_sinks_exist()
@ -82,8 +80,7 @@ static bool when_non_existent_id_is_passed_then_nothing_is_found()
return true; return true;
} }
static bool static bool when_id_with_sharps_is_passed_then_channel_is_fetched_with_clean_id()
when_id_with_sharps_is_passed_then_channel_is_fetched_with_clean_id()
{ {
log_channel& channel1 = fetch_log_channel("a1#a"); log_channel& channel1 = fetch_log_channel("a1#a");
log_channel& channel2 = fetch_log_channel("a2#a", fetch_stdout_sink(), {}); log_channel& channel2 = fetch_log_channel("a2#a", fetch_stdout_sink(), {});
@ -105,19 +102,18 @@ static bool when_channel_already_exists_then_fetch_returns_channel()
return true; return true;
} }
static constexpr char logger_id[] = "TestLogger"; static constexpr char logger_id[] = "TestLogger";
static constexpr char basic_logger_id1[] = "BasicTestLogger"; static constexpr char basic_logger_id1[] = "BasicTestLogger";
static constexpr char basic_logger_id2[] = "BasicTestLogger2"; static constexpr char basic_logger_id2[] = "BasicTestLogger2";
static bool when_fetching_logger_then_logger_instance_is_returned() static bool when_fetching_logger_then_logger_instance_is_returned()
{ {
log_channel& error = fetch_log_channel("logger.error"); log_channel& error = fetch_log_channel("logger.error");
log_channel& warning = fetch_log_channel("logger.warning"); log_channel& warning = fetch_log_channel("logger.warning");
log_channel& info = fetch_log_channel("logger.info"); log_channel& info = fetch_log_channel("logger.info");
log_channel& debug = fetch_log_channel("logger.debug"); log_channel& debug = fetch_log_channel("logger.debug");
auto& logger = auto& logger = fetch_logger<basic_logger>(logger_id, error, warning, info, debug);
fetch_logger<basic_logger>(logger_id, error, warning, info, debug);
ASSERT_EQ(logger.id(), logger_id); ASSERT_EQ(logger.id(), logger_id);
@ -127,8 +123,7 @@ static bool when_fetching_logger_then_logger_instance_is_returned()
static bool when_fetching_basic_logger_then_basic_logger_instance_is_returned() static bool when_fetching_basic_logger_then_basic_logger_instance_is_returned()
{ {
basic_logger& logger1 = fetch_basic_logger(basic_logger_id1); basic_logger& logger1 = fetch_basic_logger(basic_logger_id1);
basic_logger& logger2 = basic_logger& logger2 = fetch_basic_logger(basic_logger_id2, fetch_stdout_sink());
fetch_basic_logger(basic_logger_id2, fetch_stdout_sink());
ASSERT_EQ(logger1.id(), basic_logger_id1); ASSERT_EQ(logger1.id(), basic_logger_id1);
ASSERT_EQ(logger2.id(), basic_logger_id2); ASSERT_EQ(logger2.id(), basic_logger_id2);
@ -205,8 +200,7 @@ static bool when_invalid_id_is_passed_then_no_sink_is_found()
return true; return true;
} }
static bool static bool when_setting_stderr_as_default_then_get_default_returns_stderr_sink()
when_setting_stderr_as_default_then_get_default_returns_stderr_sink()
{ {
set_default_sink(fetch_stderr_sink()); set_default_sink(fetch_stderr_sink());
sink& default_sink = get_default_sink(); sink& default_sink = get_default_sink();
@ -216,8 +210,7 @@ when_setting_stderr_as_default_then_get_default_returns_stderr_sink()
return true; return true;
} }
static bool static bool when_creating_non_default_stdout_and_stderr_sinks_then_they_are_created()
when_creating_non_default_stdout_and_stderr_sinks_then_they_are_created()
{ {
auto& out1 = fetch_stdout_sink("stdout1"); auto& out1 = fetch_stdout_sink("stdout1");
auto& err1 = fetch_stderr_sink("stderr1"); auto& err1 = fetch_stderr_sink("stderr1");
@ -233,7 +226,7 @@ static constexpr char custom_sink_name[] = "custom_sink";
static bool when_setting_custom_sink_first_time_then_insertion_succeeds() static bool when_setting_custom_sink_first_time_then_insertion_succeeds()
{ {
std::unique_ptr<sink> custom(new test_dummies::sink_dummy); std::unique_ptr<sink> custom(new test_dummies::sink_dummy);
sink* s = custom.get(); sink* s = custom.get();
bool ret = install_custom_sink(custom_sink_name, std::move(custom)); bool ret = install_custom_sink(custom_sink_name, std::move(custom));
ASSERT_EQ(ret, true); ASSERT_EQ(ret, true);
@ -248,7 +241,7 @@ static bool when_setting_custom_sink_first_time_then_insertion_succeeds()
static bool when_setting_custom_sink_twice_then_insertion_fails() static bool when_setting_custom_sink_twice_then_insertion_fails()
{ {
std::unique_ptr<sink> custom(new test_dummies::sink_dummy); std::unique_ptr<sink> custom(new test_dummies::sink_dummy);
sink* s = custom.get(); sink* s = custom.get();
bool ret = install_custom_sink(custom_sink_name, std::move(custom)); bool ret = install_custom_sink(custom_sink_name, std::move(custom));
ASSERT_EQ(ret, false); ASSERT_EQ(ret, false);
@ -260,11 +253,9 @@ static bool when_setting_custom_sink_twice_then_insertion_fails()
return true; return true;
} }
static bool static bool when_default_formatter_is_installed_then_getter_returns_same_formatter()
when_default_formatter_is_installed_then_getter_returns_same_formatter()
{ {
auto f = auto f = std::unique_ptr<log_formatter>(new test_dummies::log_formatter_dummy);
std::unique_ptr<log_formatter>(new test_dummies::log_formatter_dummy);
set_default_log_formatter(std::move(f)); set_default_log_formatter(std::move(f));
// Dummy formatter does not implement the clone method, thus the unique // Dummy formatter does not implement the clone method, thus the unique
@ -278,35 +269,27 @@ when_default_formatter_is_installed_then_getter_returns_same_formatter()
int main() int main()
{ {
TEST_FUNCTION(when_srslog_is_created_then_stdout_and_stderr_sinks_exist); TEST_FUNCTION(when_srslog_is_created_then_stdout_and_stderr_sinks_exist);
TEST_FUNCTION( TEST_FUNCTION(when_no_installed_default_formatter_then_a_formatter_is_returned);
when_no_installed_default_formatter_then_a_formatter_is_returned);
TEST_FUNCTION(when_no_installed_default_sink_then_stdout_sink_is_used); TEST_FUNCTION(when_no_installed_default_sink_then_stdout_sink_is_used);
TEST_FUNCTION(when_fetching_channel_then_channel_instance_is_returned); TEST_FUNCTION(when_fetching_channel_then_channel_instance_is_returned);
TEST_FUNCTION(when_valid_id_is_passed_then_channel_is_found); TEST_FUNCTION(when_valid_id_is_passed_then_channel_is_found);
TEST_FUNCTION(when_non_existent_id_is_passed_then_nothing_is_found); TEST_FUNCTION(when_non_existent_id_is_passed_then_nothing_is_found);
TEST_FUNCTION( TEST_FUNCTION(when_id_with_sharps_is_passed_then_channel_is_fetched_with_clean_id);
when_id_with_sharps_is_passed_then_channel_is_fetched_with_clean_id);
TEST_FUNCTION(when_channel_already_exists_then_fetch_returns_channel); TEST_FUNCTION(when_channel_already_exists_then_fetch_returns_channel);
TEST_FUNCTION(when_fetching_logger_then_logger_instance_is_returned); TEST_FUNCTION(when_fetching_logger_then_logger_instance_is_returned);
TEST_FUNCTION( TEST_FUNCTION(when_fetching_basic_logger_then_basic_logger_instance_is_returned);
when_fetching_basic_logger_then_basic_logger_instance_is_returned);
TEST_FUNCTION(when_valid_id_and_type_is_passed_then_logger_is_found); TEST_FUNCTION(when_valid_id_and_type_is_passed_then_logger_is_found);
TEST_FUNCTION(when_basic_logger_already_exists_then_fetch_returns_logger); TEST_FUNCTION(when_basic_logger_already_exists_then_fetch_returns_logger);
TEST_FUNCTION( TEST_FUNCTION(when_invalid_id_with_valid_type_is_passed_then_no_logger_is_found);
when_invalid_id_with_valid_type_is_passed_then_no_logger_is_found);
TEST_FUNCTION(when_invalid_id_and_type_is_passed_then_no_logger_is_found); TEST_FUNCTION(when_invalid_id_and_type_is_passed_then_no_logger_is_found);
TEST_FUNCTION( TEST_FUNCTION(when_valid_id_with_invalid_type_is_passed_then_no_logger_is_found);
when_valid_id_with_invalid_type_is_passed_then_no_logger_is_found);
TEST_FUNCTION(when_file_sink_is_fetched_then_sink_instance_is_returned); TEST_FUNCTION(when_file_sink_is_fetched_then_sink_instance_is_returned);
TEST_FUNCTION(when_invalid_id_is_passed_then_no_sink_is_found); TEST_FUNCTION(when_invalid_id_is_passed_then_no_sink_is_found);
TEST_FUNCTION( TEST_FUNCTION(when_setting_stderr_as_default_then_get_default_returns_stderr_sink);
when_setting_stderr_as_default_then_get_default_returns_stderr_sink); TEST_FUNCTION(when_creating_non_default_stdout_and_stderr_sinks_then_they_are_created);
TEST_FUNCTION(
when_creating_non_default_stdout_and_stderr_sinks_then_they_are_created);
TEST_FUNCTION(when_setting_custom_sink_first_time_then_insertion_succeeds); TEST_FUNCTION(when_setting_custom_sink_first_time_then_insertion_succeeds);
TEST_FUNCTION(when_setting_custom_sink_twice_then_insertion_fails); TEST_FUNCTION(when_setting_custom_sink_twice_then_insertion_fails);
TEST_FUNCTION( TEST_FUNCTION(when_default_formatter_is_installed_then_getter_returns_same_formatter);
when_default_formatter_is_installed_then_getter_returns_same_formatter);
return 0; return 0;
} }

@ -16,48 +16,48 @@
#include <cstdio> #include <cstdio>
/// Invokes the given test function and printing test results to stdout. /// Invokes the given test function and printing test results to stdout.
#define TEST_FUNCTION(func, ...) \ #define TEST_FUNCTION(func, ...) \
do { \ do { \
if (!func(__VA_ARGS__)) { \ if (!func(__VA_ARGS__)) { \
std::printf("Test \"%s\" FAILED! - %s:%u\n", #func, __FILE__, __LINE__); \ std::printf("Test \"%s\" FAILED! - %s:%u\n", #func, __FILE__, __LINE__); \
return -1; \ return -1; \
} else { \ } else { \
std::printf("Test \"%s\" PASSED!\n", #func); \ std::printf("Test \"%s\" PASSED!\n", #func); \
} \ } \
} while (0) } while (0)
/// Asserts for equality between a and b. The == operator must exist for the /// Asserts for equality between a and b. The == operator must exist for the
/// input types. /// input types.
#define ASSERT_EQ(a, b) \ #define ASSERT_EQ(a, b) \
do { \ do { \
if ((a) == (b)) { \ if ((a) == (b)) { \
; \ ; \
} else { \ } else { \
std::printf("EQ assertion failed in Test \"%s\" - %s:%u\n Condition " \ std::printf("EQ assertion failed in Test \"%s\" - %s:%u\n Condition " \
"\"%s\" not met\n", \ "\"%s\" not met\n", \
__FUNCTION__, \ __FUNCTION__, \
__FILE__, \ __FILE__, \
__LINE__, \ __LINE__, \
#a " == " #b); \ #a " == " #b); \
return false; \ return false; \
} \ } \
} while (0) } while (0)
/// Asserts for non equality between a and b. The != operator must exist for the /// Asserts for non equality between a and b. The != operator must exist for the
/// input types. /// input types.
#define ASSERT_NE(a, b) \ #define ASSERT_NE(a, b) \
do { \ do { \
if ((a) != (b)) { \ if ((a) != (b)) { \
; \ ; \
} else { \ } else { \
std::printf("NE assertion failed in Test \"%s\" - %s:%u\n Condition " \ std::printf("NE assertion failed in Test \"%s\" - %s:%u\n Condition " \
"\"%s\" not met\n", \ "\"%s\" not met\n", \
__FUNCTION__, \ __FUNCTION__, \
__FILE__, \ __FILE__, \
__LINE__, \ __LINE__, \
#a " != " #b); \ #a " != " #b); \
return false; \ return false; \
} \ } \
} while (0) } while (0)
#endif // TESTING_HELPERS_H #endif // TESTING_HELPERS_H

Loading…
Cancel
Save