logger_manager_unittest.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // Copyright (C) 2011 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 <stdio.h>
  15. #include <unistd.h>
  16. #include <fstream>
  17. #include <iostream>
  18. #include <string>
  19. #include <gtest/gtest.h>
  20. #include <log/macros.h>
  21. #include <log/messagedef.h>
  22. #include <log/logger.h>
  23. #include <log/logger_level.h>
  24. #include <log/logger_manager.h>
  25. #include <log/logger_specification.h>
  26. #include <log/output_option.h>
  27. using namespace isc::log;
  28. using namespace std;
  29. /// \brief Derived logger
  30. ///
  31. /// Only exists to make the protected static methods in Logger public for
  32. /// test purposes.
  33. class DerivedLogger : public isc::log::Logger {
  34. public:
  35. DerivedLogger(std::string name) : isc::log::Logger(name)
  36. {}
  37. virtual ~DerivedLogger()
  38. {}
  39. static void reset() {
  40. isc::log::Logger::reset();
  41. }
  42. };
  43. /// \brief LoggerManager Test
  44. class LoggerManagerTest : public ::testing::Test {
  45. public:
  46. LoggerManagerTest()
  47. {}
  48. ~LoggerManagerTest()
  49. {
  50. DerivedLogger::reset();
  51. }
  52. };
  53. // Convenience class to create the specification for the logger "filelogger",
  54. // which, as the name suggests, logs to a file. It remembers the file name and
  55. // deletes the file when instance of the class is destroyed.
  56. class SpecificationForFileLogger {
  57. public:
  58. // Constructor - allocate file and create the specification object
  59. SpecificationForFileLogger() : spec_(), name_(""), logname_("filelogger") {
  60. OutputOption option;
  61. option.destination = OutputOption::DEST_FILE;
  62. name_ = option.filename = std::string(tmpnam(NULL));
  63. spec_.setName(logname_);
  64. spec_.addOutputOption(option);
  65. }
  66. // Destructor, remove the file. This is only a test, so ignore failures
  67. ~SpecificationForFileLogger() {
  68. if (! name_.empty()) {
  69. (void) unlink(name_.c_str());
  70. }
  71. }
  72. // Return reference to the logging specification for this loggger
  73. LoggerSpecification& getSpecification() {
  74. return spec_;
  75. }
  76. // Return name of the logger
  77. string getLoggerName() const {
  78. return logname_;
  79. }
  80. // Return name of the file
  81. string getFileName() const {
  82. return name_;
  83. }
  84. private:
  85. LoggerSpecification spec_; // Specification for this file logger
  86. string name_; // Name of the output file
  87. string logname_; // Name of this logger
  88. };
  89. // Convenience function to read an output log file and check that each line
  90. // contains the expected message ID
  91. //
  92. // \param filename Name of the file to check
  93. // \param start Iterator pointing to first expected message ID
  94. // \param finish Iterator pointing to last expected message ID
  95. template <typename T>
  96. void checkFileContents(const std::string& filename, T start, T finish) {
  97. // Access the file for input
  98. ifstream infile(filename.c_str());
  99. if (! infile.good()) {
  100. FAIL() << "Unable to open the logging file " << filename;
  101. }
  102. // Iterate round the expected message IDs and check that they appear in
  103. // the string.
  104. string line; // Line read from the file
  105. T i = start; // Iterator
  106. getline(infile, line);
  107. int lineno = 1;
  108. while ((i != finish) && (infile.good())) {
  109. // Check that the message ID appears in the line.
  110. EXPECT_TRUE(line.find(string(*i)) != string::npos)
  111. << "Expected to find " << string(*i) << " on line " << lineno
  112. << " of logging file " << filename;
  113. // Go for the next line
  114. ++i;
  115. getline(infile, line);
  116. ++lineno;
  117. }
  118. // Why did the loop end?
  119. EXPECT_TRUE(i == finish) << "Did not reach the end of the message ID list";
  120. EXPECT_TRUE(infile.eof()) << "Did not reach the end of the logging file";
  121. // File will close when the instream is deleted at the end of this
  122. // function.
  123. }
  124. // Check that the logger correctly creates something logging to a file.
  125. TEST_F(LoggerManagerTest, FileLogger) {
  126. // Create a specification for the file logger and use the manager to
  127. // connect the "filelogger" logger to it.
  128. SpecificationForFileLogger file_spec;
  129. vector<LoggerSpecification> specVector(1, file_spec.getSpecification());
  130. LoggerManager manager;
  131. manager.process(specVector.begin(), specVector.end());
  132. // Try logging to the file. Local scope is set to ensure that the logger
  133. // is destroyed before we reset the global logging. We record what we
  134. // put in the file for a later comparison.
  135. vector<MessageID> ids;
  136. {
  137. Logger logger(file_spec.getLoggerName());
  138. LOG_FATAL(logger, MSG_DUPMSGID).arg("test");
  139. ids.push_back(MSG_DUPMSGID);
  140. LOG_FATAL(logger, MSG_DUPLNS).arg("test");
  141. ids.push_back(MSG_DUPLNS);
  142. }
  143. DerivedLogger::reset();
  144. // At this point, the output file should contain two lines with messages
  145. // LOGTEST_TEST1 and LOGTEST_TEST2 messages - test this.
  146. checkFileContents(file_spec.getFileName(), ids.begin(), ids.end());
  147. }