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

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

Powered by Google App Engine
This is Rietveld 408576698