OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 The Chromium 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 "chrome/test/base/test_log_collector_win.h" | |
6 | |
7 #include <windows.h> | |
8 | |
9 #include <algorithm> | |
10 #include <ios> // For std::hex | |
robertshield
2012/03/09 16:58:04
std::hex does not appear in this file.
grt (UTC plus 2)
2012/03/09 17:55:25
I never said it did. :-) The C++ spec says that
| |
11 | |
12 #include "base/command_line.h" | |
13 #include "base/compiler_specific.h" | |
14 #include "base/file_path.h" | |
15 #include "base/file_util.h" | |
16 #include "base/lazy_instance.h" | |
17 #include "base/logging.h" | |
18 #include "base/memory/scoped_ptr.h" | |
19 #include "base/scoped_temp_dir.h" | |
20 #include "base/stringprintf.h" | |
21 #include "chrome/test/base/file_logger_win.h" | |
22 #include "chrome/test/base/log_file_printer_win.h" | |
23 #include "chrome/test/base/test_switches.h" | |
24 #include "testing/gtest/include/gtest/gtest.h" | |
25 | |
26 namespace { | |
27 | |
28 const char kTraceLogExtension[] = ".etl"; | |
29 | |
30 class TestLogCollector { | |
31 public: | |
32 TestLogCollector(); | |
33 ~TestLogCollector(); | |
34 | |
35 void Initialize(testing::UnitTest* unit_test); | |
36 | |
37 void SetUp(); | |
38 void StartSessionForTest(const testing::TestInfo& test_info); | |
39 bool LogTestPartResult(const testing::TestPartResult& test_part_result); | |
40 void ProcessSessionForTest(const testing::TestInfo& test_info); | |
41 void TearDown(); | |
42 | |
43 private: | |
44 // An EventListener that generally delegates to a given default result | |
45 // printer with a few exceptions; see individual method comments for details. | |
46 class EventListener : public testing::TestEventListener { | |
47 public: | |
48 // Ownership of |default_result_printer| is taken by the new instance. | |
49 EventListener(TestLogCollector* test_log_collector, | |
50 testing::TestEventListener* default_result_printer); | |
51 virtual ~EventListener(); | |
52 | |
53 // Sets up the log collector. | |
54 virtual void OnTestProgramStart( | |
55 const testing::UnitTest& unit_test) OVERRIDE { | |
56 test_log_collector_->SetUp(); | |
57 default_result_printer_->OnTestProgramStart(unit_test); | |
58 } | |
59 | |
60 virtual void OnTestIterationStart(const testing::UnitTest& unit_test, | |
61 int iteration) OVERRIDE { | |
62 default_result_printer_->OnTestIterationStart(unit_test, iteration); | |
63 } | |
64 | |
65 virtual void OnEnvironmentsSetUpStart( | |
66 const testing::UnitTest& unit_test) OVERRIDE { | |
67 default_result_printer_->OnEnvironmentsSetUpStart(unit_test); | |
68 } | |
69 | |
70 virtual void OnEnvironmentsSetUpEnd( | |
71 const testing::UnitTest& unit_test) OVERRIDE { | |
72 default_result_printer_->OnEnvironmentsSetUpEnd(unit_test); | |
73 } | |
74 | |
75 virtual void OnTestCaseStart(const testing::TestCase& test_case) OVERRIDE { | |
76 default_result_printer_->OnTestCaseStart(test_case); | |
77 } | |
78 | |
79 // Calls back to the collector to start collecting logs for this test. | |
80 virtual void OnTestStart(const testing::TestInfo& test_info) OVERRIDE { | |
81 default_result_printer_->OnTestStart(test_info); | |
82 test_log_collector_->StartSessionForTest(test_info); | |
83 } | |
84 | |
85 // Calls back to the collector with the partial result. If the collector | |
86 // does not handle it, it is given to the default result printer. | |
87 virtual void OnTestPartResult( | |
88 const testing::TestPartResult& test_part_result) OVERRIDE { | |
89 if (!test_log_collector_->LogTestPartResult(test_part_result)) | |
90 default_result_printer_->OnTestPartResult(test_part_result); | |
91 } | |
92 | |
93 // Calls back to the collector to handle the collected log for the test that | |
94 // has just ended. | |
95 virtual void OnTestEnd(const testing::TestInfo& test_info) OVERRIDE { | |
96 test_log_collector_->ProcessSessionForTest(test_info); | |
97 default_result_printer_->OnTestEnd(test_info); | |
98 } | |
99 | |
100 virtual void OnTestCaseEnd(const testing::TestCase& test_case) OVERRIDE { | |
101 default_result_printer_->OnTestCaseEnd(test_case); | |
102 } | |
103 | |
104 virtual void OnEnvironmentsTearDownStart( | |
105 const testing::UnitTest& unit_test) OVERRIDE { | |
106 default_result_printer_->OnEnvironmentsTearDownStart(unit_test); | |
107 } | |
108 | |
109 virtual void OnEnvironmentsTearDownEnd( | |
110 const testing::UnitTest& unit_test) OVERRIDE { | |
111 default_result_printer_->OnEnvironmentsTearDownEnd(unit_test); | |
112 } | |
113 | |
114 virtual void OnTestIterationEnd(const testing::UnitTest& unit_test, | |
115 int iteration) OVERRIDE { | |
116 default_result_printer_->OnTestIterationEnd(unit_test, iteration); | |
117 } | |
118 | |
119 // Tears down the log collector. | |
120 virtual void OnTestProgramEnd(const testing::UnitTest& unit_test) OVERRIDE { | |
121 default_result_printer_->OnTestProgramEnd(unit_test); | |
122 test_log_collector_->TearDown(); | |
123 } | |
124 | |
125 private: | |
126 TestLogCollector* test_log_collector_; | |
127 scoped_ptr<testing::TestEventListener> default_result_printer_; | |
128 | |
129 DISALLOW_COPY_AND_ASSIGN(EventListener); | |
130 }; | |
131 | |
132 // The Google Test unit test into which the collector has been installed. | |
133 testing::UnitTest* unit_test_; | |
134 | |
135 // A temporary directory into which a log file is placed for the duration of | |
136 // each test. Created/destroyed at collector SetUp and TearDown. | |
137 ScopedTempDir log_temp_dir_; | |
138 | |
139 // The test logger. Initialized/Unintitialized at collector SetUp and | |
140 // TearDown. | |
141 FileLogger file_logger_; | |
142 | |
143 // The current log file. Valid only during a test. | |
144 FilePath log_file_; | |
145 | |
146 // True if --also-emit-success-logs was specified on the command line. | |
147 bool also_emit_success_logs_; | |
148 | |
149 DISALLOW_COPY_AND_ASSIGN(TestLogCollector); | |
150 }; | |
151 | |
152 base::LazyInstance<TestLogCollector> g_test_log_collector = | |
153 LAZY_INSTANCE_INITIALIZER; | |
154 | |
155 // TestLogCollector::EventListener implementation | |
156 | |
157 TestLogCollector::EventListener::EventListener( | |
158 TestLogCollector* test_log_collector, | |
159 testing::TestEventListener* default_result_printer) | |
160 : test_log_collector_(test_log_collector), | |
161 default_result_printer_(default_result_printer) { | |
162 } | |
163 | |
164 TestLogCollector::EventListener::~EventListener() { | |
165 } | |
166 | |
167 // TestLogCollector implementation | |
168 | |
169 TestLogCollector::TestLogCollector() | |
170 : unit_test_(NULL), also_emit_success_logs_(false) { | |
171 } | |
172 | |
173 TestLogCollector::~TestLogCollector() { | |
174 } | |
175 | |
176 void TestLogCollector::Initialize(testing::UnitTest* unit_test) { | |
177 if (unit_test_ != NULL) { | |
178 CHECK_EQ(unit_test, unit_test_) | |
179 << "Cannot install the test log collector in multiple unit tests."; | |
180 return; // Already initialized. | |
181 } | |
182 | |
183 // Remove the default result printer and install the collector's listener | |
184 // which delegates to the printer. If the default result printer has already | |
185 // been released, log an error and move on. | |
186 testing::TestEventListeners& listeners = unit_test->listeners(); | |
187 testing::TestEventListener* default_result_printer = | |
188 listeners.default_result_printer(); | |
189 if (default_result_printer == NULL) { | |
190 LOG(ERROR) << "Failed to initialize the test log collector on account of " | |
191 "another component having released the default result " | |
192 "printer."; | |
193 } else { | |
194 // Ownership of |default_release_printer| is passed to the new listener, and | |
195 // ownership of the new listener is passed to the unit test. | |
196 listeners.Append( | |
197 new EventListener(this, listeners.Release(default_result_printer))); | |
198 | |
199 also_emit_success_logs_ = CommandLine::ForCurrentProcess()->HasSwitch( | |
200 switches::kAlsoEmitSuccessLogs); | |
201 | |
202 unit_test_ = unit_test; | |
203 } | |
204 } | |
205 | |
206 // Invoked by the listener at test program start to create the temporary log | |
207 // directory and initialize the logger. | |
208 void TestLogCollector::SetUp() { | |
209 if (!log_temp_dir_.CreateUniqueTempDir()) { | |
210 LOG(ERROR) << "Failed to create temporary directory to hold log files."; | |
211 } else { | |
212 file_logger_.Initialize(); | |
213 } | |
214 } | |
215 | |
216 // Invoked by the listener at test start to begin collecting logs in a file. | |
217 void TestLogCollector::StartSessionForTest(const testing::TestInfo& test_info) { | |
218 if (log_temp_dir_.IsValid()) { | |
219 std::string log_file_name(test_info.name()); | |
220 std::replace(log_file_name.begin(), log_file_name.end(), '/', '_'); | |
221 log_file_name.append(kTraceLogExtension); | |
222 log_file_ = log_temp_dir_.path().AppendASCII(log_file_name); | |
223 | |
224 file_logger_.StartLogging(log_file_); | |
225 } | |
226 } | |
227 | |
228 // Invoked by the listener when a test result is produced to log an event for | |
229 // the result. | |
230 bool TestLogCollector::LogTestPartResult( | |
231 const testing::TestPartResult& test_part_result) { | |
232 // Can't handle the event if no trace session. | |
233 if (!file_logger_.is_logging()) | |
234 return false; | |
235 | |
236 if (test_part_result.type() != testing::TestPartResult::kSuccess) { | |
237 // Approximate Google Test's message formatting. | |
238 LOG(ERROR) | |
239 << base::StringPrintf("%s(%d): error: %s", test_part_result.file_name(), | |
240 test_part_result.line_number(), | |
241 test_part_result.message()); | |
242 } | |
243 return true; | |
244 } | |
245 | |
246 // Invoked by the listener at test end to dump the collected log in case of | |
247 // error. | |
248 void TestLogCollector::ProcessSessionForTest( | |
249 const testing::TestInfo& test_info) { | |
250 if (file_logger_.is_logging()) { | |
251 file_logger_.StopLogging(); | |
252 | |
253 if (also_emit_success_logs_ || test_info.result()->Failed()) { | |
254 std::cerr << "----- log messages for " | |
255 << test_info.test_case_name() << "." << test_info.name() | |
256 << " above this line are repeated below -----" << std::endl; | |
257 // Dump the log to stderr. | |
258 logging_win::PrintLogFile(log_file_, &std::cerr); | |
259 std::cerr.flush(); | |
260 } | |
261 | |
262 if (!file_util::Delete(log_file_, false)) | |
263 LOG(ERROR) << "Failed to delete log file " << log_file_.value(); | |
264 } | |
265 | |
266 log_file_.clear(); | |
267 } | |
268 | |
269 // Invoked by the listener at test program end to shut down the logger and | |
270 // delete the temporary log directory. | |
271 void TestLogCollector::TearDown() { | |
272 file_logger_.Uninitialize(); | |
273 | |
274 ignore_result(log_temp_dir_.Delete()); | |
275 } | |
276 | |
277 } // namespace | |
278 | |
279 void InstallTestLogCollector(testing::UnitTest* unit_test) { | |
280 // Must be called before running any tests. | |
281 DCHECK(unit_test); | |
282 DCHECK(!unit_test->current_test_case()); | |
283 | |
284 g_test_log_collector.Get().Initialize(unit_test); | |
285 } | |
OLD | NEW |