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