logging_unittest.cc 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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. // Tests that the spec file is valid.
  43. TEST_F(LoggingTest, basicSpec) {
  44. std::string specfile = std::string(TEST_DATA_BUILDDIR) + "/../logging.spec";
  45. ASSERT_NO_THROW(isc::config::moduleSpecFromFile(specfile));
  46. }
  47. // Checks that contructor is able to process specified storage properly
  48. TEST_F(LoggingTest, constructor) {
  49. SrvConfigPtr null_ptr;
  50. EXPECT_THROW(LogConfigParser parser(null_ptr), BadValue);
  51. SrvConfigPtr nonnull(new SrvConfig());
  52. EXPECT_NO_THROW(LogConfigParser parser(nonnull));
  53. }
  54. // Checks if the LogConfigParser class is able to transform JSON structures
  55. // into Configuration usable by log4cplus. This test checks for output
  56. // configured to stdout on debug level.
  57. TEST_F(LoggingTest, parsingConsoleOutput) {
  58. const char* config_txt =
  59. "{ \"loggers\": ["
  60. " {"
  61. " \"name\": \"kea\","
  62. " \"output_options\": ["
  63. " {"
  64. " \"output\": \"stdout\","
  65. " \"flush\": true"
  66. " }"
  67. " ],"
  68. " \"debuglevel\": 99,"
  69. " \"severity\": \"DEBUG\""
  70. " }"
  71. "]}";
  72. SrvConfigPtr storage(new SrvConfig());
  73. LogConfigParser parser(storage);
  74. // We need to parse properly formed JSON and then extract
  75. // "loggers" element from it. For some reason fromJSON is
  76. // throwing at opening square bracket
  77. ConstElementPtr config = Element::fromJSON(config_txt);
  78. config = config->get("loggers");
  79. EXPECT_NO_THROW(parser.parseConfiguration(config));
  80. ASSERT_EQ(1, storage->getLoggingInfo().size());
  81. EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
  82. EXPECT_EQ(99, storage->getLoggingInfo()[0].debuglevel_);
  83. EXPECT_EQ(isc::log::DEBUG, storage->getLoggingInfo()[0].severity_);
  84. ASSERT_EQ(1, storage->getLoggingInfo()[0].destinations_.size());
  85. EXPECT_EQ("stdout" , storage->getLoggingInfo()[0].destinations_[0].output_);
  86. EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[0].flush_);
  87. }
  88. // Checks if the LogConfigParser class is able to transform JSON structures
  89. // into Configuration usable by log4cplus. This test checks for output
  90. // configured to a file on INFO level.
  91. TEST_F(LoggingTest, parsingFile) {
  92. const char* config_txt =
  93. "{ \"loggers\": ["
  94. " {"
  95. " \"name\": \"kea\","
  96. " \"output_options\": ["
  97. " {"
  98. " \"output\": \"logfile.txt\""
  99. " }"
  100. " ],"
  101. " \"severity\": \"INFO\""
  102. " }"
  103. "]}";
  104. SrvConfigPtr storage(new SrvConfig());
  105. LogConfigParser parser(storage);
  106. // We need to parse properly formed JSON and then extract
  107. // "loggers" element from it. For some reason fromJSON is
  108. // throwing at opening square bracket
  109. ConstElementPtr config = Element::fromJSON(config_txt);
  110. config = config->get("loggers");
  111. EXPECT_NO_THROW(parser.parseConfiguration(config));
  112. ASSERT_EQ(1, storage->getLoggingInfo().size());
  113. EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
  114. EXPECT_EQ(0, storage->getLoggingInfo()[0].debuglevel_);
  115. EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
  116. ASSERT_EQ(1, storage->getLoggingInfo()[0].destinations_.size());
  117. EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
  118. // Default for immediate flush is true
  119. EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[0].flush_);
  120. }
  121. // Checks if the LogConfigParser class is able to transform data structures
  122. // into Configuration usable by log4cplus. This test checks that more than
  123. // one logger can be configured.
  124. TEST_F(LoggingTest, multipleLoggers) {
  125. const char* config_txt =
  126. "{ \"loggers\": ["
  127. " {"
  128. " \"name\": \"kea\","
  129. " \"output_options\": ["
  130. " {"
  131. " \"output\": \"logfile.txt\","
  132. " \"flush\": true"
  133. " }"
  134. " ],"
  135. " \"severity\": \"INFO\""
  136. " },"
  137. " {"
  138. " \"name\": \"wombat\","
  139. " \"output_options\": ["
  140. " {"
  141. " \"output\": \"logfile2.txt\","
  142. " \"flush\": false"
  143. " }"
  144. " ],"
  145. " \"severity\": \"DEBUG\","
  146. " \"debuglevel\": 99"
  147. " }"
  148. "]}";
  149. SrvConfigPtr storage(new SrvConfig());
  150. LogConfigParser parser(storage);
  151. // We need to parse properly formed JSON and then extract
  152. // "loggers" element from it. For some reason fromJSON is
  153. // throwing at opening square bracket
  154. ConstElementPtr config = Element::fromJSON(config_txt);
  155. config = config->get("loggers");
  156. EXPECT_NO_THROW(parser.parseConfiguration(config));
  157. ASSERT_EQ(2, storage->getLoggingInfo().size());
  158. EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
  159. EXPECT_EQ(0, storage->getLoggingInfo()[0].debuglevel_);
  160. EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
  161. ASSERT_EQ(1, storage->getLoggingInfo()[0].destinations_.size());
  162. EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
  163. EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[0].flush_);
  164. EXPECT_EQ("wombat", storage->getLoggingInfo()[1].name_);
  165. EXPECT_EQ(99, storage->getLoggingInfo()[1].debuglevel_);
  166. EXPECT_EQ(isc::log::DEBUG, storage->getLoggingInfo()[1].severity_);
  167. ASSERT_EQ(1, storage->getLoggingInfo()[1].destinations_.size());
  168. EXPECT_EQ("logfile2.txt" , storage->getLoggingInfo()[1].destinations_[0].output_);
  169. EXPECT_FALSE(storage->getLoggingInfo()[1].destinations_[0].flush_);
  170. }
  171. // Checks if the LogConfigParser class is able to transform data structures
  172. // into Configuration usable by log4cplus. This test checks that more than
  173. // one logging destination can be configured.
  174. TEST_F(LoggingTest, multipleLoggingDestinations) {
  175. const char* config_txt =
  176. "{ \"loggers\": ["
  177. " {"
  178. " \"name\": \"kea\","
  179. " \"output_options\": ["
  180. " {"
  181. " \"output\": \"logfile.txt\""
  182. " },"
  183. " {"
  184. " \"output\": \"stdout\""
  185. " }"
  186. " ],"
  187. " \"severity\": \"INFO\""
  188. " }"
  189. "]}";
  190. SrvConfigPtr storage(new SrvConfig());
  191. LogConfigParser parser(storage);
  192. // We need to parse properly formed JSON and then extract
  193. // "loggers" element from it. For some reason fromJSON is
  194. // throwing at opening square bracket
  195. ConstElementPtr config = Element::fromJSON(config_txt);
  196. config = config->get("loggers");
  197. EXPECT_NO_THROW(parser.parseConfiguration(config));
  198. ASSERT_EQ(1, storage->getLoggingInfo().size());
  199. EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
  200. EXPECT_EQ(0, storage->getLoggingInfo()[0].debuglevel_);
  201. EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
  202. ASSERT_EQ(2, storage->getLoggingInfo()[0].destinations_.size());
  203. EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
  204. EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[0].flush_);
  205. EXPECT_EQ("stdout" , storage->getLoggingInfo()[0].destinations_[1].output_);
  206. EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[1].flush_);
  207. }
  208. /// @todo Add tests for malformed logging configuration
  209. /// @todo There is no easy way to test applyConfiguration() and defaultLogging().
  210. /// To test them, it would require instrumenting log4cplus to actually fake
  211. /// the logging set up. Alternatively, we could develop set of test suites
  212. /// that check each logging destination spearately (e.g. configure log file, then
  213. /// check if the file is indeed created or configure stdout destination, then
  214. /// swap console file descriptors and check that messages are really logged.
  215. };