// // log_manager_test.cxx // logger_test // // Created by Sam Jaffe on 4/2/19. // #include "logger/log_manager.h" #include "resource_factory/prototype_factory.hpp" #include "logger/c_logger.h" #include "logger/exception.h" #include "logger/logger.h" #include "logger/properties.h" #include "mock_logger.h" using namespace logging; class LogManagerTest : public ::testing::Test { public: void SetUp() override; void TearDown() override; protected: std::shared_ptr appender; std::shared_ptr layout; private: appenders::scoped_binding abinding_; layouts::scoped_binding lbinding_; }; namespace logging { level level_from_string(std::string const & value); } void LogManagerTest::SetUp() { auto GetMock = [this](properties const & props) { appender = std::make_shared(); if (props.contains("threshold")) { appender->threshold = level_from_string(props["threshold"]); } return appender; }; abinding_ = appenders::instance().bind_scoped("Mock", GetMock); auto GetMockLayout = [this](properties const &) { return layout = std::make_shared(); }; lbinding_ = layouts::instance().bind_scoped("MockLayout", GetMockLayout); } void LogManagerTest::TearDown() { abinding_.reset(); lbinding_.reset(); } extern properties const APPENDER_LEVEL_PROPERTY_SCHEMA; extern properties const DEFAULT_LAYOUT_PROPERTY_SCHEMA; extern properties const LOGGER_LEVEL_PROPERTY_SCHEMA; extern properties const MIN_PROPERTY_SCHEMA; extern properties const MULTIPLEX_PROPERTY_SCHEMA; TEST_F(LogManagerTest, CanInjectMock) { manager().configure(MIN_PROPERTY_SCHEMA); EXPECT_THAT(appender, ::testing::NotNull()); EXPECT_THAT(layout, ::testing::NotNull()); } TEST_F(LogManagerTest, IfNoLayoutIsProvidedThenWeUseTheDefault) { manager().configure(DEFAULT_LAYOUT_PROPERTY_SCHEMA); EXPECT_THAT(appender, ::testing::NotNull()); EXPECT_THAT(layout, testing::IsNull()); } TEST_F(LogManagerTest, WillThrowIfSchemaError) { using namespace logging::property; // clang-format off properties const BAD_SCHEMA = _obj({ {"configuration", _obj({ {"loggers", _obj({ {"root", _obj({ {"appenders", _v("Mock")} })} })}, {"appenders", _obj({})} })} }); // clang-format on EXPECT_THROW(manager().configure(BAD_SCHEMA), invalid_property_type); } using ::testing::_; using ::testing::AnyNumber; TEST_F(LogManagerTest, CanFetchInjectedMock) { manager mgr; mgr.configure(MIN_PROPERTY_SCHEMA); EXPECT_CALL(*appender, flush()).Times(AnyNumber()); EXPECT_CALL(*appender, write(MessageEq("TEST MESSAGE"), _)); c_logger l = mgr.c_get(); l.error("TEST MESSAGE"); } TEST_F(LogManagerTest, MultiplexMockLogsToMultipleImpls) { manager mgr; mgr.configure(MULTIPLEX_PROPERTY_SCHEMA); EXPECT_CALL(*appender, flush()).Times(AnyNumber()); EXPECT_CALL(*appender, write(MessageEq("TEST MESSAGE"), _)).Times(2); c_logger l = mgr.c_get(); l.error("TEST MESSAGE"); } TEST_F(LogManagerTest, LevelCanBeBakedIntoAppenderProperties) { manager mgr; mgr.configure(APPENDER_LEVEL_PROPERTY_SCHEMA); EXPECT_CALL(*appender, flush()).Times(AnyNumber()); EXPECT_CALL(*appender, write(MessageEq("TEST MESSAGE"), _)).Times(1); EXPECT_CALL(*appender, write(MessageEq("LOWER MESSAGE"), _)).Times(0); c_logger l = mgr.c_get(); l.warn("TEST MESSAGE"); l.info("LOWER MESSAGE"); } TEST_F(LogManagerTest, LevelCanBeBakedIntoLoggerProperties) { manager mgr; mgr.configure(LOGGER_LEVEL_PROPERTY_SCHEMA); EXPECT_CALL(*appender, flush()).Times(AnyNumber()); EXPECT_CALL(*appender, write(_, _)).Times(0); c_logger l = mgr.c_get(); l.warn("TEST MESSAGE"); } TEST_F(LogManagerTest, CanFetchLoggerByName) { manager mgr; mgr.configure(MIN_PROPERTY_SCHEMA); EXPECT_CALL(*appender, flush()).Times(AnyNumber()); EXPECT_CALL(*appender, write(MessageEq("TEST MESSAGE"), _)); c_logger l = mgr.c_get("root"); l.error("TEST MESSAGE"); } TEST_F(LogManagerTest, ThrowsIfAskingForNonExistantLoggerName) { manager mgr; mgr.configure(MIN_PROPERTY_SCHEMA); EXPECT_THROW(mgr.c_get("Mock"), std::out_of_range); EXPECT_THROW(mgr.get("Mock"), std::out_of_range); }