Home | History | Annotate | Download | only in diagnostics
      1 // Copyright 2013 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/browser/diagnostics/diagnostics_controller.h"
      6 
      7 #include "base/command_line.h"
      8 #include "base/file_util.h"
      9 #include "base/files/scoped_temp_dir.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/path_service.h"
     12 #include "chrome/browser/diagnostics/diagnostics_model.h"
     13 #include "chrome/browser/diagnostics/diagnostics_writer.h"
     14 #include "chrome/browser/diagnostics/sqlite_diagnostics.h"
     15 #include "chrome/common/chrome_paths.h"
     16 #include "chrome/common/chrome_switches.h"
     17 #include "chromeos/chromeos_constants.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 namespace diagnostics {
     21 
     22 // Basic harness to acquire and release the required temporary environment to
     23 // run a test in.
     24 class DiagnosticsControllerTest : public testing::Test {
     25  protected:
     26   DiagnosticsControllerTest() : cmdline_(CommandLine::NO_PROGRAM) {}
     27 
     28   virtual ~DiagnosticsControllerTest() {}
     29 
     30   virtual void SetUp() {
     31     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     32     base::FilePath test_data;
     33     PathService::Get(chrome::DIR_TEST_DATA, &test_data);
     34     test_data = test_data.Append(FILE_PATH_LITERAL("diagnostics"));
     35     test_data = test_data.Append(FILE_PATH_LITERAL("user"));
     36     base::CopyDirectory(test_data, temp_dir_.path(), true);
     37     profile_dir_ = temp_dir_.path().Append(FILE_PATH_LITERAL("user"));
     38 
     39 #if defined(OS_CHROMEOS)
     40     // Redirect the home dir to the profile directory. We have to do this
     41     // because NSS uses the HOME directory to find where to store it's database,
     42     // so that's where the diagnostics and recovery code looks for it.
     43 
     44     // Preserve existing home directory setting, if any.
     45     const char* old_home_dir = ::getenv("HOME");
     46     if (old_home_dir)
     47       old_home_dir_ = old_home_dir;
     48     else
     49       old_home_dir_.clear();
     50     ::setenv("HOME", profile_dir_.value().c_str(), 1);
     51 #endif
     52 
     53     cmdline_ = CommandLine(CommandLine::NO_PROGRAM);
     54     cmdline_.AppendSwitchPath(switches::kUserDataDir, profile_dir_);
     55     cmdline_.AppendSwitch(switches::kDiagnostics);
     56     cmdline_.AppendSwitch(switches::kDiagnosticsRecovery);
     57     writer_.reset();
     58     // Use this writer instead, if you want to see the diagnostics output.
     59     // writer_.reset(new DiagnosticsWriter(DiagnosticsWriter::MACHINE));
     60   }
     61 
     62   virtual void TearDown() {
     63     DiagnosticsController::GetInstance()->ClearResults();
     64 #if defined(OS_CHROMEOS)
     65     if (!old_home_dir_.empty()) {
     66       ::setenv("HOME", old_home_dir_.c_str(), 1);
     67     } else {
     68       ::unsetenv("HOME");
     69     }
     70     old_home_dir_.clear();
     71 #endif
     72   }
     73 
     74   void CorruptDataFile(const base::FilePath& path) {
     75     // Just write some random characters into the file tInvaludUsero "corrupt"
     76     // it.
     77     const char bogus_data[] = "wwZ2uNYNuyUVzFbDm3DL";
     78     file_util::WriteFile(path, bogus_data, arraysize(bogus_data));
     79   }
     80 
     81   scoped_ptr<DiagnosticsModel> model_;
     82   CommandLine cmdline_;
     83   base::ScopedTempDir temp_dir_;
     84   scoped_ptr<DiagnosticsWriter> writer_;
     85   base::FilePath profile_dir_;
     86 
     87 #if defined(OS_CHROMEOS)
     88   std::string old_home_dir_;
     89 #endif
     90 
     91   DISALLOW_COPY_AND_ASSIGN(DiagnosticsControllerTest);
     92 };
     93 
     94 TEST_F(DiagnosticsControllerTest, Diagnostics) {
     95   DiagnosticsController::GetInstance()->Run(cmdline_, writer_.get());
     96   EXPECT_TRUE(DiagnosticsController::GetInstance()->HasResults());
     97   const DiagnosticsModel& results =
     98       DiagnosticsController::GetInstance()->GetResults();
     99   EXPECT_EQ(results.GetTestRunCount(), results.GetTestAvailableCount());
    100   EXPECT_EQ(DiagnosticsModel::kDiagnosticsTestCount, results.GetTestRunCount());
    101   for (int i = 0; i < results.GetTestRunCount(); ++i) {
    102     const DiagnosticsModel::TestInfo& info(results.GetTest(i));
    103     EXPECT_EQ(DiagnosticsModel::TEST_OK, info.GetResult()) << "Test: "
    104                                                            << info.GetName();
    105   }
    106 }
    107 
    108 TEST_F(DiagnosticsControllerTest, RecoverAllOK) {
    109   DiagnosticsController::GetInstance()->Run(cmdline_, writer_.get());
    110   DiagnosticsController::GetInstance()->RunRecovery(cmdline_, writer_.get());
    111   EXPECT_TRUE(DiagnosticsController::GetInstance()->HasResults());
    112   const DiagnosticsModel& results =
    113       DiagnosticsController::GetInstance()->GetResults();
    114   EXPECT_EQ(results.GetTestRunCount(), results.GetTestAvailableCount());
    115   EXPECT_EQ(DiagnosticsModel::kDiagnosticsTestCount, results.GetTestRunCount());
    116   for (int i = 0; i < results.GetTestRunCount(); ++i) {
    117     const DiagnosticsModel::TestInfo& info(results.GetTest(i));
    118     EXPECT_EQ(DiagnosticsModel::RECOVERY_OK, info.GetResult())
    119         << "Test: " << info.GetName();
    120   }
    121 }
    122 
    123 #if defined(OS_CHROMEOS)
    124 TEST_F(DiagnosticsControllerTest, RecoverFromNssCertDbFailure) {
    125   base::FilePath db_path = profile_dir_.Append(chromeos::kNssCertDbPath);
    126   EXPECT_TRUE(base::PathExists(db_path));
    127   CorruptDataFile(db_path);
    128   DiagnosticsController::GetInstance()->Run(cmdline_, writer_.get());
    129   ASSERT_TRUE(DiagnosticsController::GetInstance()->HasResults());
    130   const DiagnosticsModel& results =
    131       DiagnosticsController::GetInstance()->GetResults();
    132   EXPECT_EQ(results.GetTestRunCount(), results.GetTestAvailableCount());
    133   EXPECT_EQ(DiagnosticsModel::kDiagnosticsTestCount, results.GetTestRunCount());
    134 
    135   const DiagnosticsModel::TestInfo* info = NULL;
    136   EXPECT_TRUE(
    137       results.GetTestInfo(DIAGNOSTICS_SQLITE_INTEGRITY_NSS_CERT_TEST, &info));
    138   EXPECT_EQ(DiagnosticsModel::TEST_FAIL_CONTINUE, info->GetResult());
    139   EXPECT_EQ(DIAG_SQLITE_ERROR_HANDLER_CALLED, info->GetOutcomeCode());
    140 
    141   DiagnosticsController::GetInstance()->RunRecovery(cmdline_, writer_.get());
    142   EXPECT_EQ(DiagnosticsModel::RECOVERY_OK, info->GetResult());
    143   EXPECT_FALSE(base::PathExists(db_path));
    144 }
    145 
    146 TEST_F(DiagnosticsControllerTest, RecoverFromNssKeyDbFailure) {
    147   base::FilePath db_path = profile_dir_.Append(chromeos::kNssKeyDbPath);
    148   EXPECT_TRUE(base::PathExists(db_path));
    149   CorruptDataFile(db_path);
    150   DiagnosticsController::GetInstance()->Run(cmdline_, writer_.get());
    151   ASSERT_TRUE(DiagnosticsController::GetInstance()->HasResults());
    152   const DiagnosticsModel& results =
    153       DiagnosticsController::GetInstance()->GetResults();
    154   EXPECT_EQ(results.GetTestRunCount(), results.GetTestAvailableCount());
    155   EXPECT_EQ(DiagnosticsModel::kDiagnosticsTestCount, results.GetTestRunCount());
    156 
    157   const DiagnosticsModel::TestInfo* info = NULL;
    158   EXPECT_TRUE(
    159       results.GetTestInfo(DIAGNOSTICS_SQLITE_INTEGRITY_NSS_KEY_TEST, &info));
    160   EXPECT_EQ(DiagnosticsModel::TEST_FAIL_CONTINUE, info->GetResult());
    161   EXPECT_EQ(DIAG_SQLITE_ERROR_HANDLER_CALLED, info->GetOutcomeCode());
    162 
    163   DiagnosticsController::GetInstance()->RunRecovery(cmdline_, writer_.get());
    164   EXPECT_EQ(DiagnosticsModel::RECOVERY_OK, info->GetResult());
    165   EXPECT_FALSE(base::PathExists(db_path));
    166 }
    167 #endif
    168 
    169 }  // namespace diagnostics
    170