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/logging/win/test_log_collector.h" |
| 6 |
| 7 #include <windows.h> |
| 8 |
| 9 #include <algorithm> |
| 10 #include <ios> |
| 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/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" |
| 25 |
| 26 namespace logging_win { |
| 27 |
| 28 namespace { |
| 29 |
| 30 const char kTraceLogExtension[] = ".etl"; |
| 31 |
| 32 class TestLogCollector { |
| 33 public: |
| 34 TestLogCollector(); |
| 35 ~TestLogCollector(); |
| 36 |
| 37 void Initialize(testing::UnitTest* unit_test); |
| 38 |
| 39 void SetUp(); |
| 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); |
| 43 void TearDown(); |
| 44 |
| 45 private: |
| 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 { |
| 49 public: |
| 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(); |
| 54 |
| 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); |
| 60 } |
| 61 |
| 62 virtual void OnTestIterationStart(const testing::UnitTest& unit_test, |
| 63 int iteration) OVERRIDE { |
| 64 default_result_printer_->OnTestIterationStart(unit_test, iteration); |
| 65 } |
| 66 |
| 67 virtual void OnEnvironmentsSetUpStart( |
| 68 const testing::UnitTest& unit_test) OVERRIDE { |
| 69 default_result_printer_->OnEnvironmentsSetUpStart(unit_test); |
| 70 } |
| 71 |
| 72 virtual void OnEnvironmentsSetUpEnd( |
| 73 const testing::UnitTest& unit_test) OVERRIDE { |
| 74 default_result_printer_->OnEnvironmentsSetUpEnd(unit_test); |
| 75 } |
| 76 |
| 77 virtual void OnTestCaseStart(const testing::TestCase& test_case) OVERRIDE { |
| 78 default_result_printer_->OnTestCaseStart(test_case); |
| 79 } |
| 80 |
| 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); |
| 85 } |
| 86 |
| 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); |
| 93 } |
| 94 |
| 95 // Calls back to the collector to handle the collected log for the test that |
| 96 // has just ended. |
| 97 virtual void OnTestEnd(const testing::TestInfo& test_info) OVERRIDE { |
| 98 test_log_collector_->ProcessSessionForTest(test_info); |
| 99 default_result_printer_->OnTestEnd(test_info); |
| 100 } |
| 101 |
| 102 virtual void OnTestCaseEnd(const testing::TestCase& test_case) OVERRIDE { |
| 103 default_result_printer_->OnTestCaseEnd(test_case); |
| 104 } |
| 105 |
| 106 virtual void OnEnvironmentsTearDownStart( |
| 107 const testing::UnitTest& unit_test) OVERRIDE { |
| 108 default_result_printer_->OnEnvironmentsTearDownStart(unit_test); |
| 109 } |
| 110 |
| 111 virtual void OnEnvironmentsTearDownEnd( |
| 112 const testing::UnitTest& unit_test) OVERRIDE { |
| 113 default_result_printer_->OnEnvironmentsTearDownEnd(unit_test); |
| 114 } |
| 115 |
| 116 virtual void OnTestIterationEnd(const testing::UnitTest& unit_test, |
| 117 int iteration) OVERRIDE { |
| 118 default_result_printer_->OnTestIterationEnd(unit_test, iteration); |
| 119 } |
| 120 |
| 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(); |
| 125 } |
| 126 |
| 127 private: |
| 128 TestLogCollector* test_log_collector_; |
| 129 scoped_ptr<testing::TestEventListener> default_result_printer_; |
| 130 |
| 131 DISALLOW_COPY_AND_ASSIGN(EventListener); |
| 132 }; |
| 133 |
| 134 // The Google Test unit test into which the collector has been installed. |
| 135 testing::UnitTest* unit_test_; |
| 136 |
| 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 ScopedTempDir log_temp_dir_; |
| 140 |
| 141 // The test logger. Initialized/Unintitialized at collector SetUp and |
| 142 // TearDown. |
| 143 scoped_ptr<FileLogger> file_logger_; |
| 144 |
| 145 // The current log file. Valid only during a test. |
| 146 FilePath log_file_; |
| 147 |
| 148 // True if --also-emit-success-logs was specified on the command line. |
| 149 bool also_emit_success_logs_; |
| 150 |
| 151 DISALLOW_COPY_AND_ASSIGN(TestLogCollector); |
| 152 }; |
| 153 |
| 154 base::LazyInstance<TestLogCollector> g_test_log_collector = |
| 155 LAZY_INSTANCE_INITIALIZER; |
| 156 |
| 157 // TestLogCollector::EventListener implementation |
| 158 |
| 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) { |
| 164 } |
| 165 |
| 166 TestLogCollector::EventListener::~EventListener() { |
| 167 } |
| 168 |
| 169 // TestLogCollector implementation |
| 170 |
| 171 TestLogCollector::TestLogCollector() |
| 172 : unit_test_(NULL), also_emit_success_logs_(false) { |
| 173 } |
| 174 |
| 175 TestLogCollector::~TestLogCollector() { |
| 176 } |
| 177 |
| 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. |
| 183 } |
| 184 |
| 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 " |
| 194 "printer."; |
| 195 } else { |
| 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. |
| 198 listeners.Append( |
| 199 new EventListener(this, listeners.Release(default_result_printer))); |
| 200 |
| 201 also_emit_success_logs_ = CommandLine::ForCurrentProcess()->HasSwitch( |
| 202 switches::kAlsoEmitSuccessLogs); |
| 203 |
| 204 unit_test_ = unit_test; |
| 205 } |
| 206 } |
| 207 |
| 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."; |
| 213 } else { |
| 214 file_logger_.reset(new FileLogger()); |
| 215 file_logger_->Initialize(); |
| 216 } |
| 217 } |
| 218 |
| 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); |
| 226 |
| 227 file_logger_->StartLogging(log_file_); |
| 228 } |
| 229 } |
| 230 |
| 231 // Invoked by the listener when a test result is produced to log an event for |
| 232 // the result. |
| 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()) |
| 237 return false; |
| 238 |
| 239 if (test_part_result.type() != testing::TestPartResult::kSuccess) { |
| 240 // Approximate Google Test's message formatting. |
| 241 LOG(ERROR) |
| 242 << base::StringPrintf("%s(%d): error: %s", test_part_result.file_name(), |
| 243 test_part_result.line_number(), |
| 244 test_part_result.message()); |
| 245 } |
| 246 return true; |
| 247 } |
| 248 |
| 249 // Invoked by the listener at test end to dump the collected log in case of |
| 250 // error. |
| 251 void TestLogCollector::ProcessSessionForTest( |
| 252 const testing::TestInfo& test_info) { |
| 253 if (file_logger_.get() != NULL && file_logger_->is_logging()) { |
| 254 file_logger_->StopLogging(); |
| 255 |
| 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); |
| 262 std::cerr.flush(); |
| 263 } |
| 264 |
| 265 if (!file_util::Delete(log_file_, false)) |
| 266 LOG(ERROR) << "Failed to delete log file " << log_file_.value(); |
| 267 } |
| 268 |
| 269 log_file_.clear(); |
| 270 } |
| 271 |
| 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(); |
| 276 |
| 277 ignore_result(log_temp_dir_.Delete()); |
| 278 } |
| 279 |
| 280 } // namespace |
| 281 |
| 282 void InstallTestLogCollector(testing::UnitTest* unit_test) { |
| 283 // Must be called before running any tests. |
| 284 DCHECK(unit_test); |
| 285 DCHECK(!unit_test->current_test_case()); |
| 286 |
| 287 g_test_log_collector.Get().Initialize(unit_test); |
| 288 } |
| 289 |
| 290 } // namespace logging_win |
OLD | NEW |