file_appender_test.cxx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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>
  22. get(logging::properties const &) const;
  23. private:
  24. std::shared_ptr<StubLayout> playout;
  25. char data[24];
  26. };
  27. void FileAppenderTest::SetUp() {
  28. strncpy(data, "test_log_fileXXXXXX.log", sizeof(data));
  29. int fd = -1;
  30. if ((fd = mkstemps(data, 4)) != -1) {
  31. close(fd); // We'll open this elsewhere
  32. } else {
  33. throw std::runtime_error(strerror(errno));
  34. }
  35. playout.reset(new StubLayout);
  36. }
  37. void FileAppenderTest::TearDown() {
  38. playout.reset();
  39. remove(data);
  40. memset(data, 0, sizeof(data));
  41. }
  42. std::shared_ptr<logging::log_appender>
  43. FileAppenderTest::get(logging::properties const & props) const {
  44. auto pappender = logging::appenders::instance().get("File", props);
  45. return std::make_shared<logging::log_appender>(pappender, playout);
  46. }
  47. TEST_F(FileAppenderTest, ThrowsIfNoFilename) {
  48. EXPECT_THROW(logging::appenders::instance().get("File", {}),
  49. logging::invalid_property_type);
  50. }
  51. std::string slurp(std::string const & filename) {
  52. std::ifstream in(filename);
  53. std::stringstream ss;
  54. ss << in.rdbuf();
  55. return ss.str();
  56. }
  57. TEST_F(FileAppenderTest, WritesFile) {
  58. using namespace logging;
  59. using namespace logging::property;
  60. properties props{_obj({
  61. {"filename", _v(filename())}
  62. })};
  63. using testing::Eq;
  64. logpacket pkt{{}, level::error, {}, {}, "This is a test message"};
  65. EXPECT_NO_THROW(get(props)->write(pkt));
  66. EXPECT_THAT(slurp(filename()), Eq("This is a test message"));
  67. }
  68. TEST_F(FileAppenderTest, WillNotLogBelowThreshold) {
  69. using namespace logging;
  70. using namespace logging::property;
  71. properties props{_obj({
  72. {"filename", _v(filename())}
  73. })};
  74. EXPECT_FALSE(get(props)->should_log(level::warn));
  75. EXPECT_TRUE(get(props)->should_log(level::error));
  76. }
  77. TEST_F(FileAppenderTest, AppendsToFile) {
  78. using namespace logging;
  79. using namespace logging::property;
  80. properties props{_obj({
  81. {"filename", _v(filename())}
  82. })};
  83. using testing::Eq;
  84. logpacket pkt{{}, level::error, {}, {}, "Test"};
  85. for (int i = 0; i < 2; ++i) {
  86. EXPECT_NO_THROW(get(props)->write(pkt));
  87. }
  88. EXPECT_THAT(slurp(filename()), Eq("TestTest"));
  89. }
  90. TEST_F(FileAppenderTest, OverwritesFileWithSetting) {
  91. using namespace logging;
  92. using namespace logging::property;
  93. properties props{_obj({
  94. {"filename", _v(filename())},
  95. {"fileAppend", _v(false)}
  96. })};
  97. using testing::Eq;
  98. logpacket pkt{{}, level::error, {}, {}, "Test"};
  99. for (int i = 0; i < 2; ++i) {
  100. EXPECT_NO_THROW(get(props)->write(pkt));
  101. }
  102. EXPECT_THAT(slurp(filename()), Eq("Test"));
  103. }
  104. TEST_F(FileAppenderTest, CanWriteBufferedData) {
  105. using namespace logging;
  106. using namespace logging::property;
  107. properties props{_obj({
  108. {"immediateFlush", _v(false)},
  109. {"filename", _v(filename())},
  110. {"bufferedIO", _v(true)},
  111. {"bufferSize", _v(256)}
  112. })};
  113. using testing::Eq;
  114. logpacket pkt{{}, level::error, {}, {}, "Test"};
  115. EXPECT_NO_THROW(get(props)->write(pkt));
  116. // We can't really test the results here, because the standard library is in
  117. // control of the actual writes...
  118. }
  119. TEST_F(FileAppenderTest, WillThrowIfCannotOpenFile) {
  120. using namespace logging;
  121. using namespace logging::property;
  122. properties props{_obj({
  123. {"filename", _v("./fake_directory_for_testing/file.log")}
  124. })};
  125. EXPECT_THROW(get(props), std::runtime_error);
  126. }