1 // Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 #include <gtest/gtest.h>
9 
10 #include <log/macros.h>
11 #include <log/logger_support.h>
12 #include <log/log_messages.h>
13 #include <log/buffer_appender_impl.h>
14 
15 #include <log4cplus/loggingmacros.h>
16 #include <log4cplus/logger.h>
17 #include <log4cplus/nullappender.h>
18 #include <log4cplus/spi/loggingevent.h>
19 
20 using namespace isc::log;
21 using namespace isc::log::internal;
22 
23 namespace isc {
24 namespace log {
25 
26 /// \brief Specialized test class
27 ///
28 /// In order to test append() somewhat directly, this
29 /// class implements one more method (addEvent)
30 class TestBufferAppender : public BufferAppender {
31 public:
addEvent(const log4cplus::spi::InternalLoggingEvent & event)32     void addEvent(const log4cplus::spi::InternalLoggingEvent& event) {
33         append(event);
34     }
35 };
36 
37 class BufferAppenderTest : public ::testing::Test {
38 protected:
BufferAppenderTest()39     BufferAppenderTest() : buffer_appender1(new TestBufferAppender()),
40                       appender1(buffer_appender1),
41                       buffer_appender2(new TestBufferAppender()),
42                       appender2(buffer_appender2),
43                       logger(log4cplus::Logger::getInstance("buffer"))
44     {
45         logger.setLogLevel(log4cplus::TRACE_LOG_LEVEL);
46     }
47 
~BufferAppenderTest()48     ~BufferAppenderTest() {
49         // If any log messages are left, we don't care, get rid of them,
50         // by flushing them to a null appender
51         // Given the 'messages should not get lost' approach of the logging
52         // system, not flushing them to a null appender would cause them
53         // to be dumped to stdout as the test is destroyed, making
54         // unnecessarily messy test output.
55         log4cplus::SharedAppenderPtr null_appender(
56             new log4cplus::NullAppender());
57         logger.removeAllAppenders();
58         logger.addAppender(null_appender);
59         buffer_appender1->flush();
60         buffer_appender2->flush();
61     }
62 
63     TestBufferAppender* buffer_appender1;
64     log4cplus::SharedAppenderPtr appender1;
65     TestBufferAppender* buffer_appender2;
66     log4cplus::SharedAppenderPtr appender2;
67     log4cplus::Logger logger;
68 };
69 
70 // Test that log events are indeed stored, and that they are
71 // flushed to the new appenders of their logger
TEST_F(BufferAppenderTest,flush)72 TEST_F(BufferAppenderTest, flush) {
73     ASSERT_EQ(0, buffer_appender1->getBufferSize());
74     ASSERT_EQ(0, buffer_appender2->getBufferSize());
75 
76     // Create a Logger, log a few messages with the first appender
77     logger.addAppender(appender1);
78     LOG4CPLUS_INFO(logger, "Foo");
79     ASSERT_EQ(1, buffer_appender1->getBufferSize());
80     LOG4CPLUS_INFO(logger, "Foo");
81     ASSERT_EQ(2, buffer_appender1->getBufferSize());
82     LOG4CPLUS_INFO(logger, "Foo");
83     ASSERT_EQ(3, buffer_appender1->getBufferSize());
84 
85     // Second buffer should still be empty
86     ASSERT_EQ(0, buffer_appender2->getBufferSize());
87 
88     // Replace the appender by the second one, and call flush;
89     // this should cause all events to be moved to the second buffer
90     logger.removeAllAppenders();
91     logger.addAppender(appender2);
92     buffer_appender1->flush();
93     ASSERT_EQ(0, buffer_appender1->getBufferSize());
94     ASSERT_EQ(3, buffer_appender2->getBufferSize());
95 }
96 
97 // Once flushed, logging new messages with the same buffer should fail
TEST_F(BufferAppenderTest,addAfterFlush)98 TEST_F(BufferAppenderTest, addAfterFlush) {
99     logger.addAppender(appender1);
100     buffer_appender1->flush();
101     EXPECT_THROW(LOG4CPLUS_INFO(logger, "Foo"), LogBufferAddAfterFlush);
102     // It should not have been added
103     ASSERT_EQ(0, buffer_appender1->getBufferSize());
104 
105     // But logging should work again as long as a different buffer is used
106     logger.removeAllAppenders();
107     logger.addAppender(appender2);
108     LOG4CPLUS_INFO(logger, "Foo");
109     ASSERT_EQ(1, buffer_appender2->getBufferSize());
110 }
111 
TEST_F(BufferAppenderTest,addDirectly)112 TEST_F(BufferAppenderTest, addDirectly) {
113     // A few direct calls
114     log4cplus::spi::InternalLoggingEvent event("buffer",
115                                                log4cplus::INFO_LOG_LEVEL,
116                                                "Bar", "file", 123);
117     buffer_appender1->addEvent(event);
118     ASSERT_EQ(1, buffer_appender1->getBufferSize());
119 
120     // Do one from a smaller scope to make sure destruction doesn't harm
121     {
122         log4cplus::spi::InternalLoggingEvent event2("buffer",
123                                                     log4cplus::INFO_LOG_LEVEL,
124                                                     "Bar", "file", 123);
125         buffer_appender1->addEvent(event2);
126     }
127     ASSERT_EQ(2, buffer_appender1->getBufferSize());
128 
129     // And flush them to the next
130     logger.removeAllAppenders();
131     logger.addAppender(appender2);
132     buffer_appender1->flush();
133     ASSERT_EQ(0, buffer_appender1->getBufferSize());
134     ASSERT_EQ(2, buffer_appender2->getBufferSize());
135 }
136 
137 }
138 }
139