Home | History | Annotate | Download | only in win
      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/files/file_path.h"
     15 #include "base/files/file_util.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"
     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   base::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   base::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 (!base::DeleteFile(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
    291