blob: 016c0368c0e90a2d9a3e160df5ea6fcd4f46888d [file] [log] [blame]
Christopher Wiley5781aa42012-07-30 14:42:23 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <deque>
6#include <string>
7
8#include <base/file_util.h>
9#include <base/logging.h>
10#include <base/scoped_temp_dir.h>
11#include <gmock/gmock.h>
12#include <gtest/gtest.h>
13
14#include "shill/memory_log.h"
15#include "shill/mock_log.h"
16#include "shill/scope_logger.h"
17
18using testing::_;
19
20namespace {
Christopher Wiley5781aa42012-07-30 14:42:23 -070021
Christopher Wileyf11cebb2012-08-08 12:22:20 -070022const char kTestStr1[] = "What does Mr Wallace look like?";
23const char kTestStr2[] = "And now little man, I give the watch to you.";
24const char kTestStr3[] = "This is a tasty burger!";
25const char kTestStr1WithPrefix[] = "memlog: What does Mr Wallace look like?";
26const char kTestStr2WithPrefix[] =
27 "memlog: And now little man, I give the watch to you.";
28const char kTestStr3WithPrefix[] = "memlog: This is a tasty burger!";
29
30} // namespace
Christopher Wiley5781aa42012-07-30 14:42:23 -070031
32namespace shill {
33
34class MemoryLogTest : public testing::Test {
35 protected:
36 void TearDown() {
37 // Restore everything to defaults once more.
38 MemoryLog::GetInstance()->Clear();
39 MemoryLog::GetInstance()->SetMaximumSize(
40 MemoryLog::kDefaultMaximumMemoryLogSizeInBytes);
41 ScopeLogger::GetInstance()->set_verbose_level(0);
42 ScopeLogger::GetInstance()->EnableScopesByName("");
43 ::logging::SetMinLogLevel(logging::LOG_INFO);
44 }
45};
46
47TEST_F(MemoryLogTest, ScopedLoggerStillWorks) {
48 ScopedMockLog log;
Christopher Wileyf11cebb2012-08-08 12:22:20 -070049 EXPECT_CALL(log, Log(_, _, kTestStr1WithPrefix));
50 EXPECT_CALL(log, Log(_, _, kTestStr2WithPrefix));
Christopher Wiley5781aa42012-07-30 14:42:23 -070051 SMLOG(WiFi, 2) << "does not get through";
52 ScopeLogger::GetInstance()->EnableScopesByName("+wifi");
53 // Verbose levels are inverted.
54 ScopeLogger::GetInstance()->set_verbose_level(3);
55 SMLOG(WiFi, 2) << kTestStr1;
56 // It would be nice if the compiler didn't optimize out my conditional check.
57 SMLOG_IF(WiFi, 3, strlen("two") == 3) << kTestStr2;
58 SMLOG_IF(WiFi, 3, strlen("one") == 2) << "does not get through again";
59 SMLOG(WiFi, 4) << "spanish inquisition";
60}
61
62TEST_F(MemoryLogTest, NormalLoggingStillWorks) {
63 ::logging::SetMinLogLevel(logging::LOG_WARNING);
64 ScopedMockLog log;
Christopher Wileyf11cebb2012-08-08 12:22:20 -070065 EXPECT_CALL(log, Log(_, _, kTestStr1WithPrefix));
66 EXPECT_CALL(log, Log(_, _, kTestStr2WithPrefix));
Christopher Wiley5781aa42012-07-30 14:42:23 -070067 MLOG(ERROR) << kTestStr1;
68 MLOG(INFO) << "does not propagate down";
69 // It would be nice if the compiler didn't optimize out my conditional check.
70 MLOG_IF(WARNING, strlen("two") == 3) << kTestStr2;
71}
72
73TEST_F(MemoryLogTest, MemoryLogIsLogging) {
74 ScopedMockLog log;
Christopher Wileyf11cebb2012-08-08 12:22:20 -070075 EXPECT_CALL(log, Log(_, _, kTestStr1WithPrefix));
76 EXPECT_CALL(log, Log(_, _, kTestStr2WithPrefix));
Christopher Wiley5781aa42012-07-30 14:42:23 -070077 ::logging::SetMinLogLevel(logging::LOG_WARNING);
78 ASSERT_EQ(0, MemoryLog::GetInstance()->current_size_bytes());
79 MLOG(WARNING) << kTestStr1;
80 MLOG(WARNING) << kTestStr2;
81 // LT because of the prefixes prepended by the logger
Christopher Wileyf11cebb2012-08-08 12:22:20 -070082 ASSERT_LT(strlen(kTestStr1WithPrefix) + strlen(kTestStr2WithPrefix),
Christopher Wiley5781aa42012-07-30 14:42:23 -070083 MemoryLog::GetInstance()->current_size_bytes());
84 ASSERT_EQ(2, MemoryLog::GetInstance()->TestGetNumberMessages());
85 MemoryLog::GetInstance()->Clear();
86 ASSERT_EQ(0, MemoryLog::GetInstance()->current_size_bytes());
87 ASSERT_EQ(0, MemoryLog::GetInstance()->TestGetNumberMessages());
88}
89
90TEST_F(MemoryLogTest, MemoryLogLimitingWorks) {
91 ScopedMockLog log;
92 ::logging::SetMinLogLevel(logging::LOG_WARNING);
93 MLOG(INFO) << kTestStr1;
94 size_t old_size = MemoryLog::GetInstance()->current_size_bytes();
95 MLOG(INFO) << kTestStr2;
96 size_t new_size = MemoryLog::GetInstance()->current_size_bytes();
97 // Setting the size just above the current size shouldn't affect anything.
98 MemoryLog::GetInstance()->SetMaximumSize(new_size + 1);
99 ASSERT_EQ(new_size, MemoryLog::GetInstance()->current_size_bytes());
100 // Force MemoryLog to discard the earliest message
101 MemoryLog::GetInstance()->SetMaximumSize(new_size - 1);
102 // Should be just last message in the buffer.
103 ASSERT_EQ(new_size - old_size,
104 MemoryLog::GetInstance()->current_size_bytes());
105 // Now force it to discard the most recent message.
106 MemoryLog::GetInstance()->SetMaximumSize(0);
107 ASSERT_EQ(0, MemoryLog::GetInstance()->current_size_bytes());
108 // Can't log if we don't have room, but the messages should still get to LOG
Christopher Wileyf11cebb2012-08-08 12:22:20 -0700109 EXPECT_CALL(log, Log(_, _, kTestStr3WithPrefix));
Christopher Wiley5781aa42012-07-30 14:42:23 -0700110 MLOG(WARNING) << kTestStr3;
111 ASSERT_EQ(0, MemoryLog::GetInstance()->current_size_bytes());
112 ASSERT_EQ(0, MemoryLog::GetInstance()->TestGetNumberMessages());
113}
114
115TEST_F(MemoryLogTest, MemoryLogFlushToDiskWorks) {
116 ScopedTempDir temp_dir;
117 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
118 FilePath test_path = temp_dir.path().Append("somelogfile");
119 ::logging::SetMinLogLevel(logging::LOG_WARNING);
120 MLOG(INFO) << kTestStr1;
121 MLOG(INFO) << kTestStr2;
122 MLOG(INFO) << kTestStr3;
123 ASSERT_EQ(3, MemoryLog::GetInstance()->TestGetNumberMessages());
124 // Because of all the prefixed metadata on each log message, the stuff sent to
125 // disk should be bigger than the original strings put together.
Christopher Wileyf11cebb2012-08-08 12:22:20 -0700126 size_t minimal_message_length = strlen(kTestStr1WithPrefix) +
127 strlen(kTestStr2WithPrefix) + strlen(kTestStr3WithPrefix);
128 ASSERT_LT(minimal_message_length,
Christopher Wiley5781aa42012-07-30 14:42:23 -0700129 MemoryLog::GetInstance()->FlushToDisk(test_path.value().c_str()));
130 std::string file_contents;
131 ASSERT_TRUE(file_util::ReadFileToString(test_path, &file_contents));
132 // Log should contain all three messages
Christopher Wileyf11cebb2012-08-08 12:22:20 -0700133 ASSERT_NE(file_contents.find(kTestStr1WithPrefix), std::string::npos);
134 ASSERT_NE(file_contents.find(kTestStr2WithPrefix), std::string::npos);
135 ASSERT_NE(file_contents.find(kTestStr3WithPrefix), std::string::npos);
Christopher Wiley5781aa42012-07-30 14:42:23 -0700136 // Preserve message order
Christopher Wileyf11cebb2012-08-08 12:22:20 -0700137 ASSERT_LT(file_contents.find(kTestStr1WithPrefix),
138 file_contents.find(kTestStr2WithPrefix));
139 ASSERT_LT(file_contents.find(kTestStr2WithPrefix),
140 file_contents.find(kTestStr3WithPrefix));
Christopher Wiley5781aa42012-07-30 14:42:23 -0700141 ASSERT_TRUE(temp_dir.Delete());
142}
143
Christopher Wileyf11cebb2012-08-08 12:22:20 -0700144TEST_F(MemoryLogTest, MemoryLogMessageInterceptorWorks) {
145 ASSERT_EQ(0, MemoryLog::GetInstance()->TestGetNumberMessages());
146 NOTIMPLEMENTED();
147 ASSERT_EQ(0, MemoryLog::GetInstance()->TestGetNumberMessages());
148 MemoryLog::InstallLogInterceptor();
149 NOTIMPLEMENTED();
150 ASSERT_EQ(1, MemoryLog::GetInstance()->TestGetNumberMessages());
151 // Make sure we're not double logging.
152 MLOG(ERROR) << kTestStr1;
153 ASSERT_EQ(2, MemoryLog::GetInstance()->TestGetNumberMessages());
154 // SMLOG_IF works with the intercepting handler.
155 SMLOG_IF(WiFi, 3, strlen("two") == 3) << kTestStr2;
156 ASSERT_EQ(3, MemoryLog::GetInstance()->TestGetNumberMessages());
157 SMLOG_IF(WiFi, 3, strlen("one") == 2) << "does not get through again";
158 ASSERT_EQ(3, MemoryLog::GetInstance()->TestGetNumberMessages());
159 // Similarly, MLOG_IF works with the handler.
160 MLOG_IF(ERROR, strlen("two") == 3) << kTestStr2;
161 ASSERT_EQ(4, MemoryLog::GetInstance()->TestGetNumberMessages());
162 MLOG_IF(ERROR, strlen("one") == 2) << "does not get through again";
163 ASSERT_EQ(4, MemoryLog::GetInstance()->TestGetNumberMessages());
164 MemoryLog::UninstallLogInterceptor();
165 NOTIMPLEMENTED();
166 ASSERT_EQ(4, MemoryLog::GetInstance()->TestGetNumberMessages());
167 // Normal log messages still get through.
168 MLOG(ERROR) << kTestStr2;
169 ASSERT_EQ(5, MemoryLog::GetInstance()->TestGetNumberMessages());
170}
171
Christopher Wiley5781aa42012-07-30 14:42:23 -0700172} // namespace shill