srsLTE/lib/test/srslog/log_backend_test.cpp

232 lines
5.7 KiB
C++

/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "src/srslog/log_backend_impl.h"
#include "srslte/srslog/sink.h"
#include "testing_helpers.h"
using namespace srslog;
static bool when_backend_is_started_then_is_started_returns_true()
{
log_backend_impl backend;
ASSERT_EQ(backend.is_started(), false);
backend.start();
ASSERT_EQ(backend.is_started(), true);
return true;
}
static bool when_backend_is_started_and_stopped_then_is_started_returns_false()
{
log_backend_impl backend;
backend.start();
backend.stop();
ASSERT_EQ(backend.is_started(), false);
return true;
}
namespace {
/// A Spy implementation of a log sink. Tests can query the last received memory
/// buffer by the sink and the number of invocations to the write method.
class sink_spy : public sink
{
public:
detail::error_string write(detail::memory_buffer buffer) override
{
++count;
str.insert(0, buffer.data(), buffer.size());
return {};
}
detail::error_string flush() override { return {}; }
unsigned write_invocation_count() const { return count; }
const std::string& received_buffer() const { return str; }
private:
unsigned count = 0;
std::string str;
};
} // namespace
static bool when_backend_is_not_started_then_pushed_log_entries_are_ignored()
{
sink_spy spy;
log_backend_impl backend;
detail::log_entry entry = {&spy, "Test"};
backend.push(std::move(entry));
ASSERT_EQ(spy.write_invocation_count(), 0);
return true;
}
/// Helper to build a log entry.
static detail::log_entry build_log_entry(sink* s)
{
// Populate store with some arguments.
fmt::dynamic_format_arg_store<fmt::printf_context> store;
store.push_back(3);
store.push_back("Hello");
store.push_back(3.14);
// Send the log entry to the backend.
detail::log_entry entry = {s, "Arg1:%u Arg2:%s Arg3:%.2f", std::move(store)};
return entry;
}
static bool when_backend_is_started_then_pushed_log_entries_are_sent_to_sink()
{
sink_spy spy;
log_backend_impl backend;
backend.start();
backend.push(build_log_entry(&spy));
// Stop the backend to ensure the entry has been processed.
backend.stop();
ASSERT_EQ(spy.write_invocation_count(), 1);
ASSERT_EQ(spy.received_buffer(), "Arg1:3 Arg2:Hello Arg3:3.14");
return true;
}
namespace {
/// A Configurable Stub implementation of an object to be invoked by the
/// backend. Upon invocation, instances of this class return an error that can
/// be configured dynamically.
class sink_error_stub : public sink
{
public:
explicit sink_error_stub(std::string err) : err(std::move(err)) {}
detail::error_string write(detail::memory_buffer buffer) override
{
return err;
}
detail::error_string flush() override { return err; }
private:
std::string err;
};
} // namespace
static bool when_sink_write_fails_then_error_handler_is_invoked()
{
std::string error_str("error");
sink_error_stub s(error_str);
bool valid_err = false;
unsigned count = 0;
// valid_err checks that the input error matches the expected string.
// The count variable counts the number of calls.
auto handler = [&count, &valid_err, error_str](const std::string& error) {
valid_err = (error == error_str);
++count;
};
log_backend_impl backend;
backend.set_error_handler(handler);
backend.start();
backend.push(build_log_entry(&s));
// Stop the backend to ensure the entry has been processed.
backend.stop();
ASSERT_EQ(valid_err, true);
ASSERT_EQ(count, 1);
return true;
}
static bool when_handler_is_set_after_start_then_handler_is_not_used()
{
sink_error_stub s("test");
unsigned count = 0;
// The count variable counts the number of calls.
auto handler = [&count](const std::string& error) { ++count; };
log_backend_impl backend;
// We want to remove output to stderr by the default handler.
backend.set_error_handler([](const std::string&) {});
backend.start();
backend.set_error_handler(handler);
backend.push(build_log_entry(&s));
// Stop the backend to ensure the entry has been processed.
backend.stop();
ASSERT_EQ(count, 0);
return true;
}
static bool when_empty_handler_is_used_then_backend_does_not_crash()
{
sink_error_stub s("test");
log_backend_impl backend;
// We want to remove output to stderr by the default handler.
backend.set_error_handler({});
backend.start();
backend.push(build_log_entry(&s));
// Stop the backend to ensure the entry has been processed.
backend.stop();
return true;
}
int main()
{
TEST_FUNCTION(when_backend_is_started_then_is_started_returns_true);
TEST_FUNCTION(
when_backend_is_started_and_stopped_then_is_started_returns_false);
TEST_FUNCTION(
when_backend_is_not_started_then_pushed_log_entries_are_ignored);
TEST_FUNCTION(
when_backend_is_started_then_pushed_log_entries_are_sent_to_sink);
TEST_FUNCTION(when_sink_write_fails_then_error_handler_is_invoked);
TEST_FUNCTION(when_handler_is_set_after_start_then_handler_is_not_used);
TEST_FUNCTION(when_empty_handler_is_used_then_backend_does_not_crash);
return 0;
}