esim_profile_unittest.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. // Copyright 2020 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 <string>
  5. #include "ash/services/cellular_setup/esim_test_base.h"
  6. #include "ash/services/cellular_setup/esim_test_utils.h"
  7. #include "ash/services/cellular_setup/public/mojom/esim_manager.mojom-shared.h"
  8. #include "base/strings/utf_string_conversions.h"
  9. #include "base/test/bind.h"
  10. #include "base/test/metrics/histogram_tester.h"
  11. #include "chromeos/ash/components/dbus/hermes/hermes_euicc_client.h"
  12. #include "chromeos/ash/components/dbus/hermes/hermes_profile_client.h"
  13. #include "chromeos/ash/components/network/fake_network_connection_handler.h"
  14. #include "components/user_manager/fake_user_manager.h"
  15. #include "mojo/public/cpp/bindings/pending_remote.h"
  16. namespace ash::cellular_setup {
  17. namespace {
  18. const char kProfileUninstallationResultHistogram[] =
  19. "Network.Cellular.ESim.ProfileUninstallationResult";
  20. const char kProfileRenameResultHistogram[] =
  21. "Network.Cellular.ESim.ProfileRenameResult";
  22. const char kPendingProfileLatencyHistogram[] =
  23. "Network.Cellular.ESim.ProfileDownload.PendingProfile.Latency";
  24. const char kPendingProfileInstallHistogram[] =
  25. "Network.Cellular.ESim.InstallPendingProfile.Result";
  26. class TestUserManager : public user_manager::FakeUserManager {
  27. public:
  28. explicit TestUserManager(bool is_guest) : is_guest_(is_guest) {
  29. user_manager::UserManager::SetInstance(this);
  30. }
  31. ~TestUserManager() override = default;
  32. // user_manager::UserManager:
  33. bool IsLoggedInAsGuest() const override { return is_guest_; }
  34. private:
  35. const bool is_guest_;
  36. };
  37. mojom::ESimOperationResult UninstallProfile(
  38. const mojo::Remote<mojom::ESimProfile>& esim_profile) {
  39. mojom::ESimOperationResult uninstall_result;
  40. base::RunLoop run_loop;
  41. esim_profile->UninstallProfile(base::BindOnce(
  42. [](mojom::ESimOperationResult* out_uninstall_result,
  43. base::OnceClosure quit_closure,
  44. mojom::ESimOperationResult uninstall_result) {
  45. *out_uninstall_result = uninstall_result;
  46. std::move(quit_closure).Run();
  47. },
  48. &uninstall_result, run_loop.QuitClosure()));
  49. run_loop.Run();
  50. return uninstall_result;
  51. }
  52. mojom::ESimOperationResult SetProfileNickname(
  53. const mojo::Remote<mojom::ESimProfile>& esim_profile,
  54. const std::u16string& nickname) {
  55. mojom::ESimOperationResult result;
  56. base::RunLoop run_loop;
  57. esim_profile->SetProfileNickname(
  58. nickname, base::BindOnce(
  59. [](mojom::ESimOperationResult* out_result,
  60. base::OnceClosure quit_closure,
  61. mojom::ESimOperationResult result) {
  62. *out_result = result;
  63. std::move(quit_closure).Run();
  64. },
  65. &result, run_loop.QuitClosure()));
  66. run_loop.Run();
  67. return result;
  68. }
  69. } // namespace
  70. class ESimProfileTest : public ESimTestBase {
  71. public:
  72. ESimProfileTest() = default;
  73. ESimProfileTest(const ESimProfileTest&) = delete;
  74. ESimProfileTest& operator=(const ESimProfileTest&) = delete;
  75. void SetUp() override {
  76. ESimTestBase::SetUp();
  77. SetupEuicc();
  78. }
  79. void TearDown() override {
  80. HermesProfileClient::Get()->GetTestInterface()->SetEnableProfileBehavior(
  81. HermesProfileClient::TestInterface::EnableProfileBehavior::
  82. kConnectableButNotConnected);
  83. }
  84. void SetIsGuest(bool is_guest) {
  85. test_user_manager_ = std::make_unique<TestUserManager>(is_guest);
  86. }
  87. mojo::Remote<mojom::ESimProfile> GetESimProfileForIccid(
  88. const std::string& eid,
  89. const std::string& iccid) {
  90. mojo::Remote<mojom::Euicc> euicc = GetEuiccForEid(eid);
  91. if (!euicc.is_bound()) {
  92. return mojo::Remote<mojom::ESimProfile>();
  93. }
  94. std::vector<mojo::PendingRemote<mojom::ESimProfile>>
  95. profile_pending_remotes = GetProfileList(euicc);
  96. for (auto& profile_pending_remote : profile_pending_remotes) {
  97. mojo::Remote<mojom::ESimProfile> esim_profile(
  98. std::move(profile_pending_remote));
  99. mojom::ESimProfilePropertiesPtr profile_properties =
  100. GetESimProfileProperties(esim_profile);
  101. if (profile_properties->iccid == iccid) {
  102. return esim_profile;
  103. }
  104. }
  105. return mojo::Remote<mojom::ESimProfile>();
  106. }
  107. mojom::ProfileInstallResult InstallProfile(
  108. const mojo::Remote<mojom::ESimProfile>& esim_profile,
  109. bool wait_for_connect,
  110. bool fail_connect) {
  111. mojom::ProfileInstallResult out_install_result;
  112. base::RunLoop run_loop;
  113. esim_profile->InstallProfile(
  114. /*confirmation_code=*/std::string(),
  115. base::BindLambdaForTesting(
  116. [&](mojom::ProfileInstallResult install_result) {
  117. out_install_result = install_result;
  118. run_loop.Quit();
  119. }));
  120. FastForwardProfileRefreshDelay();
  121. if (wait_for_connect) {
  122. base::RunLoop().RunUntilIdle();
  123. EXPECT_LE(1u, network_connection_handler()->connect_calls().size());
  124. if (fail_connect) {
  125. network_connection_handler()
  126. ->connect_calls()
  127. .back()
  128. .InvokeErrorCallback("fake_error_name");
  129. } else {
  130. network_connection_handler()
  131. ->connect_calls()
  132. .back()
  133. .InvokeSuccessCallback();
  134. }
  135. }
  136. run_loop.Run();
  137. return out_install_result;
  138. }
  139. private:
  140. std::unique_ptr<TestUserManager> test_user_manager_;
  141. };
  142. TEST_F(ESimProfileTest, GetProperties) {
  143. SetIsGuest(false);
  144. HermesEuiccClient::TestInterface* euicc_test =
  145. HermesEuiccClient::Get()->GetTestInterface();
  146. dbus::ObjectPath profile_path = euicc_test->AddFakeCarrierProfile(
  147. dbus::ObjectPath(ESimTestBase::kTestEuiccPath),
  148. hermes::profile::State::kPending, "",
  149. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  150. kAddProfileWithService);
  151. base::RunLoop().RunUntilIdle();
  152. HermesProfileClient::Properties* dbus_properties =
  153. HermesProfileClient::Get()->GetProperties(profile_path);
  154. mojo::Remote<mojom::ESimProfile> esim_profile = GetESimProfileForIccid(
  155. ESimTestBase::kTestEid, dbus_properties->iccid().value());
  156. ASSERT_TRUE(esim_profile.is_bound());
  157. mojom::ESimProfilePropertiesPtr mojo_properties =
  158. GetESimProfileProperties(esim_profile);
  159. EXPECT_EQ(dbus_properties->iccid().value(), mojo_properties->iccid);
  160. }
  161. TEST_F(ESimProfileTest, InstallProfile) {
  162. SetIsGuest(false);
  163. base::HistogramTester histogram_tester;
  164. HermesEuiccClient::TestInterface* euicc_test =
  165. HermesEuiccClient::Get()->GetTestInterface();
  166. dbus::ObjectPath profile_path = euicc_test->AddFakeCarrierProfile(
  167. dbus::ObjectPath(ESimTestBase::kTestEuiccPath),
  168. hermes::profile::State::kPending, "",
  169. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  170. kAddProfileWithService);
  171. base::RunLoop().RunUntilIdle();
  172. HermesProfileClient::Properties* dbus_properties =
  173. HermesProfileClient::Get()->GetProperties(profile_path);
  174. // Verify that install errors return error code properly.
  175. euicc_test->QueueHermesErrorStatus(
  176. HermesResponseStatus::kErrorNeedConfirmationCode);
  177. mojo::Remote<mojom::ESimProfile> esim_profile = GetESimProfileForIccid(
  178. ESimTestBase::kTestEid, dbus_properties->iccid().value());
  179. ASSERT_TRUE(esim_profile.is_bound());
  180. mojom::ProfileInstallResult install_result = InstallProfile(
  181. esim_profile, /*wait_for_connect=*/false, /*fail_connect=*/false);
  182. EXPECT_EQ(mojom::ProfileInstallResult::kErrorNeedsConfirmationCode,
  183. install_result);
  184. histogram_tester.ExpectTotalCount(kPendingProfileLatencyHistogram, 0);
  185. histogram_tester.ExpectBucketCount(
  186. kPendingProfileInstallHistogram,
  187. HermesResponseStatus::kErrorNeedConfirmationCode,
  188. /*expected_count=*/1);
  189. // Adding a pending profile causes a list change.
  190. EXPECT_EQ(1u, observer()->profile_list_change_calls().size());
  191. // Verify that installing pending profile returns proper results
  192. // and updates esim_profile properties.
  193. install_result = InstallProfile(esim_profile, /*wait_for_connect=*/true,
  194. /*fail_connect=*/false);
  195. // Wait for property changes to propagate.
  196. base::RunLoop().RunUntilIdle();
  197. EXPECT_EQ(mojom::ProfileInstallResult::kSuccess, install_result);
  198. mojom::ESimProfilePropertiesPtr mojo_properties =
  199. GetESimProfileProperties(esim_profile);
  200. EXPECT_EQ(dbus_properties->iccid().value(), mojo_properties->iccid);
  201. EXPECT_NE(mojo_properties->state, mojom::ProfileState::kPending);
  202. // Installing a profile causes a list change.
  203. EXPECT_EQ(2u, observer()->profile_list_change_calls().size());
  204. histogram_tester.ExpectTotalCount(kPendingProfileLatencyHistogram, 1);
  205. histogram_tester.ExpectBucketCount(kPendingProfileInstallHistogram,
  206. HermesResponseStatus::kSuccess,
  207. /*expected_count=*/1);
  208. }
  209. TEST_F(ESimProfileTest, InstallProfileAlreadyConnected) {
  210. SetIsGuest(false);
  211. dbus::ObjectPath profile_path =
  212. HermesEuiccClient::Get()->GetTestInterface()->AddFakeCarrierProfile(
  213. dbus::ObjectPath(ESimTestBase::kTestEuiccPath),
  214. hermes::profile::State::kPending, /*activation_code=*/std::string(),
  215. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  216. kAddProfileWithService);
  217. HermesProfileClient::Properties* dbus_properties =
  218. HermesProfileClient::Get()->GetProperties(profile_path);
  219. mojo::Remote<mojom::ESimProfile> esim_profile = GetESimProfileForIccid(
  220. ESimTestBase::kTestEid, dbus_properties->iccid().value());
  221. HermesProfileClient::Get()->GetTestInterface()->SetEnableProfileBehavior(
  222. HermesProfileClient::TestInterface::EnableProfileBehavior::
  223. kConnectableAndConnected);
  224. mojom::ProfileInstallResult install_result =
  225. InstallProfile(esim_profile, /*wait_for_connect=*/false,
  226. /*fail_connect=*/false);
  227. EXPECT_EQ(mojom::ProfileInstallResult::kSuccess, install_result);
  228. }
  229. TEST_F(ESimProfileTest, InstallConnectFailure) {
  230. SetIsGuest(false);
  231. HermesEuiccClient::TestInterface* euicc_test =
  232. HermesEuiccClient::Get()->GetTestInterface();
  233. dbus::ObjectPath profile_path = euicc_test->AddFakeCarrierProfile(
  234. dbus::ObjectPath(ESimTestBase::kTestEuiccPath),
  235. hermes::profile::State::kPending, "",
  236. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  237. kAddProfileWithService);
  238. base::RunLoop().RunUntilIdle();
  239. HermesProfileClient::Properties* dbus_properties =
  240. HermesProfileClient::Get()->GetProperties(profile_path);
  241. mojo::Remote<mojom::ESimProfile> esim_profile = GetESimProfileForIccid(
  242. ESimTestBase::kTestEid, dbus_properties->iccid().value());
  243. // Verify that connect failures still return success code.
  244. mojom::ProfileInstallResult install_result =
  245. InstallProfile(esim_profile, /*wait_for_connect=*/true,
  246. /*fail_connect=*/true);
  247. EXPECT_EQ(mojom::ProfileInstallResult::kSuccess, install_result);
  248. }
  249. TEST_F(ESimProfileTest, UninstallProfile) {
  250. SetIsGuest(false);
  251. base::HistogramTester histogram_tester;
  252. HermesEuiccClient::TestInterface* euicc_test =
  253. HermesEuiccClient::Get()->GetTestInterface();
  254. dbus::ObjectPath active_profile_path = euicc_test->AddFakeCarrierProfile(
  255. dbus::ObjectPath(kTestEuiccPath), hermes::profile::State::kActive, "",
  256. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  257. kAddProfileWithService);
  258. dbus::ObjectPath pending_profile_path = euicc_test->AddFakeCarrierProfile(
  259. dbus::ObjectPath(kTestEuiccPath), hermes::profile::State::kPending, "",
  260. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  261. kAddProfileWithService);
  262. base::RunLoop().RunUntilIdle();
  263. EXPECT_EQ(1u, observer()->profile_list_change_calls().size());
  264. observer()->Reset();
  265. HermesProfileClient::Properties* pending_profile_dbus_properties =
  266. HermesProfileClient::Get()->GetProperties(pending_profile_path);
  267. HermesProfileClient::Properties* active_profile_dbus_properties =
  268. HermesProfileClient::Get()->GetProperties(active_profile_path);
  269. histogram_tester.ExpectTotalCount(kProfileUninstallationResultHistogram, 0);
  270. // Verify that uninstall error codes are returned properly.
  271. euicc_test->QueueHermesErrorStatus(
  272. HermesResponseStatus::kErrorInvalidResponse);
  273. mojo::Remote<mojom::ESimProfile> active_esim_profile = GetESimProfileForIccid(
  274. ESimTestBase::kTestEid, active_profile_dbus_properties->iccid().value());
  275. ASSERT_TRUE(active_esim_profile.is_bound());
  276. mojom::ESimOperationResult result = UninstallProfile(active_esim_profile);
  277. base::RunLoop().RunUntilIdle();
  278. EXPECT_EQ(mojom::ESimOperationResult::kFailure, result);
  279. EXPECT_EQ(0u, observer()->profile_list_change_calls().size());
  280. histogram_tester.ExpectTotalCount(kProfileUninstallationResultHistogram, 1);
  281. histogram_tester.ExpectBucketCount(kProfileUninstallationResultHistogram,
  282. false, 1);
  283. // Verify that pending profiles cannot be uninstalled
  284. observer()->Reset();
  285. mojo::Remote<mojom::ESimProfile> pending_esim_profile =
  286. GetESimProfileForIccid(ESimTestBase::kTestEid,
  287. pending_profile_dbus_properties->iccid().value());
  288. ASSERT_TRUE(pending_esim_profile.is_bound());
  289. result = UninstallProfile(pending_esim_profile);
  290. base::RunLoop().RunUntilIdle();
  291. EXPECT_EQ(mojom::ESimOperationResult::kFailure, result);
  292. EXPECT_EQ(0u, observer()->profile_list_change_calls().size());
  293. histogram_tester.ExpectTotalCount(kProfileUninstallationResultHistogram, 1);
  294. histogram_tester.ExpectBucketCount(kProfileUninstallationResultHistogram,
  295. false, 1);
  296. // Verify that uninstall removes the profile and notifies observers properly.
  297. observer()->Reset();
  298. result = UninstallProfile(active_esim_profile);
  299. // The state change of the ESim profile from kActive to kInactive causes a
  300. // list change observer event.
  301. ASSERT_EQ(1u, observer()->profile_list_change_calls().size());
  302. base::RunLoop().RunUntilIdle();
  303. EXPECT_EQ(mojom::ESimOperationResult::kSuccess, result);
  304. // The removal of the ESim profile causes a list change observer event.
  305. ASSERT_EQ(2u, observer()->profile_list_change_calls().size());
  306. EXPECT_EQ(1u, GetProfileList(GetEuiccForEid(ESimTestBase::kTestEid)).size());
  307. histogram_tester.ExpectTotalCount(kProfileUninstallationResultHistogram, 2);
  308. histogram_tester.ExpectBucketCount(kProfileUninstallationResultHistogram,
  309. true, 1);
  310. }
  311. TEST_F(ESimProfileTest, CannotUninstallProfileAsGuest) {
  312. SetIsGuest(true);
  313. HermesEuiccClient::TestInterface* euicc_test =
  314. HermesEuiccClient::Get()->GetTestInterface();
  315. dbus::ObjectPath active_profile_path = euicc_test->AddFakeCarrierProfile(
  316. dbus::ObjectPath(kTestEuiccPath), hermes::profile::State::kActive, "",
  317. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  318. kAddProfileWithService);
  319. HermesProfileClient::Properties* active_profile_dbus_properties =
  320. HermesProfileClient::Get()->GetProperties(active_profile_path);
  321. mojo::Remote<mojom::ESimProfile> active_esim_profile = GetESimProfileForIccid(
  322. ESimTestBase::kTestEid, active_profile_dbus_properties->iccid().value());
  323. mojom::ESimOperationResult result = UninstallProfile(active_esim_profile);
  324. base::RunLoop().RunUntilIdle();
  325. EXPECT_EQ(mojom::ESimOperationResult::kFailure, result);
  326. }
  327. TEST_F(ESimProfileTest, SetProfileNickName) {
  328. SetIsGuest(false);
  329. const std::u16string test_nickname = u"Test nickname";
  330. base::HistogramTester histogram_tester;
  331. HermesEuiccClient::TestInterface* euicc_test =
  332. HermesEuiccClient::Get()->GetTestInterface();
  333. dbus::ObjectPath active_profile_path = euicc_test->AddFakeCarrierProfile(
  334. dbus::ObjectPath(kTestEuiccPath), hermes::profile::State::kActive, "",
  335. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  336. kAddProfileWithService);
  337. dbus::ObjectPath pending_profile_path = euicc_test->AddFakeCarrierProfile(
  338. dbus::ObjectPath(kTestEuiccPath), hermes::profile::State::kPending, "",
  339. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  340. kAddProfileWithService);
  341. base::RunLoop().RunUntilIdle();
  342. EXPECT_EQ(1u, observer()->profile_list_change_calls().size());
  343. observer()->Reset();
  344. HermesProfileClient::Properties* pending_profile_dbus_properties =
  345. HermesProfileClient::Get()->GetProperties(pending_profile_path);
  346. HermesProfileClient::Properties* active_profile_dbus_properties =
  347. HermesProfileClient::Get()->GetProperties(active_profile_path);
  348. // Verify that pending profiles cannot be modified.
  349. mojo::Remote<mojom::ESimProfile> pending_esim_profile =
  350. GetESimProfileForIccid(ESimTestBase::kTestEid,
  351. pending_profile_dbus_properties->iccid().value());
  352. ASSERT_TRUE(pending_esim_profile.is_bound());
  353. mojom::ESimOperationResult result =
  354. SetProfileNickname(pending_esim_profile, test_nickname);
  355. base::RunLoop().RunUntilIdle();
  356. EXPECT_EQ(mojom::ESimOperationResult::kFailure, result);
  357. EXPECT_EQ(0u, observer()->profile_change_calls().size());
  358. // Verify that nickname can be set on active profiles.
  359. histogram_tester.ExpectTotalCount(kProfileRenameResultHistogram, 0);
  360. mojo::Remote<mojom::ESimProfile> active_esim_profile = GetESimProfileForIccid(
  361. ESimTestBase::kTestEid, active_profile_dbus_properties->iccid().value());
  362. ASSERT_TRUE(active_esim_profile.is_bound());
  363. result = SetProfileNickname(active_esim_profile, test_nickname);
  364. base::RunLoop().RunUntilIdle();
  365. EXPECT_EQ(mojom::ESimOperationResult::kSuccess, result);
  366. histogram_tester.ExpectTotalCount(kProfileRenameResultHistogram, 1);
  367. histogram_tester.ExpectBucketCount(kProfileRenameResultHistogram, true, 1);
  368. mojom::ESimProfilePropertiesPtr active_profile_mojo_properties =
  369. GetESimProfileProperties(active_esim_profile);
  370. EXPECT_EQ(test_nickname, active_profile_mojo_properties->nickname);
  371. }
  372. TEST_F(ESimProfileTest, CannotSetProfileNickNameAsGuest) {
  373. SetIsGuest(true);
  374. HermesEuiccClient::TestInterface* euicc_test =
  375. HermesEuiccClient::Get()->GetTestInterface();
  376. dbus::ObjectPath active_profile_path = euicc_test->AddFakeCarrierProfile(
  377. dbus::ObjectPath(kTestEuiccPath), hermes::profile::State::kActive, "",
  378. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  379. kAddProfileWithService);
  380. HermesProfileClient::Properties* active_profile_dbus_properties =
  381. HermesProfileClient::Get()->GetProperties(active_profile_path);
  382. mojo::Remote<mojom::ESimProfile> active_esim_profile = GetESimProfileForIccid(
  383. ESimTestBase::kTestEid, active_profile_dbus_properties->iccid().value());
  384. mojom::ESimOperationResult result =
  385. SetProfileNickname(active_esim_profile, u"Nickname");
  386. base::RunLoop().RunUntilIdle();
  387. EXPECT_EQ(mojom::ESimOperationResult::kFailure, result);
  388. }
  389. } // namespace ash::cellular_setup