file_appender_test.cxx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. //
  2. // file_appender_test.cxx
  3. // logger_test
  4. //
  5. // Created by Sam Jaffe on 4/13/19.
  6. //
  7. #include <cstdlib>
  8. #include <fstream>
  9. #include <gmock/gmock.h>
  10. #include "resource_factory/prototype_factory.hpp"
  11. #include "logger/exception.h"
  12. #include "logger/log_manager.h"
  13. #include "logger/properties.h"
  14. #include "logger_impl.h"
  15. #include "mock_logger.h"
  16. class FileAppenderTest : public testing::Test {
  17. protected:
  18. void SetUp() override;
  19. void TearDown() override;
  20. std::string filename() const { return data; }
  21. std::shared_ptr<logging::log_appender> get(logging::properties const &) const;
  22. private:
  23. std::shared_ptr<StubLayout> playout;
  24. char data[24];
  25. };
  26. void FileAppenderTest::SetUp() {
  27. strncpy(data, "test_log_fileXXXXXX.log", sizeof(data));
  28. int fd = -1;
  29. if ((fd = mkstemps(data, 4)) != -1) {
  30. close(fd); // We'll open this elsewhere
  31. } else {
  32. throw std::runtime_error(strerror(errno));
  33. }
  34. playout.reset(new StubLayout);
  35. }
  36. void FileAppenderTest::TearDown() {
  37. playout.reset();
  38. remove(data);
  39. memset(data, 0, sizeof(data));
  40. }
  41. std::shared_ptr<logging::log_appender>
  42. FileAppenderTest::get(logging::properties const & props) const {
  43. auto pappender = logging::appenders::instance().get("File", props);
  44. return std::make_shared<logging::log_appender>(pappender, playout);
  45. }
  46. TEST_F(FileAppenderTest, ThrowsIfNoFilename) {
  47. EXPECT_THROW(logging::appenders::instance().get("File", {}),
  48. logging::invalid_property_type);
  49. }
  50. std::string slurp(std::string const & filename) {
  51. std::ifstream in(filename);
  52. std::stringstream ss;
  53. ss << in.rdbuf();
  54. return ss.str();
  55. }
  56. TEST_F(FileAppenderTest, WritesFile) {
  57. using namespace logging;
  58. using namespace logging::property;
  59. properties props{_obj({{"filename", _v(filename())}})};
  60. using testing::Eq;
  61. logpacket pkt{{}, level::error, {}, {}, "This is a test message"};
  62. EXPECT_NO_THROW(get(props)->write(pkt));
  63. EXPECT_THAT(slurp(filename()), Eq("This is a test message"));
  64. }
  65. TEST_F(FileAppenderTest, WillNotLogBelowThreshold) {
  66. using namespace logging;
  67. using namespace logging::property;
  68. properties props{_obj({{"filename", _v(filename())}})};
  69. EXPECT_FALSE(get(props)->should_log(level::warn));
  70. EXPECT_TRUE(get(props)->should_log(level::error));
  71. }
  72. TEST_F(FileAppenderTest, AppendsToFile) {
  73. using namespace logging;
  74. using namespace logging::property;
  75. properties props{_obj({{"filename", _v(filename())}})};
  76. using testing::Eq;
  77. logpacket pkt{{}, level::error, {}, {}, "Test"};
  78. for (int i = 0; i < 2; ++i) {
  79. EXPECT_NO_THROW(get(props)->write(pkt));
  80. }
  81. EXPECT_THAT(slurp(filename()), Eq("TestTest"));
  82. }
  83. TEST_F(FileAppenderTest, OverwritesFileWithSetting) {
  84. using namespace logging;
  85. using namespace logging::property;
  86. properties props{
  87. _obj({{"filename", _v(filename())}, {"fileAppend", _v(false)}})};
  88. using testing::Eq;
  89. logpacket pkt{{}, level::error, {}, {}, "Test"};
  90. for (int i = 0; i < 2; ++i) {
  91. EXPECT_NO_THROW(get(props)->write(pkt));
  92. }
  93. EXPECT_THAT(slurp(filename()), Eq("Test"));
  94. }
  95. TEST_F(FileAppenderTest, CanWriteBufferedData) {
  96. using namespace logging;
  97. using namespace logging::property;
  98. properties props{_obj({{"immediateFlush", _v(false)},
  99. {"filename", _v(filename())},
  100. {"bufferedIO", _v(true)},
  101. {"bufferSize", _v(256)}})};
  102. using testing::Eq;
  103. logpacket pkt{{}, level::error, {}, {}, "Test"};
  104. EXPECT_NO_THROW(get(props)->write(pkt));
  105. // We can't really test the results here, because the standard library is in
  106. // control of the actual writes...
  107. }
  108. TEST_F(FileAppenderTest, WillThrowIfCannotOpenFile) {
  109. using namespace logging;
  110. using namespace logging::property;
  111. properties props{
  112. _obj({{"filename", _v("./fake_directory_for_testing/file.log")}})};
  113. EXPECT_THROW(get(props), std::runtime_error);
  114. }