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.
5 #include "chrome/test/logging/win/test_log_collector.h"
12 #include "base/command_line.h"
13 #include "base/compiler_specific.h"
14 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/files/scoped_temp_dir.h"
17 #include "base/lazy_instance.h"
18 #include "base/logging.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "base/strings/stringprintf.h"
21 #include "chrome/test/base/test_switches.h"
22 #include "chrome/test/logging/win/file_logger.h"
23 #include "chrome/test/logging/win/log_file_printer.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 namespace logging_win
{
30 const char kTraceLogExtension
[] = ".etl";
32 class TestLogCollector
{
37 void Initialize(testing::UnitTest
* unit_test
);
40 void StartSessionForTest(const testing::TestInfo
& test_info
);
41 bool LogTestPartResult(const testing::TestPartResult
& test_part_result
);
42 void ProcessSessionForTest(const testing::TestInfo
& test_info
);
46 // An EventListener that generally delegates to a given default result
47 // printer with a few exceptions; see individual method comments for details.
48 class EventListener
: public testing::TestEventListener
{
50 // Ownership of |default_result_printer| is taken by the new instance.
51 EventListener(TestLogCollector
* test_log_collector
,
52 testing::TestEventListener
* default_result_printer
);
53 virtual ~EventListener();
55 // Sets up the log collector.
56 virtual void OnTestProgramStart(
57 const testing::UnitTest
& unit_test
) OVERRIDE
{
58 test_log_collector_
->SetUp();
59 default_result_printer_
->OnTestProgramStart(unit_test
);
62 virtual void OnTestIterationStart(const testing::UnitTest
& unit_test
,
63 int iteration
) OVERRIDE
{
64 default_result_printer_
->OnTestIterationStart(unit_test
, iteration
);
67 virtual void OnEnvironmentsSetUpStart(
68 const testing::UnitTest
& unit_test
) OVERRIDE
{
69 default_result_printer_
->OnEnvironmentsSetUpStart(unit_test
);
72 virtual void OnEnvironmentsSetUpEnd(
73 const testing::UnitTest
& unit_test
) OVERRIDE
{
74 default_result_printer_
->OnEnvironmentsSetUpEnd(unit_test
);
77 virtual void OnTestCaseStart(const testing::TestCase
& test_case
) OVERRIDE
{
78 default_result_printer_
->OnTestCaseStart(test_case
);
81 // Calls back to the collector to start collecting logs for this test.
82 virtual void OnTestStart(const testing::TestInfo
& test_info
) OVERRIDE
{
83 default_result_printer_
->OnTestStart(test_info
);
84 test_log_collector_
->StartSessionForTest(test_info
);
87 // Calls back to the collector with the partial result. If the collector
88 // does not handle it, it is given to the default result printer.
89 virtual void OnTestPartResult(
90 const testing::TestPartResult
& test_part_result
) OVERRIDE
{
91 if (!test_log_collector_
->LogTestPartResult(test_part_result
))
92 default_result_printer_
->OnTestPartResult(test_part_result
);
95 // Calls back to the collector to handle the collected log for the test that
97 virtual void OnTestEnd(const testing::TestInfo
& test_info
) OVERRIDE
{
98 test_log_collector_
->ProcessSessionForTest(test_info
);
99 default_result_printer_
->OnTestEnd(test_info
);
102 virtual void OnTestCaseEnd(const testing::TestCase
& test_case
) OVERRIDE
{
103 default_result_printer_
->OnTestCaseEnd(test_case
);
106 virtual void OnEnvironmentsTearDownStart(
107 const testing::UnitTest
& unit_test
) OVERRIDE
{
108 default_result_printer_
->OnEnvironmentsTearDownStart(unit_test
);
111 virtual void OnEnvironmentsTearDownEnd(
112 const testing::UnitTest
& unit_test
) OVERRIDE
{
113 default_result_printer_
->OnEnvironmentsTearDownEnd(unit_test
);
116 virtual void OnTestIterationEnd(const testing::UnitTest
& unit_test
,
117 int iteration
) OVERRIDE
{
118 default_result_printer_
->OnTestIterationEnd(unit_test
, iteration
);
121 // Tears down the log collector.
122 virtual void OnTestProgramEnd(const testing::UnitTest
& unit_test
) OVERRIDE
{
123 default_result_printer_
->OnTestProgramEnd(unit_test
);
124 test_log_collector_
->TearDown();
128 TestLogCollector
* test_log_collector_
;
129 scoped_ptr
<testing::TestEventListener
> default_result_printer_
;
131 DISALLOW_COPY_AND_ASSIGN(EventListener
);
134 // The Google Test unit test into which the collector has been installed.
135 testing::UnitTest
* unit_test_
;
137 // A temporary directory into which a log file is placed for the duration of
138 // each test. Created/destroyed at collector SetUp and TearDown.
139 base::ScopedTempDir log_temp_dir_
;
141 // The test logger. Initialized/Unintitialized at collector SetUp and
143 scoped_ptr
<FileLogger
> file_logger_
;
145 // The current log file. Valid only during a test.
146 base::FilePath log_file_
;
148 // True if --also-emit-success-logs was specified on the command line.
149 bool also_emit_success_logs_
;
151 DISALLOW_COPY_AND_ASSIGN(TestLogCollector
);
154 base::LazyInstance
<TestLogCollector
> g_test_log_collector
=
155 LAZY_INSTANCE_INITIALIZER
;
157 // TestLogCollector::EventListener implementation
159 TestLogCollector::EventListener::EventListener(
160 TestLogCollector
* test_log_collector
,
161 testing::TestEventListener
* default_result_printer
)
162 : test_log_collector_(test_log_collector
),
163 default_result_printer_(default_result_printer
) {
166 TestLogCollector::EventListener::~EventListener() {
169 // TestLogCollector implementation
171 TestLogCollector::TestLogCollector()
172 : unit_test_(NULL
), also_emit_success_logs_(false) {
175 TestLogCollector::~TestLogCollector() {
178 void TestLogCollector::Initialize(testing::UnitTest
* unit_test
) {
179 if (unit_test_
!= NULL
) {
180 CHECK_EQ(unit_test
, unit_test_
)
181 << "Cannot install the test log collector in multiple unit tests.";
182 return; // Already initialized.
185 // Remove the default result printer and install the collector's listener
186 // which delegates to the printer. If the default result printer has already
187 // been released, log an error and move on.
188 testing::TestEventListeners
& listeners
= unit_test
->listeners();
189 testing::TestEventListener
* default_result_printer
=
190 listeners
.default_result_printer();
191 if (default_result_printer
== NULL
) {
192 LOG(ERROR
) << "Failed to initialize the test log collector on account of "
193 "another component having released the default result "
196 // Ownership of |default_release_printer| is passed to the new listener, and
197 // ownership of the new listener is passed to the unit test.
199 new EventListener(this, listeners
.Release(default_result_printer
)));
201 also_emit_success_logs_
= CommandLine::ForCurrentProcess()->HasSwitch(
202 switches::kAlsoEmitSuccessLogs
);
204 unit_test_
= unit_test
;
208 // Invoked by the listener at test program start to create the temporary log
209 // directory and initialize the logger.
210 void TestLogCollector::SetUp() {
211 if (!log_temp_dir_
.CreateUniqueTempDir()) {
212 LOG(ERROR
) << "Failed to create temporary directory to hold log files.";
214 file_logger_
.reset(new FileLogger());
215 file_logger_
->Initialize();
219 // Invoked by the listener at test start to begin collecting logs in a file.
220 void TestLogCollector::StartSessionForTest(const testing::TestInfo
& test_info
) {
221 if (log_temp_dir_
.IsValid()) {
222 std::string
log_file_name(test_info
.name());
223 std::replace(log_file_name
.begin(), log_file_name
.end(), '/', '_');
224 log_file_name
.append(kTraceLogExtension
);
225 log_file_
= log_temp_dir_
.path().AppendASCII(log_file_name
);
227 file_logger_
->StartLogging(log_file_
);
231 // Invoked by the listener when a test result is produced to log an event for
233 bool TestLogCollector::LogTestPartResult(
234 const testing::TestPartResult
& test_part_result
) {
235 // Can't handle the event if no trace session.
236 if (!file_logger_
.get() || !file_logger_
->is_logging())
239 if (test_part_result
.type() != testing::TestPartResult::kSuccess
) {
240 // Approximate Google Test's message formatting.
242 << base::StringPrintf("%s(%d): error: %s", test_part_result
.file_name(),
243 test_part_result
.line_number(),
244 test_part_result
.message());
249 // Invoked by the listener at test end to dump the collected log in case of
251 void TestLogCollector::ProcessSessionForTest(
252 const testing::TestInfo
& test_info
) {
253 if (file_logger_
.get() != NULL
&& file_logger_
->is_logging()) {
254 file_logger_
->StopLogging();
256 if (also_emit_success_logs_
|| test_info
.result()->Failed()) {
257 std::cerr
<< "----- log messages for "
258 << test_info
.test_case_name() << "." << test_info
.name()
259 << " above this line are repeated below -----" << std::endl
;
260 // Dump the log to stderr.
261 logging_win::PrintLogFile(log_file_
, &std::cerr
);
265 if (!base::DeleteFile(log_file_
, false))
266 LOG(ERROR
) << "Failed to delete log file " << log_file_
.value();
272 // Invoked by the listener at test program end to shut down the logger and
273 // delete the temporary log directory.
274 void TestLogCollector::TearDown() {
275 file_logger_
.reset();
277 ignore_result(log_temp_dir_
.Delete());
282 void InstallTestLogCollector(testing::UnitTest
* unit_test
) {
283 // Must be called before running any tests.
285 DCHECK(!unit_test
->current_test_case());
287 g_test_log_collector
.Get().Initialize(unit_test
);
290 } // namespace logging_win