logging_unittest.cc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. // Copyright (C) 2014, 2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <exceptions/exceptions.h>
  16. #include <cc/data.h>
  17. #include <config/module_spec.h>
  18. #include <dhcpsrv/logging.h>
  19. #include <gtest/gtest.h>
  20. #include <log/logger_support.h>
  21. using namespace isc;
  22. using namespace isc::dhcp;
  23. using namespace isc::data;
  24. namespace {
  25. /// @brief Logging Test Fixture Class
  26. ///
  27. /// Trivial class that ensures that the logging is reset to its defaults after
  28. /// each test. Strictly speaking this only resets the testing root logger (which
  29. /// has the name "kea") but as the only other logger mentioned here ("wombat")
  30. /// is not used elsewhere, that is sufficient.
  31. class LoggingTest : public ::testing::Test {
  32. public:
  33. /// @brief Constructor
  34. LoggingTest() {}
  35. /// @brief Destructor
  36. ///
  37. /// Reset root logger back to defaults.
  38. ~LoggingTest() {
  39. isc::log::setDefaultLoggingOutput();
  40. }
  41. };
  42. // Helper to get the spec file
  43. std::string specfile(const std::string& name) {
  44. return (std::string(TEST_DATA_BUILDDIR) + "/../" + name);
  45. }
  46. // Tests that the spec file is valid.
  47. TEST_F(LoggingTest, basicSpec) {
  48. ASSERT_NO_THROW(isc::config::moduleSpecFromFile(specfile("logging.spec")));
  49. }
  50. // Checks that contructor is able to process specified storage properly
  51. TEST_F(LoggingTest, constructor) {
  52. SrvConfigPtr null_ptr;
  53. EXPECT_THROW(LogConfigParser parser(null_ptr), BadValue);
  54. SrvConfigPtr nonnull(new SrvConfig());
  55. EXPECT_NO_THROW(LogConfigParser parser(nonnull));
  56. }
  57. // Checks if the LogConfigParser class is able to transform JSON structures
  58. // into Configuration usable by log4cplus. This test checks for output
  59. // configured to stdout on debug level.
  60. TEST_F(LoggingTest, parsingConsoleOutput) {
  61. const char* config_txt =
  62. "{ \"loggers\": ["
  63. " {"
  64. " \"name\": \"kea\","
  65. " \"output_options\": ["
  66. " {"
  67. " \"output\": \"stdout\""
  68. " }"
  69. " ],"
  70. " \"debuglevel\": 99,"
  71. " \"severity\": \"DEBUG\""
  72. " }"
  73. "]}";
  74. SrvConfigPtr storage(new SrvConfig());
  75. LogConfigParser parser(storage);
  76. // We need to parse properly formed JSON and then extract
  77. // "loggers" element from it. For some reason fromJSON is
  78. // throwing at opening square bracket
  79. ConstElementPtr config = Element::fromJSON(config_txt);
  80. config = config->get("loggers");
  81. EXPECT_NO_THROW(parser.parseConfiguration(config));
  82. ASSERT_EQ(1, storage->getLoggingInfo().size());
  83. EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
  84. EXPECT_EQ(99, storage->getLoggingInfo()[0].debuglevel_);
  85. EXPECT_EQ(isc::log::DEBUG, storage->getLoggingInfo()[0].severity_);
  86. ASSERT_EQ(1, storage->getLoggingInfo()[0].destinations_.size());
  87. EXPECT_EQ("stdout" , storage->getLoggingInfo()[0].destinations_[0].output_);
  88. }
  89. // Checks if the LogConfigParser class is able to transform JSON structures
  90. // into Configuration usable by log4cplus. This test checks for output
  91. // configured to a file on INFO level.
  92. TEST_F(LoggingTest, parsingFile) {
  93. const char* config_txt =
  94. "{ \"loggers\": ["
  95. " {"
  96. " \"name\": \"kea\","
  97. " \"output_options\": ["
  98. " {"
  99. " \"output\": \"logfile.txt\""
  100. " }"
  101. " ],"
  102. " \"severity\": \"INFO\""
  103. " }"
  104. "]}";
  105. SrvConfigPtr storage(new SrvConfig());
  106. LogConfigParser parser(storage);
  107. // We need to parse properly formed JSON and then extract
  108. // "loggers" element from it. For some reason fromJSON is
  109. // throwing at opening square bracket
  110. ConstElementPtr config = Element::fromJSON(config_txt);
  111. config = config->get("loggers");
  112. EXPECT_NO_THROW(parser.parseConfiguration(config));
  113. ASSERT_EQ(1, storage->getLoggingInfo().size());
  114. EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
  115. EXPECT_EQ(0, storage->getLoggingInfo()[0].debuglevel_);
  116. EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
  117. ASSERT_EQ(1, storage->getLoggingInfo()[0].destinations_.size());
  118. EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
  119. }
  120. // Checks if the LogConfigParser class is able to transform data structures
  121. // into Configuration usable by log4cplus. This test checks that more than
  122. // one logger can be configured.
  123. TEST_F(LoggingTest, multipleLoggers) {
  124. const char* config_txt =
  125. "{ \"loggers\": ["
  126. " {"
  127. " \"name\": \"kea\","
  128. " \"output_options\": ["
  129. " {"
  130. " \"output\": \"logfile.txt\""
  131. " }"
  132. " ],"
  133. " \"severity\": \"INFO\""
  134. " },"
  135. " {"
  136. " \"name\": \"wombat\","
  137. " \"output_options\": ["
  138. " {"
  139. " \"output\": \"logfile2.txt\""
  140. " }"
  141. " ],"
  142. " \"severity\": \"DEBUG\","
  143. " \"debuglevel\": 99"
  144. " }"
  145. "]}";
  146. SrvConfigPtr storage(new SrvConfig());
  147. LogConfigParser parser(storage);
  148. // We need to parse properly formed JSON and then extract
  149. // "loggers" element from it. For some reason fromJSON is
  150. // throwing at opening square bracket
  151. ConstElementPtr config = Element::fromJSON(config_txt);
  152. config = config->get("loggers");
  153. EXPECT_NO_THROW(parser.parseConfiguration(config));
  154. ASSERT_EQ(2, storage->getLoggingInfo().size());
  155. EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
  156. EXPECT_EQ(0, storage->getLoggingInfo()[0].debuglevel_);
  157. EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
  158. ASSERT_EQ(1, storage->getLoggingInfo()[0].destinations_.size());
  159. EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
  160. EXPECT_EQ("wombat", storage->getLoggingInfo()[1].name_);
  161. EXPECT_EQ(99, storage->getLoggingInfo()[1].debuglevel_);
  162. EXPECT_EQ(isc::log::DEBUG, storage->getLoggingInfo()[1].severity_);
  163. ASSERT_EQ(1, storage->getLoggingInfo()[1].destinations_.size());
  164. EXPECT_EQ("logfile2.txt" , storage->getLoggingInfo()[1].destinations_[0].output_);
  165. }
  166. // Checks if the LogConfigParser class is able to transform data structures
  167. // into Configuration usable by log4cplus. This test checks that more than
  168. // one logging destination can be configured.
  169. TEST_F(LoggingTest, multipleLoggingDestinations) {
  170. const char* config_txt =
  171. "{ \"loggers\": ["
  172. " {"
  173. " \"name\": \"kea\","
  174. " \"output_options\": ["
  175. " {"
  176. " \"output\": \"logfile.txt\""
  177. " },"
  178. " {"
  179. " \"output\": \"stdout\""
  180. " }"
  181. " ],"
  182. " \"severity\": \"INFO\""
  183. " }"
  184. "]}";
  185. SrvConfigPtr storage(new SrvConfig());
  186. LogConfigParser parser(storage);
  187. // We need to parse properly formed JSON and then extract
  188. // "loggers" element from it. For some reason fromJSON is
  189. // throwing at opening square bracket
  190. ConstElementPtr config = Element::fromJSON(config_txt);
  191. config = config->get("loggers");
  192. EXPECT_NO_THROW(parser.parseConfiguration(config));
  193. ASSERT_EQ(1, storage->getLoggingInfo().size());
  194. EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
  195. EXPECT_EQ(0, storage->getLoggingInfo()[0].debuglevel_);
  196. EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
  197. ASSERT_EQ(2, storage->getLoggingInfo()[0].destinations_.size());
  198. EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
  199. EXPECT_EQ("stdout" , storage->getLoggingInfo()[0].destinations_[1].output_);
  200. }
  201. /// @todo There is no easy way to test applyConfiguration() and defaultLogging().
  202. /// To test them, it would require instrumenting log4cplus to actually fake
  203. /// the logging set up. Alternatively, we could develop set of test suites
  204. /// that check each logging destination spearately (e.g. configure log file, then
  205. /// check if the file is indeed created or configure stdout destination, then
  206. /// swap console file descriptors and check that messages are really logged.
  207. };