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