// // file_appender_test.cxx // logger_test // // Created by Sam Jaffe on 4/13/19. // #include #include #include #include "resource_factory/prototype_factory.hpp" #include "logger/exception.h" #include "logger/log_manager.h" #include "logger/properties.h" #include "logger_impl.h" #include "mock_logger.h" class FileAppenderTest : public testing::Test { protected: void SetUp() override; void TearDown() override; std::string filename() const { return data; } std::shared_ptr get(logging::properties const &) const; private: std::shared_ptr playout; char data[24]; }; void FileAppenderTest::SetUp() { strncpy(data, "test_log_fileXXXXXX.log", sizeof(data)); int fd = -1; if ((fd = mkstemps(data, 4)) != -1) { close(fd); // We'll open this elsewhere } else { throw std::runtime_error(strerror(errno)); } playout.reset(new StubLayout); } void FileAppenderTest::TearDown() { playout.reset(); remove(data); memset(data, 0, sizeof(data)); } std::shared_ptr FileAppenderTest::get(logging::properties const & props) const { auto pappender = logging::appenders::instance().get("File", props); return std::make_shared(pappender, playout); } TEST_F(FileAppenderTest, ThrowsIfNoFilename) { EXPECT_THROW(logging::appenders::instance().get("File", {}), logging::invalid_property_type); } std::string slurp(std::string const & filename) { std::ifstream in(filename); std::stringstream ss; ss << in.rdbuf(); return ss.str(); } TEST_F(FileAppenderTest, WritesFile) { using namespace logging; using namespace logging::property; properties props{_obj({{"filename", _v(filename())}})}; using testing::Eq; logpacket pkt{{}, level::error, {}, {}, "This is a test message"}; EXPECT_NO_THROW(get(props)->write(pkt)); EXPECT_THAT(slurp(filename()), Eq("This is a test message")); } TEST_F(FileAppenderTest, WillNotLogBelowThreshold) { using namespace logging; using namespace logging::property; properties props{_obj({{"filename", _v(filename())}})}; EXPECT_FALSE(get(props)->should_log(level::warn)); EXPECT_TRUE(get(props)->should_log(level::error)); } TEST_F(FileAppenderTest, AppendsToFile) { using namespace logging; using namespace logging::property; properties props{_obj({{"filename", _v(filename())}})}; using testing::Eq; logpacket pkt{{}, level::error, {}, {}, "Test"}; for (int i = 0; i < 2; ++i) { EXPECT_NO_THROW(get(props)->write(pkt)); } EXPECT_THAT(slurp(filename()), Eq("TestTest")); } TEST_F(FileAppenderTest, OverwritesFileWithSetting) { using namespace logging; using namespace logging::property; properties props{ _obj({{"filename", _v(filename())}, {"fileAppend", _v(false)}})}; using testing::Eq; logpacket pkt{{}, level::error, {}, {}, "Test"}; for (int i = 0; i < 2; ++i) { EXPECT_NO_THROW(get(props)->write(pkt)); } EXPECT_THAT(slurp(filename()), Eq("Test")); } TEST_F(FileAppenderTest, CanWriteBufferedData) { using namespace logging; using namespace logging::property; properties props{_obj({{"immediateFlush", _v(false)}, {"filename", _v(filename())}, {"bufferedIO", _v(true)}, {"bufferSize", _v(256)}})}; using testing::Eq; logpacket pkt{{}, level::error, {}, {}, "Test"}; EXPECT_NO_THROW(get(props)->write(pkt)); // We can't really test the results here, because the standard library is in // control of the actual writes... } TEST_F(FileAppenderTest, WillThrowIfCannotOpenFile) { using namespace logging; using namespace logging::property; properties props{ _obj({{"filename", _v("./fake_directory_for_testing/file.log")}})}; EXPECT_THROW(get(props), std::runtime_error); }