diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2022-02-22 17:03:21 +0100 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2022-02-22 17:03:21 +0100 |
commit | 619def44c1cca9f3cdf63544d5f24f2c7a7d9b77 (patch) | |
tree | 01868de723cb82c86842f33743fa7b14e24c1fa3 /test/buildtool/logging/logger.test.cpp | |
download | justbuild-619def44c1cca9f3cdf63544d5f24f2c7a7d9b77.tar.gz |
Initial self-hosting commit
This is the initial version of our tool that is able to
build itself. In can be bootstrapped by
./bin/bootstrap.py
Co-authored-by: Oliver Reiche <oliver.reiche@huawei.com>
Co-authored-by: Victor Moreno <victor.moreno1@huawei.com>
Diffstat (limited to 'test/buildtool/logging/logger.test.cpp')
-rw-r--r-- | test/buildtool/logging/logger.test.cpp | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/test/buildtool/logging/logger.test.cpp b/test/buildtool/logging/logger.test.cpp new file mode 100644 index 00000000..329b69b0 --- /dev/null +++ b/test/buildtool/logging/logger.test.cpp @@ -0,0 +1,322 @@ +#include <atomic> +#include <string> +#include <unordered_map> + +#include "catch2/catch.hpp" +#include "src/buildtool/logging/log_config.hpp" +#include "src/buildtool/logging/log_sink.hpp" +#include "src/buildtool/logging/logger.hpp" + +// Stores prints from test sink instances +class TestPrints { + public: + static void Print(int sink_id, std::string const& print) noexcept { + prints_[sink_id].push_back(print); + } + [[nodiscard]] static auto Read(int sink_id) noexcept + -> std::vector<std::string> { + return prints_[sink_id]; + } + + static void Clear() noexcept { + prints_.clear(); + counter_ = 0; + } + + static auto GetId() noexcept -> int { return counter_++; } + + private: + static inline std::atomic<int> counter_{}; + static inline std::unordered_map<int, std::vector<std::string>> prints_{}; +}; + +// Test sink, prints to TestPrints depending on its own instance id. +class LogSinkTest : public ILogSink { + public: + static auto CreateFactory() -> LogSinkFactory { + return [] { return std::make_shared<LogSinkTest>(); }; + } + + LogSinkTest() noexcept { id_ = TestPrints::GetId(); } + + void Emit(Logger const* logger, + LogLevel level, + std::string const& msg) const noexcept final { + auto prefix = LogLevelToString(level); + + if (logger != nullptr) { + prefix += " (" + logger->Name() + ")"; + } + + TestPrints::Print(id_, prefix + ": " + msg); + } + + private: + int id_{}; +}; + +class OneGlobalSinkFixture { + public: + OneGlobalSinkFixture() { + TestPrints::Clear(); + LogConfig::SetLogLimit(LogLevel::Info); + LogConfig::SetSinks({LogSinkTest::CreateFactory()}); + } +}; + +class TwoGlobalSinksFixture : public OneGlobalSinkFixture { + public: + TwoGlobalSinksFixture() { + LogConfig::AddSink(LogSinkTest::CreateFactory()); + } +}; + +TEST_CASE_METHOD(OneGlobalSinkFixture, + "Global static logger with one sink", + "[logger]") { + // logs should be forwarded to sink instance: 0 + int instance = 0; + + // create log outside of log limit + Logger::Log(LogLevel::Trace, "first"); + CHECK(TestPrints::Read(instance).empty()); + + SECTION("create log within log limit") { + Logger::Log(LogLevel::Info, "second"); + auto prints = TestPrints::Read(instance); + REQUIRE(prints.size() == 1); + CHECK(prints[0] == "INFO: second"); + + SECTION("increase log limit create log within log limit") { + LogConfig::SetLogLimit(LogLevel::Trace); + Logger::Log(LogLevel::Trace, "third"); + auto prints = TestPrints::Read(instance); + REQUIRE(prints.size() == 2); + CHECK(prints[1] == "TRACE: third"); + + SECTION("log via lambda function") { + Logger::Log(LogLevel::Trace, + [] { return std::string{"forth"}; }); + auto prints = TestPrints::Read(instance); + REQUIRE(prints.size() == 3); + CHECK(prints[2] == "TRACE: forth"); + } + } + } +} + +TEST_CASE_METHOD(OneGlobalSinkFixture, + "Local named logger using one global sink", + "[logger]") { + // create logger with sink instances from global LogConfig + Logger logger("TestLogger"); + + // logs should be forwarded to same sink instance as before: 0 + int instance = 0; + + // create log outside of log limit + logger.Emit(LogLevel::Trace, "first"); + CHECK(TestPrints::Read(instance).empty()); + + SECTION("create log within log limit") { + logger.Emit(LogLevel::Info, "second"); + auto prints = TestPrints::Read(instance); + REQUIRE(prints.size() == 1); + CHECK(prints[0] == "INFO (TestLogger): second"); + + SECTION("increase log limit create log within log limit") { + logger.SetLogLimit(LogLevel::Trace); + logger.Emit(LogLevel::Trace, "third"); + auto prints = TestPrints::Read(instance); + REQUIRE(prints.size() == 2); + CHECK(prints[1] == "TRACE (TestLogger): third"); + + SECTION("log via lambda function") { + logger.Emit(LogLevel::Trace, + [] { return std::string{"forth"}; }); + auto prints = TestPrints::Read(instance); + REQUIRE(prints.size() == 3); + CHECK(prints[2] == "TRACE (TestLogger): forth"); + } + } + } +} + +TEST_CASE_METHOD(OneGlobalSinkFixture, + "Local named logger with its own sink instance" + "[logger]") { + // create logger with separate sink instance + Logger logger("OwnSinkLogger", {LogSinkTest::CreateFactory()}); + + // logs should be forwarded to new sink instance: 1 + int instance = 1; + + // create log outside of log limit + logger.Emit(LogLevel::Trace, "first"); + CHECK(TestPrints::Read(instance).empty()); + + SECTION("create log within log limit") { + logger.Emit(LogLevel::Info, "second"); + auto prints = TestPrints::Read(instance); + REQUIRE(prints.size() == 1); + CHECK(prints[0] == "INFO (OwnSinkLogger): second"); + + SECTION("increase log limit create log within log limit") { + logger.SetLogLimit(LogLevel::Trace); + logger.Emit(LogLevel::Trace, "third"); + auto prints = TestPrints::Read(instance); + REQUIRE(prints.size() == 2); + CHECK(prints[1] == "TRACE (OwnSinkLogger): third"); + + SECTION("log via lambda function") { + logger.Emit(LogLevel::Trace, + [] { return std::string{"forth"}; }); + auto prints = TestPrints::Read(instance); + REQUIRE(prints.size() == 3); + CHECK(prints[2] == "TRACE (OwnSinkLogger): forth"); + } + } + } +} + +TEST_CASE_METHOD(TwoGlobalSinksFixture, + "Global static logger with two sinks", + "[logger]") { + // logs should be forwarded to sink instances: 0 and 1 + int instance1 = 0; + int instance2 = 1; + + // create log outside of log limit + Logger::Log(LogLevel::Trace, "first"); + CHECK(TestPrints::Read(instance1).empty()); + CHECK(TestPrints::Read(instance2).empty()); + + SECTION("create log within log limit") { + Logger::Log(LogLevel::Info, "second"); + auto prints1 = TestPrints::Read(instance1); + auto prints2 = TestPrints::Read(instance2); + REQUIRE(prints1.size() == 1); + REQUIRE(prints2.size() == 1); + CHECK(prints1[0] == "INFO: second"); + CHECK(prints2[0] == "INFO: second"); + + SECTION("increase log limit create log within log limit") { + LogConfig::SetLogLimit(LogLevel::Trace); + Logger::Log(LogLevel::Trace, "third"); + auto prints1 = TestPrints::Read(instance1); + auto prints2 = TestPrints::Read(instance2); + REQUIRE(prints1.size() == 2); + REQUIRE(prints2.size() == 2); + CHECK(prints1[1] == "TRACE: third"); + CHECK(prints2[1] == "TRACE: third"); + + SECTION("log via lambda function") { + Logger::Log(LogLevel::Trace, + [] { return std::string{"forth"}; }); + auto prints1 = TestPrints::Read(instance1); + auto prints2 = TestPrints::Read(instance2); + REQUIRE(prints1.size() == 3); + REQUIRE(prints2.size() == 3); + CHECK(prints1[2] == "TRACE: forth"); + CHECK(prints2[2] == "TRACE: forth"); + } + } + } +} + +TEST_CASE_METHOD(TwoGlobalSinksFixture, + "Local named logger using two global sinks", + "[logger]") { + // create logger with sink instances from global LogConfig + Logger logger("TestLogger"); + + // logs should be forwarded to same sink instances: 0 and 1 + int instance1 = 0; + int instance2 = 1; + + // create log outside of log limit + logger.Emit(LogLevel::Trace, "first"); + CHECK(TestPrints::Read(instance1).empty()); + CHECK(TestPrints::Read(instance2).empty()); + + SECTION("create log within log limit") { + logger.Emit(LogLevel::Info, "second"); + auto prints1 = TestPrints::Read(instance1); + auto prints2 = TestPrints::Read(instance2); + REQUIRE(prints1.size() == 1); + REQUIRE(prints2.size() == 1); + CHECK(prints1[0] == "INFO (TestLogger): second"); + CHECK(prints2[0] == "INFO (TestLogger): second"); + + SECTION("increase log limit create log within log limit") { + logger.SetLogLimit(LogLevel::Trace); + logger.Emit(LogLevel::Trace, "third"); + auto prints1 = TestPrints::Read(instance1); + auto prints2 = TestPrints::Read(instance2); + REQUIRE(prints1.size() == 2); + REQUIRE(prints2.size() == 2); + CHECK(prints1[1] == "TRACE (TestLogger): third"); + CHECK(prints2[1] == "TRACE (TestLogger): third"); + + SECTION("log via lambda function") { + logger.Emit(LogLevel::Trace, + [] { return std::string{"forth"}; }); + auto prints1 = TestPrints::Read(instance1); + auto prints2 = TestPrints::Read(instance2); + REQUIRE(prints1.size() == 3); + REQUIRE(prints2.size() == 3); + CHECK(prints1[2] == "TRACE (TestLogger): forth"); + CHECK(prints2[2] == "TRACE (TestLogger): forth"); + } + } + } +} + +TEST_CASE_METHOD(TwoGlobalSinksFixture, + "Local named logger with its own two sink instances", + "[logger]") { + // create logger with separate sink instances + Logger logger("OwnSinkLogger", + {LogSinkTest::CreateFactory(), LogSinkTest::CreateFactory()}); + + // logs should be forwarded to new sink instances: 2 and 3 + int instance1 = 2; + int instance2 = 3; + + // create log outside of log limit + logger.Emit(LogLevel::Trace, "first"); + CHECK(TestPrints::Read(instance1).empty()); + CHECK(TestPrints::Read(instance2).empty()); + + SECTION("create log within log limit") { + logger.Emit(LogLevel::Info, "second"); + auto prints1 = TestPrints::Read(instance1); + auto prints2 = TestPrints::Read(instance2); + REQUIRE(prints1.size() == 1); + REQUIRE(prints2.size() == 1); + CHECK(prints1[0] == "INFO (OwnSinkLogger): second"); + CHECK(prints2[0] == "INFO (OwnSinkLogger): second"); + + SECTION("increase log limit create log within log limit") { + logger.SetLogLimit(LogLevel::Trace); + logger.Emit(LogLevel::Trace, "third"); + auto prints1 = TestPrints::Read(instance1); + auto prints2 = TestPrints::Read(instance2); + REQUIRE(prints1.size() == 2); + REQUIRE(prints2.size() == 2); + CHECK(prints1[1] == "TRACE (OwnSinkLogger): third"); + CHECK(prints2[1] == "TRACE (OwnSinkLogger): third"); + + SECTION("log via lambda function") { + logger.Emit(LogLevel::Trace, + [] { return std::string{"forth"}; }); + auto prints1 = TestPrints::Read(instance1); + auto prints2 = TestPrints::Read(instance2); + REQUIRE(prints1.size() == 3); + REQUIRE(prints2.size() == 3); + CHECK(prints1[2] == "TRACE (OwnSinkLogger): forth"); + CHECK(prints2[2] == "TRACE (OwnSinkLogger): forth"); + } + } + } +} |