sys_info_unittest.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  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. #include <stdint.h>
  5. #include <utility>
  6. #include <vector>
  7. #include "base/bind.h"
  8. #include "base/environment.h"
  9. #include "base/files/file_util.h"
  10. #include "base/numerics/safe_conversions.h"
  11. #include "base/process/process_metrics.h"
  12. #include "base/run_loop.h"
  13. #include "base/strings/pattern.h"
  14. #include "base/strings/string_number_conversions.h"
  15. #include "base/strings/string_split.h"
  16. #include "base/strings/string_util.h"
  17. #include "base/strings/sys_string_conversions.h"
  18. #include "base/strings/utf_string_conversions.h"
  19. #include "base/system/sys_info.h"
  20. #include "base/test/scoped_chromeos_version_info.h"
  21. #include "base/test/scoped_running_on_chromeos.h"
  22. #include "base/test/task_environment.h"
  23. #include "base/threading/platform_thread.h"
  24. #include "base/threading/scoped_blocking_call.h"
  25. #include "base/time/time.h"
  26. #include "build/build_config.h"
  27. #include "testing/gtest/include/gtest/gtest-death-test.h"
  28. #include "testing/gtest/include/gtest/gtest.h"
  29. #include "testing/platform_test.h"
  30. #include "third_party/abseil-cpp/absl/types/optional.h"
  31. #if BUILDFLAG(IS_WIN)
  32. #include "base/win/com_init_util.h"
  33. #include "base/win/scoped_bstr.h"
  34. #include "base/win/scoped_com_initializer.h"
  35. #include "base/win/scoped_variant.h"
  36. #include "base/win/wmi.h"
  37. #endif // BUILDFLAG(IS_WIN)
  38. namespace base {
  39. #if BUILDFLAG(IS_ANDROID)
  40. // Some Android (Cast) test devices have a large portion of physical memory
  41. // reserved. During investigation, around 115-150 MB were seen reserved, so we
  42. // track this here with a factory of safety of 2.
  43. static constexpr int kReservedPhysicalMemory = 300 * 1024; // In _K_bytes.
  44. #endif // BUILDFLAG(IS_ANDROID)
  45. using SysInfoTest = PlatformTest;
  46. TEST_F(SysInfoTest, NumProcs) {
  47. // We aren't actually testing that it's correct, just that it's sane.
  48. EXPECT_GE(SysInfo::NumberOfProcessors(), 1);
  49. }
  50. TEST_F(SysInfoTest, AmountOfMem) {
  51. // We aren't actually testing that it's correct, just that it's sane.
  52. EXPECT_GT(SysInfo::AmountOfPhysicalMemory(), 0u);
  53. EXPECT_GT(SysInfo::AmountOfPhysicalMemoryMB(), 0);
  54. // The maxmimal amount of virtual memory can be zero which means unlimited.
  55. EXPECT_GE(SysInfo::AmountOfVirtualMemory(), 0u);
  56. }
  57. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
  58. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  59. #define MAYBE_AmountOfAvailablePhysicalMemory \
  60. DISABLED_AmountOfAvailablePhysicalMemory
  61. #else
  62. #define MAYBE_AmountOfAvailablePhysicalMemory AmountOfAvailablePhysicalMemory
  63. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  64. TEST_F(SysInfoTest, MAYBE_AmountOfAvailablePhysicalMemory) {
  65. // Note: info is in _K_bytes.
  66. SystemMemoryInfoKB info;
  67. ASSERT_TRUE(GetSystemMemoryInfo(&info));
  68. EXPECT_GT(info.free, 0);
  69. if (info.available != 0) {
  70. // If there is MemAvailable from kernel.
  71. EXPECT_LT(info.available, info.total);
  72. const uint64_t amount = SysInfo::AmountOfAvailablePhysicalMemory(info);
  73. // We aren't actually testing that it's correct, just that it's sane.
  74. // Available memory is |free - reserved + reclaimable (inactive, non-free)|.
  75. // On some android platforms, reserved is a substantial portion.
  76. const int available =
  77. #if BUILDFLAG(IS_ANDROID)
  78. std::max(info.free - kReservedPhysicalMemory, 0);
  79. #else
  80. info.free;
  81. #endif // BUILDFLAG(IS_ANDROID)
  82. EXPECT_GT(amount, checked_cast<uint64_t>(available) * 1024);
  83. EXPECT_LT(amount / 1024, checked_cast<uint64_t>(info.available));
  84. // Simulate as if there is no MemAvailable.
  85. info.available = 0;
  86. }
  87. // There is no MemAvailable. Check the fallback logic.
  88. const uint64_t amount = SysInfo::AmountOfAvailablePhysicalMemory(info);
  89. // We aren't actually testing that it's correct, just that it's sane.
  90. EXPECT_GT(amount, checked_cast<uint64_t>(info.free) * 1024);
  91. EXPECT_LT(amount / 1024, checked_cast<uint64_t>(info.total));
  92. }
  93. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
  94. // BUILDFLAG(IS_ANDROID)
  95. TEST_F(SysInfoTest, AmountOfFreeDiskSpace) {
  96. // We aren't actually testing that it's correct, just that it's sane.
  97. FilePath tmp_path;
  98. ASSERT_TRUE(GetTempDir(&tmp_path));
  99. EXPECT_GE(SysInfo::AmountOfFreeDiskSpace(tmp_path), 0) << tmp_path;
  100. }
  101. TEST_F(SysInfoTest, AmountOfTotalDiskSpace) {
  102. // We aren't actually testing that it's correct, just that it's sane.
  103. FilePath tmp_path;
  104. ASSERT_TRUE(GetTempDir(&tmp_path));
  105. EXPECT_GT(SysInfo::AmountOfTotalDiskSpace(tmp_path), 0) << tmp_path;
  106. }
  107. #if BUILDFLAG(IS_FUCHSIA)
  108. // Verify that specifying total disk space for nested directories matches
  109. // the deepest-nested.
  110. TEST_F(SysInfoTest, NestedVolumesAmountOfTotalDiskSpace) {
  111. constexpr int64_t kOuterVolumeQuota = 1024;
  112. constexpr int64_t kInnerVolumeQuota = kOuterVolumeQuota / 2;
  113. FilePath tmp_path;
  114. ASSERT_TRUE(GetTempDir(&tmp_path));
  115. SysInfo::SetAmountOfTotalDiskSpace(tmp_path, kOuterVolumeQuota);
  116. const FilePath subdirectory_path = tmp_path.Append("subdirectory");
  117. SysInfo::SetAmountOfTotalDiskSpace(subdirectory_path, kInnerVolumeQuota);
  118. EXPECT_EQ(SysInfo::AmountOfTotalDiskSpace(tmp_path), kOuterVolumeQuota);
  119. EXPECT_EQ(SysInfo::AmountOfTotalDiskSpace(subdirectory_path),
  120. kInnerVolumeQuota);
  121. // Remove the inner directory quota setting and check again.
  122. SysInfo::SetAmountOfTotalDiskSpace(subdirectory_path, -1);
  123. EXPECT_EQ(SysInfo::AmountOfTotalDiskSpace(subdirectory_path),
  124. kOuterVolumeQuota);
  125. }
  126. #endif // BUILDFLAG(IS_FUCHSIA)
  127. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
  128. BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
  129. TEST_F(SysInfoTest, OperatingSystemVersion) {
  130. std::string version = SysInfo::OperatingSystemVersion();
  131. EXPECT_FALSE(version.empty());
  132. }
  133. TEST_F(SysInfoTest, OperatingSystemVersionNumbers) {
  134. int32_t os_major_version = -1;
  135. int32_t os_minor_version = -1;
  136. int32_t os_bugfix_version = -1;
  137. SysInfo::OperatingSystemVersionNumbers(&os_major_version, &os_minor_version,
  138. &os_bugfix_version);
  139. EXPECT_GT(os_major_version, -1);
  140. EXPECT_GT(os_minor_version, -1);
  141. EXPECT_GT(os_bugfix_version, -1);
  142. }
  143. #endif
  144. #if BUILDFLAG(IS_IOS)
  145. TEST_F(SysInfoTest, GetIOSBuildNumber) {
  146. std::string build_number(SysInfo::GetIOSBuildNumber());
  147. EXPECT_GT(build_number.length(), 0U);
  148. }
  149. #endif // BUILDFLAG(IS_IOS)
  150. TEST_F(SysInfoTest, Uptime) {
  151. TimeDelta up_time_1 = SysInfo::Uptime();
  152. // UpTime() is implemented internally using TimeTicks::Now(), which documents
  153. // system resolution as being 1-15ms. Sleep a little longer than that.
  154. PlatformThread::Sleep(Milliseconds(20));
  155. TimeDelta up_time_2 = SysInfo::Uptime();
  156. EXPECT_GT(up_time_1.InMicroseconds(), 0);
  157. EXPECT_GT(up_time_2.InMicroseconds(), up_time_1.InMicroseconds());
  158. }
  159. #if BUILDFLAG(IS_APPLE)
  160. TEST_F(SysInfoTest, HardwareModelNameFormatMacAndiOS) {
  161. std::string hardware_model = SysInfo::HardwareModelName();
  162. ASSERT_FALSE(hardware_model.empty());
  163. // Check that the model is of the expected format, which is different on iOS
  164. // simulators and real iOS / MacOS devices.
  165. #if BUILDFLAG(IS_IOS) && TARGET_OS_SIMULATOR
  166. // On iOS simulators, the device model looks like "iOS Simulator (Foo[,Bar])"
  167. // where Foo is either "Unknown", "iPhone" or "iPad", and Bar, if present, is
  168. // a number.
  169. EXPECT_TRUE(base::MatchPattern(hardware_model, "iOS Simulator (*)"))
  170. << hardware_model;
  171. std::vector<StringPiece> mainPieces =
  172. SplitStringPiece(hardware_model, "()", KEEP_WHITESPACE, SPLIT_WANT_ALL);
  173. ASSERT_EQ(3u, mainPieces.size()) << hardware_model;
  174. std::vector<StringPiece> modelPieces =
  175. SplitStringPiece(mainPieces[1], ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
  176. ASSERT_GE(modelPieces.size(), 1u) << hardware_model;
  177. if (modelPieces.size() == 1u) {
  178. EXPECT_TRUE(modelPieces[0] == "Unknown" || modelPieces[0] == "iPhone" ||
  179. modelPieces[0] == "iPad")
  180. << hardware_model;
  181. } else {
  182. int value;
  183. EXPECT_TRUE(StringToInt(modelPieces[1], &value)) << hardware_model;
  184. }
  185. #else
  186. // The expected format is "Foo,Bar" where Foo is "iPhone" or "iPad" and Bar is
  187. // a number.
  188. std::vector<StringPiece> pieces =
  189. SplitStringPiece(hardware_model, ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
  190. ASSERT_EQ(2u, pieces.size()) << hardware_model;
  191. int value;
  192. EXPECT_TRUE(StringToInt(pieces[1], &value)) << hardware_model;
  193. #endif // BUILDFLAG(IS_IOS) && TARGET_OS_SIMULATOR
  194. }
  195. #endif // BUILDFLAG(IS_APPLE)
  196. TEST_F(SysInfoTest, GetHardwareInfo) {
  197. test::TaskEnvironment task_environment;
  198. absl::optional<SysInfo::HardwareInfo> hardware_info;
  199. auto callback = base::BindOnce(
  200. [](absl::optional<SysInfo::HardwareInfo>* target_info,
  201. SysInfo::HardwareInfo info) { *target_info = std::move(info); },
  202. &hardware_info);
  203. SysInfo::GetHardwareInfo(std::move(callback));
  204. task_environment.RunUntilIdle();
  205. ASSERT_TRUE(hardware_info.has_value());
  206. EXPECT_TRUE(IsStringUTF8(hardware_info->manufacturer));
  207. EXPECT_TRUE(IsStringUTF8(hardware_info->model));
  208. bool empty_result_expected =
  209. #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_WIN) || \
  210. BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
  211. false;
  212. #else
  213. true;
  214. #endif
  215. EXPECT_EQ(hardware_info->manufacturer.empty(), empty_result_expected);
  216. EXPECT_EQ(hardware_info->model.empty(), empty_result_expected);
  217. }
  218. #if BUILDFLAG(IS_WIN)
  219. TEST_F(SysInfoTest, GetHardwareInfoWMIMatchRegistry) {
  220. base::win::ScopedCOMInitializer com_initializer;
  221. test::TaskEnvironment task_environment;
  222. absl::optional<SysInfo::HardwareInfo> hardware_info;
  223. auto callback = base::BindOnce(
  224. [](absl::optional<SysInfo::HardwareInfo>* target_info,
  225. SysInfo::HardwareInfo info) { *target_info = std::move(info); },
  226. &hardware_info);
  227. SysInfo::GetHardwareInfo(std::move(callback));
  228. task_environment.RunUntilIdle();
  229. ASSERT_TRUE(hardware_info.has_value());
  230. Microsoft::WRL::ComPtr<IWbemServices> wmi_services;
  231. EXPECT_TRUE(base::win::CreateLocalWmiConnection(true, &wmi_services));
  232. static constexpr wchar_t query_computer_system[] =
  233. L"SELECT Manufacturer,Model FROM Win32_ComputerSystem";
  234. Microsoft::WRL::ComPtr<IEnumWbemClassObject> enumerator_computer_system;
  235. HRESULT hr = wmi_services->ExecQuery(
  236. base::win::ScopedBstr(L"WQL").Get(),
  237. base::win::ScopedBstr(query_computer_system).Get(),
  238. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr,
  239. &enumerator_computer_system);
  240. EXPECT_FALSE(FAILED(hr) || !enumerator_computer_system.Get());
  241. Microsoft::WRL::ComPtr<IWbemClassObject> class_object;
  242. ULONG items_returned = 0;
  243. hr = enumerator_computer_system->Next(WBEM_INFINITE, 1, &class_object,
  244. &items_returned);
  245. EXPECT_FALSE(FAILED(hr) || !items_returned);
  246. base::win::ScopedVariant manufacturerVar;
  247. std::wstring manufacturer;
  248. hr = class_object->Get(L"Manufacturer", 0, manufacturerVar.Receive(), nullptr,
  249. nullptr);
  250. if (SUCCEEDED(hr) && manufacturerVar.type() == VT_BSTR) {
  251. manufacturer.assign(V_BSTR(manufacturerVar.ptr()),
  252. ::SysStringLen(V_BSTR(manufacturerVar.ptr())));
  253. }
  254. base::win::ScopedVariant modelVar;
  255. std::wstring model;
  256. hr = class_object->Get(L"Model", 0, modelVar.Receive(), nullptr, nullptr);
  257. if (SUCCEEDED(hr) && modelVar.type() == VT_BSTR) {
  258. model.assign(V_BSTR(modelVar.ptr()),
  259. ::SysStringLen(V_BSTR(modelVar.ptr())));
  260. }
  261. EXPECT_TRUE(hardware_info->manufacturer == base::SysWideToUTF8(manufacturer));
  262. EXPECT_TRUE(hardware_info->model == base::SysWideToUTF8(model));
  263. }
  264. #endif
  265. #if BUILDFLAG(IS_CHROMEOS)
  266. TEST_F(SysInfoTest, GoogleChromeOSVersionNumbers) {
  267. int32_t os_major_version = -1;
  268. int32_t os_minor_version = -1;
  269. int32_t os_bugfix_version = -1;
  270. const char kLsbRelease[] =
  271. "FOO=1234123.34.5\n"
  272. "CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
  273. test::ScopedChromeOSVersionInfo version(kLsbRelease, Time());
  274. SysInfo::OperatingSystemVersionNumbers(&os_major_version, &os_minor_version,
  275. &os_bugfix_version);
  276. EXPECT_EQ(1, os_major_version);
  277. EXPECT_EQ(2, os_minor_version);
  278. EXPECT_EQ(3, os_bugfix_version);
  279. }
  280. TEST_F(SysInfoTest, GoogleChromeOSVersionNumbersFirst) {
  281. int32_t os_major_version = -1;
  282. int32_t os_minor_version = -1;
  283. int32_t os_bugfix_version = -1;
  284. const char kLsbRelease[] =
  285. "CHROMEOS_RELEASE_VERSION=1.2.3.4\n"
  286. "FOO=1234123.34.5\n";
  287. test::ScopedChromeOSVersionInfo version(kLsbRelease, Time());
  288. SysInfo::OperatingSystemVersionNumbers(&os_major_version, &os_minor_version,
  289. &os_bugfix_version);
  290. EXPECT_EQ(1, os_major_version);
  291. EXPECT_EQ(2, os_minor_version);
  292. EXPECT_EQ(3, os_bugfix_version);
  293. }
  294. TEST_F(SysInfoTest, GoogleChromeOSNoVersionNumbers) {
  295. int32_t os_major_version = -1;
  296. int32_t os_minor_version = -1;
  297. int32_t os_bugfix_version = -1;
  298. const char kLsbRelease[] = "FOO=1234123.34.5\n";
  299. test::ScopedChromeOSVersionInfo version(kLsbRelease, Time());
  300. SysInfo::OperatingSystemVersionNumbers(&os_major_version, &os_minor_version,
  301. &os_bugfix_version);
  302. EXPECT_EQ(0, os_major_version);
  303. EXPECT_EQ(0, os_minor_version);
  304. EXPECT_EQ(0, os_bugfix_version);
  305. }
  306. TEST_F(SysInfoTest, GoogleChromeOSLsbReleaseTime) {
  307. const char kLsbRelease[] = "CHROMEOS_RELEASE_VERSION=1.2.3.4";
  308. // Use a fake time that can be safely displayed as a string.
  309. const Time lsb_release_time(Time::FromDoubleT(12345.6));
  310. test::ScopedChromeOSVersionInfo version(kLsbRelease, lsb_release_time);
  311. Time parsed_lsb_release_time = SysInfo::GetLsbReleaseTime();
  312. EXPECT_DOUBLE_EQ(lsb_release_time.ToDoubleT(),
  313. parsed_lsb_release_time.ToDoubleT());
  314. }
  315. TEST_F(SysInfoTest, IsRunningOnChromeOS) {
  316. {
  317. const char kLsbRelease1[] =
  318. "CHROMEOS_RELEASE_NAME=Non Chrome OS\n"
  319. "CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
  320. test::ScopedChromeOSVersionInfo version(kLsbRelease1, Time());
  321. EXPECT_FALSE(SysInfo::IsRunningOnChromeOS());
  322. }
  323. {
  324. const char kLsbRelease2[] =
  325. "CHROMEOS_RELEASE_NAME=Chrome OS\n"
  326. "CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
  327. test::ScopedChromeOSVersionInfo version(kLsbRelease2, Time());
  328. EXPECT_TRUE(SysInfo::IsRunningOnChromeOS());
  329. }
  330. {
  331. const char kLsbRelease3[] = "CHROMEOS_RELEASE_NAME=Chromium OS\n";
  332. test::ScopedChromeOSVersionInfo version(kLsbRelease3, Time());
  333. EXPECT_TRUE(SysInfo::IsRunningOnChromeOS());
  334. }
  335. }
  336. // Regression test for https://crbug.com/1148904.
  337. TEST_F(SysInfoTest, ScopedChromeOSVersionInfoDoesNotChangeEnvironment) {
  338. std::unique_ptr<Environment> environment = Environment::Create();
  339. ASSERT_FALSE(environment->HasVar("LSB_RELEASE"));
  340. {
  341. const char kLsbRelease[] =
  342. "CHROMEOS_RELEASE_NAME=Chrome OS\n"
  343. "CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
  344. test::ScopedChromeOSVersionInfo version(kLsbRelease, Time());
  345. }
  346. EXPECT_FALSE(environment->HasVar("LSB_RELEASE"));
  347. }
  348. TEST_F(SysInfoTest, CrashOnBaseImage) {
  349. const char kLsbRelease[] =
  350. "CHROMEOS_RELEASE_NAME=Chrome OS\n"
  351. "CHROMEOS_RELEASE_VERSION=1.2.3.4\n"
  352. "CHROMEOS_RELEASE_TRACK=stable-channel\n";
  353. test::ScopedChromeOSVersionInfo version(kLsbRelease, Time());
  354. EXPECT_TRUE(SysInfo::IsRunningOnChromeOS());
  355. EXPECT_DEATH_IF_SUPPORTED({ SysInfo::CrashIfChromeOSNonTestImage(); }, "");
  356. }
  357. TEST_F(SysInfoTest, NoCrashOnTestImage) {
  358. const char kLsbRelease[] =
  359. "CHROMEOS_RELEASE_NAME=Chrome OS\n"
  360. "CHROMEOS_RELEASE_VERSION=1.2.3.4\n"
  361. "CHROMEOS_RELEASE_TRACK=testimage-channel\n";
  362. test::ScopedChromeOSVersionInfo version(kLsbRelease, Time());
  363. EXPECT_TRUE(SysInfo::IsRunningOnChromeOS());
  364. // Should not crash.
  365. SysInfo::CrashIfChromeOSNonTestImage();
  366. }
  367. TEST_F(SysInfoTest, NoCrashOnLinuxBuild) {
  368. test::ScopedChromeOSVersionInfo version("", Time());
  369. EXPECT_FALSE(SysInfo::IsRunningOnChromeOS());
  370. // Should not crash.
  371. SysInfo::CrashIfChromeOSNonTestImage();
  372. }
  373. TEST_F(SysInfoTest, ScopedRunningOnChromeOS) {
  374. // base_unittests run both on linux-chromeos and actual devices, so the
  375. // initial state of IsRunningOnChromeOS may vary.
  376. bool was_running = SysInfo::IsRunningOnChromeOS();
  377. {
  378. test::ScopedRunningOnChromeOS running_on_chromeos;
  379. EXPECT_TRUE(SysInfo::IsRunningOnChromeOS());
  380. }
  381. // Previous value restored.
  382. EXPECT_EQ(was_running, SysInfo::IsRunningOnChromeOS());
  383. }
  384. #endif // BUILDFLAG(IS_CHROMEOS)
  385. } // namespace base