euicc_unittest.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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 "ash/services/cellular_setup/euicc.h"
  5. #include <utility>
  6. #include "ash/services/cellular_setup/esim_test_base.h"
  7. #include "ash/services/cellular_setup/esim_test_utils.h"
  8. #include "base/run_loop.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 "chromeos/ash/components/network/network_type_pattern.h"
  15. #include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
  16. #include "mojo/public/cpp/bindings/pending_remote.h"
  17. #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
  18. namespace ash::cellular_setup {
  19. namespace {
  20. const char kInstallViaQrCodeHistogram[] =
  21. "Network.Cellular.ESim.InstallViaQrCode.Result";
  22. using InstallResultPair = std::pair<mojom::ProfileInstallResult,
  23. mojo::PendingRemote<mojom::ESimProfile>>;
  24. mojom::ESimOperationResult RequestPendingProfiles(
  25. mojo::Remote<mojom::Euicc>& euicc) {
  26. mojom::ESimOperationResult result;
  27. base::RunLoop run_loop;
  28. euicc->RequestPendingProfiles(base::BindOnce(
  29. [](mojom::ESimOperationResult* out, base::OnceClosure quit_closure,
  30. mojom::ESimOperationResult result) {
  31. *out = result;
  32. std::move(quit_closure).Run();
  33. },
  34. &result, run_loop.QuitClosure()));
  35. run_loop.Run();
  36. return result;
  37. }
  38. } // namespace
  39. class EuiccTest : public ESimTestBase {
  40. public:
  41. EuiccTest() = default;
  42. EuiccTest(const EuiccTest&) = delete;
  43. EuiccTest& operator=(const EuiccTest&) = delete;
  44. void SetUp() override {
  45. ESimTestBase::SetUp();
  46. SetupEuicc();
  47. }
  48. void TearDown() override {
  49. HermesProfileClient::Get()->GetTestInterface()->SetEnableProfileBehavior(
  50. HermesProfileClient::TestInterface::EnableProfileBehavior::
  51. kConnectableButNotConnected);
  52. }
  53. InstallResultPair InstallProfileFromActivationCode(
  54. const mojo::Remote<mojom::Euicc>& euicc,
  55. const std::string& activation_code,
  56. const std::string& confirmation_code,
  57. bool wait_for_create,
  58. bool wait_for_connect,
  59. bool fail_connect) {
  60. mojom::ProfileInstallResult out_install_result;
  61. mojo::PendingRemote<mojom::ESimProfile> out_esim_profile;
  62. base::RunLoop run_loop;
  63. euicc->InstallProfileFromActivationCode(
  64. activation_code, confirmation_code, /*is_install_via_qr_code=*/true,
  65. base::BindLambdaForTesting(
  66. [&](mojom::ProfileInstallResult install_result,
  67. mojo::PendingRemote<mojom::ESimProfile> esim_profile) {
  68. out_install_result = install_result;
  69. out_esim_profile = std::move(esim_profile);
  70. run_loop.Quit();
  71. }));
  72. if (wait_for_create) {
  73. base::RunLoop().RunUntilIdle();
  74. // Set the enable notify prolie list update back to true if it was false
  75. // before and fire the pending notify profile list update and that should
  76. // make the pending create callback complete.
  77. cellular_esim_profile_handler()->SetEnableNotifyProfileListUpdate(true);
  78. }
  79. FastForwardProfileRefreshDelay();
  80. if (wait_for_connect) {
  81. base::RunLoop().RunUntilIdle();
  82. EXPECT_LE(1u, network_connection_handler()->connect_calls().size());
  83. if (fail_connect) {
  84. network_connection_handler()
  85. ->connect_calls()
  86. .back()
  87. .InvokeErrorCallback("fake_error_name");
  88. } else {
  89. network_connection_handler()
  90. ->connect_calls()
  91. .back()
  92. .InvokeSuccessCallback();
  93. }
  94. }
  95. run_loop.Run();
  96. return std::make_pair(out_install_result, std::move(out_esim_profile));
  97. }
  98. };
  99. TEST_F(EuiccTest, GetProperties) {
  100. mojo::Remote<mojom::Euicc> euicc = GetEuiccForEid(ESimTestBase::kTestEid);
  101. ASSERT_TRUE(euicc.is_bound());
  102. mojom::EuiccPropertiesPtr properties = GetEuiccProperties(euicc);
  103. EXPECT_EQ(ESimTestBase::kTestEid, properties->eid);
  104. EXPECT_EQ(true, properties->is_active);
  105. }
  106. TEST_F(EuiccTest, GetProfileList) {
  107. mojo::Remote<mojom::Euicc> euicc = GetEuiccForEid(ESimTestBase::kTestEid);
  108. ASSERT_TRUE(euicc.is_bound());
  109. std::vector<mojo::PendingRemote<mojom::ESimProfile>> esim_profile_list =
  110. GetProfileList(euicc);
  111. EXPECT_EQ(0u, esim_profile_list.size());
  112. HermesEuiccClient::TestInterface* euicc_test =
  113. HermesEuiccClient::Get()->GetTestInterface();
  114. dbus::ObjectPath active_profile_path = euicc_test->AddFakeCarrierProfile(
  115. dbus::ObjectPath(kTestEuiccPath), hermes::profile::State::kActive, "",
  116. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  117. kAddProfileWithService);
  118. dbus::ObjectPath pending_profile_path = euicc_test->AddFakeCarrierProfile(
  119. dbus::ObjectPath(kTestEuiccPath), hermes::profile::State::kPending, "",
  120. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  121. kAddProfileWithService);
  122. base::RunLoop().RunUntilIdle();
  123. esim_profile_list = GetProfileList(euicc);
  124. EXPECT_EQ(2u, esim_profile_list.size());
  125. }
  126. TEST_F(EuiccTest, InstallProfileFromActivationCode) {
  127. base::HistogramTester histogram_tester;
  128. mojo::Remote<mojom::Euicc> euicc = GetEuiccForEid(ESimTestBase::kTestEid);
  129. ASSERT_TRUE(euicc.is_bound());
  130. HermesEuiccClient::TestInterface* euicc_test =
  131. HermesEuiccClient::Get()->GetTestInterface();
  132. // Verify that the callback is not completed if update profile list
  133. // notification is not fired and save the callback until an update profile
  134. // list gets called.
  135. cellular_esim_profile_handler()->SetEnableNotifyProfileListUpdate(false);
  136. InstallResultPair result_pair = InstallProfileFromActivationCode(
  137. euicc, euicc_test->GenerateFakeActivationCode(),
  138. /*confirmation_code=*/std::string(), /*wait_for_create=*/true,
  139. /*wait_for_connect=*/false, /*fail_connect=*/false);
  140. EXPECT_EQ(mojom::ProfileInstallResult::kSuccess, result_pair.first);
  141. EXPECT_TRUE(result_pair.second.is_valid());
  142. histogram_tester.ExpectBucketCount(kInstallViaQrCodeHistogram,
  143. HermesResponseStatus::kSuccess,
  144. /*expected_count=*/1);
  145. // Verify that install succeeds when valid activation code is passed.
  146. result_pair = InstallProfileFromActivationCode(
  147. euicc, euicc_test->GenerateFakeActivationCode(),
  148. /*confirmation_code=*/std::string(), /*wait_for_create=*/false,
  149. /*wait_for_connect=*/false, /*fail_connect=*/false);
  150. EXPECT_EQ(mojom::ProfileInstallResult::kSuccess, result_pair.first);
  151. EXPECT_TRUE(result_pair.second.is_valid());
  152. histogram_tester.ExpectBucketCount(kInstallViaQrCodeHistogram,
  153. HermesResponseStatus::kSuccess,
  154. /*expected_count=*/2);
  155. }
  156. TEST_F(EuiccTest, InstallProfileAlreadyConnected) {
  157. mojo::Remote<mojom::Euicc> euicc = GetEuiccForEid(ESimTestBase::kTestEid);
  158. ASSERT_TRUE(euicc.is_bound());
  159. HermesProfileClient::Get()->GetTestInterface()->SetEnableProfileBehavior(
  160. HermesProfileClient::TestInterface::EnableProfileBehavior::
  161. kConnectableAndConnected);
  162. InstallResultPair result_pair = InstallProfileFromActivationCode(
  163. euicc,
  164. HermesEuiccClient::Get()
  165. ->GetTestInterface()
  166. ->GenerateFakeActivationCode(),
  167. /*confirmation_code=*/std::string(), /*wait_for_create=*/false,
  168. /*wait_for_connect=*/false, /*fail_connect=*/false);
  169. EXPECT_EQ(mojom::ProfileInstallResult::kSuccess, result_pair.first);
  170. }
  171. TEST_F(EuiccTest, InstallPendingProfileFromActivationCode) {
  172. mojo::Remote<mojom::Euicc> euicc = GetEuiccForEid(ESimTestBase::kTestEid);
  173. ASSERT_TRUE(euicc.is_bound());
  174. HermesEuiccClient::TestInterface* euicc_test =
  175. HermesEuiccClient::Get()->GetTestInterface();
  176. // Verify that installing a pending profile with its activation code returns
  177. // proper status code and profile object.
  178. dbus::ObjectPath profile_path = euicc_test->AddFakeCarrierProfile(
  179. dbus::ObjectPath(kTestEuiccPath), hermes::profile::State::kPending, "",
  180. HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
  181. kAddProfileWithService);
  182. base::RunLoop().RunUntilIdle();
  183. HermesProfileClient::Properties* dbus_properties =
  184. HermesProfileClient::Get()->GetProperties(profile_path);
  185. // Adding a pending profile causes a list change.
  186. EXPECT_EQ(1u, observer()->profile_list_change_calls().size());
  187. InstallResultPair result_pair = InstallProfileFromActivationCode(
  188. euicc, dbus_properties->activation_code().value(),
  189. /*confirmation_code=*/std::string(), /*wait_for_create=*/false,
  190. /*wait_for_connect=*/true, /*fail_connect=*/false);
  191. EXPECT_EQ(mojom::ProfileInstallResult::kSuccess, result_pair.first);
  192. ASSERT_TRUE(result_pair.second.is_valid());
  193. mojo::Remote<mojom::ESimProfile> esim_profile(std::move(result_pair.second));
  194. mojom::ESimProfilePropertiesPtr mojo_properties =
  195. GetESimProfileProperties(esim_profile);
  196. EXPECT_EQ(dbus_properties->iccid().value(), mojo_properties->iccid);
  197. // Installing a profile causes a list change.
  198. EXPECT_EQ(2u, observer()->profile_list_change_calls().size());
  199. }
  200. TEST_F(EuiccTest, RequestPendingProfiles) {
  201. static const char kOperationResultMetric[] =
  202. "Network.Cellular.ESim.RequestPendingProfiles.OperationResult";
  203. base::HistogramTester histogram_tester;
  204. mojo::Remote<mojom::Euicc> euicc = GetEuiccForEid(ESimTestBase::kTestEid);
  205. ASSERT_TRUE(euicc.is_bound());
  206. HermesEuiccClient::TestInterface* euicc_test =
  207. HermesEuiccClient::Get()->GetTestInterface();
  208. // Verify that pending profile request errors are return properly.
  209. euicc_test->QueueHermesErrorStatus(HermesResponseStatus::kErrorNoResponse);
  210. EXPECT_EQ(mojom::ESimOperationResult::kFailure,
  211. RequestPendingProfiles(euicc));
  212. histogram_tester.ExpectBucketCount(
  213. kOperationResultMetric,
  214. Euicc::RequestPendingProfilesResult::kInhibitFailed,
  215. /*expected_count=*/1);
  216. EXPECT_EQ(0u, observer()->profile_list_change_calls().size());
  217. constexpr base::TimeDelta kHermesInteractiveDelay = base::Milliseconds(3000);
  218. HermesEuiccClient::Get()->GetTestInterface()->SetInteractiveDelay(
  219. kHermesInteractiveDelay);
  220. // Verify that successful request returns correct status code.
  221. EXPECT_EQ(mojom::ESimOperationResult::kSuccess,
  222. RequestPendingProfiles(euicc));
  223. // Before requesting pending profiles, we request installed profiles, so we
  224. // expect that there will be 2 delays (one for installed, one for pending).
  225. histogram_tester.ExpectTimeBucketCount(
  226. "Network.Cellular.ESim.ProfileDiscovery.Latency",
  227. 2 * kHermesInteractiveDelay, 1);
  228. histogram_tester.ExpectTotalCount(
  229. "Network.Cellular.ESim.ProfileDiscovery.Latency", 1);
  230. histogram_tester.ExpectBucketCount(
  231. kOperationResultMetric, Euicc::RequestPendingProfilesResult::kSuccess,
  232. /*expected_count=*/1);
  233. }
  234. TEST_F(EuiccTest, GetEidQRCode) {
  235. mojo::Remote<mojom::Euicc> euicc = GetEuiccForEid(ESimTestBase::kTestEid);
  236. ASSERT_TRUE(euicc.is_bound());
  237. mojom::QRCodePtr qr_code_result;
  238. base::RunLoop run_loop;
  239. euicc->GetEidQRCode(base::BindOnce(
  240. [](mojom::QRCodePtr* out, base::OnceClosure quit_closure,
  241. mojom::QRCodePtr properties) {
  242. *out = std::move(properties);
  243. std::move(quit_closure).Run();
  244. },
  245. &qr_code_result, run_loop.QuitClosure()));
  246. run_loop.Run();
  247. ASSERT_FALSE(qr_code_result.is_null());
  248. EXPECT_LT(0, qr_code_result->size);
  249. }
  250. } // namespace ash::cellular_setup