Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: chrome/test/base/test_log_collector_win.cc

Issue 9584017: New test infrastructure for producing verbose logs in failing tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tweaked comments Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698