json_layout_test.cxx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. //
  2. // json_layout_test.cxx
  3. // logger_test
  4. //
  5. // Created by Sam Jaffe on 4/13/19.
  6. //
  7. #include <gmock/gmock.h>
  8. #include <json/json.h>
  9. #include "resource_factory/prototype_factory.hpp"
  10. #include "logger/detail/layout.h"
  11. #include "logger/log_manager.h"
  12. #include "logger/logpacket.h"
  13. #include "logger/properties.h"
  14. TEST(JsonLayoutTest, CanConstructWithNoConfig) {
  15. EXPECT_NO_THROW(logging::layouts::instance().get("JsonLayout", {}));
  16. }
  17. // Thursday, April 4, 2019 6:17:20 PM GMT
  18. namespace {
  19. constexpr const int NOW = 1554401840;
  20. }
  21. std::string const formatted_output = R"({
  22. "instant" : {
  23. "epochSecond" : 1554401840,
  24. "nanoOfSecond" : 123456000
  25. },
  26. "level" : "WARNING",
  27. "loggerName" : "UnitTest",
  28. "message" : "This is a test message"
  29. })";
  30. std::string const compact_output = "{\"instant\":{\"epochSecond\":"
  31. "1554401840,\"nanoOfSecond\":123456000},\"level\":\"WARNING\","
  32. "\"loggerName\":\"UnitTest\",\"message\":\"This is a test message\"}";
  33. TEST(JsonLayoutTest, LogsInformationInJSON) {
  34. using namespace logging;
  35. auto playout = layouts::instance().get("JsonLayout", {});
  36. std::stringstream ss;
  37. playout->format(ss, {{NOW, 123456}, level::warning, {}, "UnitTest",
  38. "This is a test message"});
  39. using testing::Eq;
  40. EXPECT_THAT(ss.str(), Eq(formatted_output));
  41. }
  42. TEST(JsonLayoutTest, CompactMeansNoWhitespace) {
  43. using namespace logging;
  44. using namespace logging::property;
  45. properties const props{_obj({
  46. {"compact", _v(true)}
  47. })};
  48. auto playout = layouts::instance().get("JsonLayout", props);
  49. std::stringstream ss;
  50. playout->format(ss, {{NOW, 123456}, level::warning, {}, "UnitTest",
  51. "This is a test message"});
  52. using testing::Eq;
  53. EXPECT_THAT(ss.str(), Eq(compact_output));
  54. }
  55. TEST(JsonLayoutTest, EOLPropertyAppendsNewline) {
  56. using namespace logging;
  57. using namespace logging::property;
  58. properties const props{_obj({
  59. {"eventEol", _v(true)}
  60. })};
  61. auto playout = layouts::instance().get("JsonLayout", props);
  62. std::stringstream ss;
  63. playout->format(ss, {{NOW, 123456}, level::warning, {}, "UnitTest",
  64. "This is a test message"});
  65. using testing::EndsWith;
  66. using testing::StartsWith;
  67. EXPECT_THAT(ss.str(), StartsWith(formatted_output));
  68. EXPECT_THAT(ss.str(), EndsWith(logging::NEWLINE_TOKEN));
  69. }
  70. std::string const struct_output = R"({
  71. "instant" : {
  72. "epochSecond" : 1554401840,
  73. "nanoOfSecond" : 123456000
  74. },
  75. "level" : "WARNING",
  76. "loggerName" : "UnitTest",
  77. "message" : "{225}"
  78. })";
  79. struct example {
  80. int content;
  81. };
  82. std::ostream & operator<<(std::ostream & os, example const & ex) {
  83. return os << '{' << ex.content << '}';
  84. }
  85. std::string const struct_json_output = R"({
  86. "instant" : {
  87. "epochSecond" : 1554401840,
  88. "nanoOfSecond" : 123456000
  89. },
  90. "level" : "WARNING",
  91. "loggerName" : "UnitTest",
  92. "message" : {
  93. "content" : 225
  94. }
  95. })";
  96. struct json_example {
  97. int content;
  98. };
  99. std::ostream & operator<<(std::ostream & os, json_example const & ex) {
  100. return os << '{' << ex.content << '}';
  101. }
  102. Json::Value to_json(json_example const & ex) {
  103. Json::Value json;
  104. json["content"] = ex.content;
  105. return json;
  106. }
  107. TEST(JsonLayoutTest, MessageCanBeLoggedAsJSON) {
  108. using namespace logging;
  109. using namespace logging::property;
  110. properties const props{_obj({
  111. {"objectMessageAsJsonObject", _v(true)}
  112. })};
  113. auto playout = layouts::instance().get("JsonLayout", props);
  114. std::stringstream ss;
  115. json_example ex{225};
  116. playout->format(ss, {{NOW, 123456}, level::warning, {}, "UnitTest",
  117. {"This is a test message", ex}});
  118. using testing::Eq;
  119. EXPECT_THAT(ss.str(), Eq(struct_json_output));
  120. }
  121. TEST(JsonLayoutTest, ObjectLackingJsonDefaultsToString) {
  122. using namespace logging;
  123. using namespace logging::property;
  124. properties const props{_obj({
  125. {"objectMessageAsJsonObject", _v(true)}
  126. })};
  127. auto playout = layouts::instance().get("JsonLayout", props);
  128. std::stringstream ss;
  129. example ex{225};
  130. playout->format(ss, {{NOW, 123456}, level::warning, {}, "UnitTest",
  131. {"This is a test message", ex}});
  132. using testing::Eq;
  133. EXPECT_THAT(ss.str(), Eq(struct_output));
  134. }