diagnostics_log_controller_unittest.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. // Copyright 2022 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. #include "ash/system/diagnostics/diagnostics_log_controller.h"
  5. #include <memory>
  6. #include <string>
  7. #include <vector>
  8. #include "ash/constants/ash_features.h"
  9. #include "ash/public/cpp/session/session_types.h"
  10. #include "ash/session/session_controller_impl.h"
  11. #include "ash/shell.h"
  12. #include "ash/system/diagnostics/diagnostics_browser_delegate.h"
  13. #include "ash/system/diagnostics/log_test_helpers.h"
  14. #include "ash/system/diagnostics/networking_log.h"
  15. #include "ash/system/diagnostics/routine_log.h"
  16. #include "ash/system/diagnostics/telemetry_log.h"
  17. #include "ash/test/ash_test_base.h"
  18. #include "ash/webui/diagnostics_ui/mojom/network_health_provider.mojom-forward.h"
  19. #include "ash/webui/diagnostics_ui/mojom/network_health_provider.mojom-shared.h"
  20. #include "base/files/file_path.h"
  21. #include "base/files/file_util.h"
  22. #include "base/files/scoped_temp_dir.h"
  23. #include "base/test/scoped_feature_list.h"
  24. #include "components/user_manager/user_type.h"
  25. #include "testing/gtest/include/gtest/gtest.h"
  26. namespace ash {
  27. namespace diagnostics {
  28. namespace {
  29. const char kTestSessionLogFileName[] = "test_session_log.txt";
  30. const char kDiangosticsDirName[] = "diagnostics";
  31. const char kDefaultUserDir[] = "/fake/user-dir";
  32. const char kTmpDiagnosticsDir[] = "/tmp/diagnostics";
  33. const char kTestUserEmail[] = "test-user@gmail.com";
  34. const char kFakeUserDir[] = "fake-user";
  35. // Log headers content.
  36. const char kRoutineLogSubsectionHeader[] = "--- Test Routines ---";
  37. const char kSystemLogSectionHeader[] = "=== System ===";
  38. const char kNetworkingLogSectionHeader[] = "=== Networking ===";
  39. const char kNetworkingLogNetworkInfoHeader[] = "--- Network Info ---";
  40. const char kNetworkingLogNetworkEventsHeader[] = "--- Network Events ---";
  41. // Fake delegate used to set the expected user directory path.
  42. class FakeDiagnosticsBrowserDelegate : public DiagnosticsBrowserDelegate {
  43. public:
  44. explicit FakeDiagnosticsBrowserDelegate(
  45. const base::FilePath path = base::FilePath(kDefaultUserDir))
  46. : active_user_dir_(path) {}
  47. ~FakeDiagnosticsBrowserDelegate() override = default;
  48. base::FilePath GetActiveUserProfileDir() override { return active_user_dir_; }
  49. private:
  50. base::FilePath active_user_dir_;
  51. };
  52. } // namespace
  53. class DiagnosticsLogControllerTest : public NoSessionAshTestBase {
  54. public:
  55. DiagnosticsLogControllerTest() = default;
  56. DiagnosticsLogControllerTest(DiagnosticsLogControllerTest&) = delete;
  57. DiagnosticsLogControllerTest& operator=(DiagnosticsLogControllerTest&) =
  58. delete;
  59. ~DiagnosticsLogControllerTest() override = default;
  60. void SetUp() override {
  61. feature_list_.InitAndEnableFeature(
  62. ash::features::kEnableLogControllerForDiagnosticsApp);
  63. NoSessionAshTestBase::SetUp();
  64. }
  65. protected:
  66. base::FilePath GetSessionLogPath() {
  67. EXPECT_TRUE(save_dir_.CreateUniqueTempDir());
  68. return save_dir_.GetPath().Append(kTestSessionLogFileName);
  69. }
  70. void ResetLogBasePath() {
  71. return DiagnosticsLogController::Get()->ResetLogBasePath();
  72. }
  73. base::FilePath log_base_path() {
  74. return DiagnosticsLogController::Get()->log_base_path_;
  75. }
  76. void SetBrowserDelegate(
  77. std::unique_ptr<DiagnosticsBrowserDelegate> delegate) {
  78. DiagnosticsLogController::Get()->delegate_ = std::move(delegate);
  79. }
  80. void InitializeWithFakeDelegate() {
  81. std::unique_ptr<DiagnosticsBrowserDelegate> delegate =
  82. std::make_unique<FakeDiagnosticsBrowserDelegate>();
  83. DiagnosticsLogController::Initialize(std::move(delegate));
  84. }
  85. void SimulateLockScreen() {
  86. DCHECK(!Shell::Get()->session_controller()->IsScreenLocked());
  87. Shell::Get()->session_controller()->LockScreen();
  88. task_environment()->RunUntilIdle();
  89. EXPECT_TRUE(Shell::Get()->session_controller()->IsScreenLocked());
  90. }
  91. void SimulateUnlockScreen() {
  92. DCHECK(Shell::Get()->session_controller()->IsScreenLocked());
  93. SessionInfo info;
  94. info.state = session_manager::SessionState::ACTIVE;
  95. Shell::Get()->session_controller()->SetSessionInfo(std::move(info));
  96. task_environment()->RunUntilIdle();
  97. EXPECT_FALSE(Shell::Get()->session_controller()->IsScreenLocked());
  98. }
  99. void SimulateLogoutActiveUser() {
  100. Shell::Get()->session_controller()->RequestSignOut();
  101. task_environment()->RunUntilIdle();
  102. EXPECT_FALSE(
  103. Shell::Get()->session_controller()->IsActiveUserSessionStarted());
  104. }
  105. private:
  106. base::test::ScopedFeatureList feature_list_;
  107. base::ScopedTempDir save_dir_;
  108. };
  109. TEST_F(DiagnosticsLogControllerTest,
  110. ShellProvidesControllerWhenFeatureEnabled) {
  111. EXPECT_NO_FATAL_FAILURE(DiagnosticsLogController::Get());
  112. EXPECT_NE(nullptr, DiagnosticsLogController::Get());
  113. }
  114. TEST_F(DiagnosticsLogControllerTest, IsInitializedAfterDelegateProvided) {
  115. EXPECT_NE(nullptr, DiagnosticsLogController::Get());
  116. EXPECT_FALSE(DiagnosticsLogController::IsInitialized());
  117. InitializeWithFakeDelegate();
  118. EXPECT_TRUE(DiagnosticsLogController::IsInitialized());
  119. }
  120. TEST_F(DiagnosticsLogControllerTest, GenerateSessionLogOnBlockingPoolFile) {
  121. base::ScopedTempDir scoped_diagnostics_log_dir;
  122. EXPECT_TRUE(scoped_diagnostics_log_dir.CreateUniqueTempDir());
  123. const base::FilePath expected_path_regular_user =
  124. base::FilePath(scoped_diagnostics_log_dir.GetPath().Append(kFakeUserDir));
  125. const base::FilePath expected_diagnostics_log_path =
  126. expected_path_regular_user.Append(kDiangosticsDirName);
  127. SimulateUserLogin(kTestUserEmail);
  128. DiagnosticsLogController::Initialize(
  129. std::make_unique<FakeDiagnosticsBrowserDelegate>(
  130. expected_path_regular_user));
  131. const base::FilePath save_file_path = GetSessionLogPath();
  132. EXPECT_TRUE(DiagnosticsLogController::Get()->GenerateSessionLogOnBlockingPool(
  133. save_file_path));
  134. EXPECT_TRUE(base::PathExists(save_file_path));
  135. std::string contents;
  136. EXPECT_TRUE(base::ReadFileToString(save_file_path, &contents));
  137. const std::vector<std::string> log_lines = GetLogLines(contents);
  138. EXPECT_EQ(8u, log_lines.size());
  139. EXPECT_EQ(kSystemLogSectionHeader, log_lines[0]);
  140. EXPECT_EQ(kRoutineLogSubsectionHeader, log_lines[1]);
  141. const std::string expected_no_routine_msg =
  142. "No routines of this type were run in the session.";
  143. EXPECT_EQ(expected_no_routine_msg, log_lines[2]);
  144. EXPECT_EQ(kNetworkingLogSectionHeader, log_lines[3]);
  145. EXPECT_EQ(kNetworkingLogNetworkInfoHeader, log_lines[4]);
  146. EXPECT_EQ(kRoutineLogSubsectionHeader, log_lines[5]);
  147. EXPECT_EQ(expected_no_routine_msg, log_lines[6]);
  148. EXPECT_EQ(kNetworkingLogNetworkEventsHeader, log_lines[7]);
  149. }
  150. TEST_F(DiagnosticsLogControllerTest,
  151. GenerateWithRoutinesSessionLogOnBlockingPoolFile) {
  152. base::ScopedTempDir scoped_diagnostics_log_dir;
  153. EXPECT_TRUE(scoped_diagnostics_log_dir.CreateUniqueTempDir());
  154. const base::FilePath expected_path_regular_user =
  155. base::FilePath(scoped_diagnostics_log_dir.GetPath().Append(kFakeUserDir));
  156. const base::FilePath expected_diagnostics_log_path =
  157. expected_path_regular_user.Append(kDiangosticsDirName);
  158. SimulateUserLogin(kTestUserEmail);
  159. DiagnosticsLogController::Initialize(
  160. std::make_unique<FakeDiagnosticsBrowserDelegate>(
  161. expected_path_regular_user));
  162. RoutineLog* routine_log = DiagnosticsLogController::Get()->GetRoutineLog();
  163. routine_log->LogRoutineCancelled(mojom::RoutineType::kArcHttp);
  164. routine_log->LogRoutineCancelled(mojom::RoutineType::kBatteryCharge);
  165. task_environment()->RunUntilIdle();
  166. // Generate log file at test path.
  167. const base::FilePath save_file_path = GetSessionLogPath();
  168. EXPECT_TRUE(DiagnosticsLogController::Get()->GenerateSessionLogOnBlockingPool(
  169. save_file_path));
  170. EXPECT_TRUE(base::PathExists(save_file_path));
  171. std::string contents;
  172. EXPECT_TRUE(base::ReadFileToString(save_file_path, &contents));
  173. const std::vector<std::string> log_lines = GetLogLines(contents);
  174. EXPECT_EQ(8u, log_lines.size());
  175. // System state and routine data.
  176. EXPECT_EQ(kSystemLogSectionHeader, log_lines[0]);
  177. EXPECT_EQ(kRoutineLogSubsectionHeader, log_lines[1]);
  178. const std::string expected_canceled_routine_msg =
  179. "Inflight Routine Cancelled";
  180. auto system_routine_line = GetLogLineContents(log_lines[2]);
  181. EXPECT_EQ(2u, system_routine_line.size());
  182. EXPECT_EQ(expected_canceled_routine_msg, system_routine_line[1]);
  183. // Network state and routine data.
  184. EXPECT_EQ(kNetworkingLogSectionHeader, log_lines[3]);
  185. EXPECT_EQ(kNetworkingLogNetworkInfoHeader, log_lines[4]);
  186. EXPECT_EQ(kRoutineLogSubsectionHeader, log_lines[5]);
  187. auto network_routine_line = GetLogLineContents(log_lines[6]);
  188. EXPECT_EQ(2u, network_routine_line.size());
  189. EXPECT_EQ(expected_canceled_routine_msg, network_routine_line[1]);
  190. EXPECT_EQ(kNetworkingLogNetworkEventsHeader, log_lines[7]);
  191. }
  192. TEST_F(DiagnosticsLogControllerTest,
  193. ResetAndInitializeShouldNotLookupProfilePath) {
  194. const base::FilePath expected_path_not_regular_user =
  195. base::FilePath(kTmpDiagnosticsDir);
  196. // Simulate called before delegate configured.
  197. DiagnosticsLogController::Get()->ResetAndInitializeLogWriters();
  198. EXPECT_EQ(expected_path_not_regular_user, log_base_path());
  199. InitializeWithFakeDelegate();
  200. // Simulate sign-in user.
  201. ClearLogin();
  202. DiagnosticsLogController::Get()->ResetAndInitializeLogWriters();
  203. EXPECT_EQ(expected_path_not_regular_user, log_base_path());
  204. SimulateGuestLogin();
  205. DiagnosticsLogController::Get()->ResetAndInitializeLogWriters();
  206. EXPECT_EQ(expected_path_not_regular_user, log_base_path());
  207. SimulateKioskMode(user_manager::UserType::USER_TYPE_KIOSK_APP);
  208. DiagnosticsLogController::Get()->ResetAndInitializeLogWriters();
  209. EXPECT_EQ(expected_path_not_regular_user, log_base_path());
  210. SimulateKioskMode(user_manager::UserType::USER_TYPE_ARC_KIOSK_APP);
  211. DiagnosticsLogController::Get()->ResetAndInitializeLogWriters();
  212. EXPECT_EQ(expected_path_not_regular_user, log_base_path());
  213. }
  214. TEST_F(DiagnosticsLogControllerTest,
  215. ResetAndInitializeShouldLookupProfileUserEmptyPath) {
  216. const base::FilePath expected_path_not_regular_user =
  217. base::FilePath(kTmpDiagnosticsDir);
  218. // Simulate DiagnosticsBrowserDelegate returning empty path.
  219. std::unique_ptr<DiagnosticsBrowserDelegate> delegate_with_empty_file_path =
  220. std::make_unique<FakeDiagnosticsBrowserDelegate>(base::FilePath());
  221. SetBrowserDelegate(std::move(delegate_with_empty_file_path));
  222. SimulateUserLogin(kTestUserEmail);
  223. DiagnosticsLogController::Get()->ResetAndInitializeLogWriters();
  224. EXPECT_EQ(expected_path_not_regular_user, log_base_path());
  225. }
  226. TEST_F(DiagnosticsLogControllerTest,
  227. ResetAndInitializeForShouldLookupProfileUserNonEmptyPath) {
  228. InitializeWithFakeDelegate();
  229. const base::FilePath expected_path_regular_user =
  230. base::FilePath(kDefaultUserDir).Append(kDiangosticsDirName);
  231. SimulateUserLogin(kTestUserEmail);
  232. DiagnosticsLogController::Get()->ResetAndInitializeLogWriters();
  233. EXPECT_EQ(expected_path_regular_user, log_base_path());
  234. }
  235. TEST_F(DiagnosticsLogControllerTest,
  236. LogBaseCorrectlyUpdatedOnActiveUserSessionChanged) {
  237. const base::FilePath expected_path_not_regular_user =
  238. base::FilePath(kTmpDiagnosticsDir);
  239. InitializeWithFakeDelegate();
  240. // Simulate sign-in user.
  241. ClearLogin();
  242. EXPECT_EQ(expected_path_not_regular_user, log_base_path());
  243. SimulateGuestLogin();
  244. EXPECT_EQ(expected_path_not_regular_user, log_base_path());
  245. SimulateKioskMode(user_manager::UserType::USER_TYPE_KIOSK_APP);
  246. EXPECT_EQ(expected_path_not_regular_user, log_base_path());
  247. SimulateKioskMode(user_manager::UserType::USER_TYPE_ARC_KIOSK_APP);
  248. EXPECT_EQ(expected_path_not_regular_user, log_base_path());
  249. SimulateUserLogin(kTestUserEmail);
  250. const base::FilePath expected_path_regular_user =
  251. base::FilePath(kDefaultUserDir).Append(kDiangosticsDirName);
  252. EXPECT_EQ(expected_path_regular_user, log_base_path());
  253. SimulateLockScreen();
  254. EXPECT_EQ(expected_path_regular_user, log_base_path());
  255. SimulateUnlockScreen();
  256. EXPECT_EQ(expected_path_regular_user, log_base_path());
  257. SimulateLogoutActiveUser();
  258. EXPECT_EQ(expected_path_not_regular_user, log_base_path());
  259. }
  260. TEST_F(DiagnosticsLogControllerTest, SetLogWritersUsingLogBasePath) {
  261. base::ScopedTempDir scoped_dir;
  262. EXPECT_TRUE(scoped_dir.CreateUniqueTempDir());
  263. const base::FilePath expected_path_regular_user =
  264. base::FilePath(scoped_dir.GetPath().Append(kFakeUserDir));
  265. const base::FilePath expected_diagnostics_log_path =
  266. expected_path_regular_user.Append(kDiangosticsDirName);
  267. SimulateUserLogin(kTestUserEmail);
  268. DiagnosticsLogController::Initialize(
  269. std::make_unique<FakeDiagnosticsBrowserDelegate>(
  270. expected_path_regular_user));
  271. // After initialize log writers exist.
  272. EXPECT_EQ(expected_diagnostics_log_path, log_base_path());
  273. NetworkingLog* networking_log =
  274. DiagnosticsLogController::Get()->GetNetworkingLog();
  275. RoutineLog* routine_log = DiagnosticsLogController::Get()->GetRoutineLog();
  276. TelemetryLog* telemetry_log =
  277. DiagnosticsLogController::Get()->GetTelemetryLog();
  278. EXPECT_NE(nullptr, networking_log);
  279. EXPECT_NE(nullptr, routine_log);
  280. EXPECT_NE(nullptr, telemetry_log);
  281. // Simulate events to write files.
  282. const std::vector<std::string> networks{"fake_guid", "other_fake_guid"};
  283. networking_log->UpdateNetworkList(networks, "fake_guid");
  284. networking_log->UpdateNetworkState(mojom::Network::New());
  285. routine_log->LogRoutineCancelled(mojom::RoutineType::kDnsResolution);
  286. routine_log->LogRoutineCancelled(mojom::RoutineType::kCpuStress);
  287. // Wait for Append tasks which create the logs to complete.
  288. task_environment()->RunUntilIdle();
  289. EXPECT_FALSE(
  290. routine_log->GetContentsForCategory(RoutineLog::RoutineCategory::kNetwork)
  291. .empty());
  292. EXPECT_FALSE(
  293. routine_log->GetContentsForCategory(RoutineLog::RoutineCategory::kSystem)
  294. .empty());
  295. EXPECT_TRUE(base::PathExists(
  296. expected_diagnostics_log_path.Append("network_events.log")));
  297. EXPECT_TRUE(base::PathExists(expected_diagnostics_log_path.Append(
  298. "diagnostics_routines_network.log")));
  299. EXPECT_TRUE(base::PathExists(
  300. expected_diagnostics_log_path.Append("diagnostics_routines_system.log")));
  301. }
  302. TEST_F(DiagnosticsLogControllerTest, ClearLogDirectoryOnInitialize) {
  303. base::ScopedTempDir scoped_dir;
  304. EXPECT_TRUE(scoped_dir.CreateUniqueTempDir());
  305. const base::FilePath expected_path_regular_user =
  306. base::FilePath(scoped_dir.GetPath().Append(kFakeUserDir));
  307. const base::FilePath expected_diagnostics_log_path =
  308. expected_path_regular_user.Append(kDiangosticsDirName);
  309. EXPECT_TRUE(base::CreateDirectory(expected_diagnostics_log_path));
  310. EXPECT_TRUE(base::PathExists(expected_diagnostics_log_path));
  311. SimulateUserLogin(kTestUserEmail);
  312. DiagnosticsLogController::Initialize(
  313. std::make_unique<FakeDiagnosticsBrowserDelegate>(
  314. expected_path_regular_user));
  315. // Wait for delete to complete.
  316. task_environment()->RunUntilIdle();
  317. EXPECT_FALSE(base::PathExists(expected_diagnostics_log_path));
  318. // Before routines updated log file does not exist.
  319. RoutineLog* routine_log = DiagnosticsLogController::Get()->GetRoutineLog();
  320. routine_log->LogRoutineCancelled(mojom::RoutineType::kDnsResolution);
  321. // Wait for append to write logs.
  322. task_environment()->RunUntilIdle();
  323. EXPECT_EQ(expected_diagnostics_log_path, log_base_path());
  324. EXPECT_TRUE(base::PathExists(expected_diagnostics_log_path));
  325. }
  326. } // namespace diagnostics
  327. } // namespace ash