tether_controller_impl_unittest.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  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/components/phonehub/tether_controller_impl.h"
  5. #include <memory>
  6. #include "ash/components/phonehub/fake_user_action_recorder.h"
  7. #include "ash/components/phonehub/mutable_phone_model.h"
  8. #include "ash/components/phonehub/phone_model_test_util.h"
  9. #include "ash/components/phonehub/phone_status_model.h"
  10. #include "ash/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h"
  11. #include "base/memory/weak_ptr.h"
  12. #include "base/strings/stringprintf.h"
  13. #include "base/strings/utf_string_conversions.h"
  14. #include "base/test/task_environment.h"
  15. #include "chromeos/ash/components/network/network_state_handler.h"
  16. #include "chromeos/ash/components/network/network_state_test_helper.h"
  17. #include "chromeos/services/network_config/in_process_instance.h"
  18. #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
  19. #include "testing/gtest/include/gtest/gtest.h"
  20. namespace ash {
  21. namespace phonehub {
  22. namespace {
  23. using ::chromeos::network_config::mojom::ConnectionStateType;
  24. using ::chromeos::network_config::mojom::NetworkStatePropertiesPtr;
  25. using ::chromeos::network_config::mojom::StartConnectResult;
  26. using multidevice_setup::mojom::Feature;
  27. using multidevice_setup::mojom::FeatureState;
  28. constexpr char kWifiGuid[] = "WifiGuid";
  29. constexpr char kTetherGuid[] = "TetherGuid";
  30. constexpr char kTetherNetworkName[] = "TetherNetworkName";
  31. constexpr char kTetherNetworkCarrier[] = "TetherNetworkCarrier";
  32. constexpr int kBatteryPercentage = 100;
  33. constexpr int kSignalStrength = 100;
  34. constexpr bool kHasConnectedToHost = true;
  35. class FakeObserver : public TetherController::Observer {
  36. public:
  37. FakeObserver() = default;
  38. ~FakeObserver() override = default;
  39. size_t num_status_changes() const { return num_status_changes_; }
  40. size_t num_scan_failed() const { return num_scan_failed_; }
  41. // TetherController::Observer:
  42. void OnTetherStatusChanged() override { ++num_status_changes_; }
  43. void OnAttemptConnectionScanFailed() override { ++num_scan_failed_; }
  44. private:
  45. size_t num_status_changes_ = 0;
  46. size_t num_scan_failed_ = 0;
  47. };
  48. PhoneStatusModel CreateTestPhoneStatusModel(
  49. PhoneStatusModel::MobileStatus mobile_status =
  50. PhoneStatusModel::MobileStatus::kSimWithReception) {
  51. PhoneStatusModel::MobileConnectionMetadata metadata;
  52. metadata.signal_strength = PhoneStatusModel::SignalStrength::kFourBars;
  53. metadata.mobile_provider =
  54. mobile_status == PhoneStatusModel::MobileStatus::kSimWithReception
  55. ? std::u16string(kFakeMobileProviderName)
  56. : std::u16string();
  57. return PhoneStatusModel(mobile_status, metadata,
  58. PhoneStatusModel::ChargingState::kNotCharging,
  59. PhoneStatusModel::BatterySaverState::kOff,
  60. /*battery_percentage=*/100u);
  61. }
  62. } // namespace
  63. class TetherControllerImplTest : public testing::Test {
  64. protected:
  65. friend class TetherControllerImpl;
  66. TetherControllerImplTest() = default;
  67. TetherControllerImplTest(const TetherControllerImplTest&) = delete;
  68. TetherControllerImplTest& operator=(const TetherControllerImplTest&) = delete;
  69. ~TetherControllerImplTest() override = default;
  70. class FakeTetherNetworkConnector
  71. : public TetherControllerImpl::TetherNetworkConnector {
  72. public:
  73. FakeTetherNetworkConnector() {
  74. chromeos::network_config::BindToInProcessInstance(
  75. cros_network_config_.BindNewPipeAndPassReceiver());
  76. }
  77. ~FakeTetherNetworkConnector() override = default;
  78. void StartConnect(const std::string& guid,
  79. StartConnectCallback callback) override {
  80. start_connect_callback_ = std::move(callback);
  81. }
  82. void StartDisconnect(const std::string& guid,
  83. StartDisconnectCallback callback) override {
  84. start_disconnect_callback_ = std::move(callback);
  85. }
  86. void GetNetworkStateList(
  87. chromeos::network_config::mojom::NetworkFilterPtr filter,
  88. GetNetworkStateListCallback callback) override {
  89. cros_network_config_->GetNetworkStateList(
  90. std::move(filter),
  91. base::BindOnce(
  92. &FakeTetherNetworkConnector::OnVisibleTetherNetworkFetched,
  93. weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
  94. }
  95. void SetNextConnectionStateType(ConnectionStateType connection_state) {
  96. connection_state_ = connection_state;
  97. }
  98. void OnVisibleTetherNetworkFetched(
  99. GetNetworkStateListCallback callback,
  100. std::vector<NetworkStatePropertiesPtr> networks) {
  101. if (connection_state_.has_value() && networks.size() == 1) {
  102. networks[0]->connection_state = *connection_state_;
  103. connection_state_ = absl::nullopt;
  104. }
  105. std::move(callback).Run(std::move(networks));
  106. }
  107. bool DoesPendingStartConnectCallbackExist() {
  108. return !start_connect_callback_.is_null();
  109. }
  110. bool DoesPendingDisconnectCallbackExist() {
  111. return !start_disconnect_callback_.is_null();
  112. }
  113. void InvokeStartConnectCallbackWithFakeResult(
  114. StartConnectResult result = StartConnectResult::kSuccess,
  115. const std::string& message = "") {
  116. std::move(start_connect_callback_).Run(result, message);
  117. }
  118. void InvokeDisconnectCallbackWithRealResults(std::string service_path) {
  119. cros_network_config_->StartDisconnect(
  120. service_path, std::move(start_disconnect_callback_));
  121. }
  122. void InvokeDisconnectCallbackWithFakeParams(bool success = true) {
  123. std::move(start_disconnect_callback_).Run(success);
  124. }
  125. private:
  126. mojo::Remote<chromeos::network_config::mojom::CrosNetworkConfig>
  127. cros_network_config_;
  128. absl::optional<ConnectionStateType> connection_state_;
  129. StartConnectCallback start_connect_callback_;
  130. StartDisconnectCallback start_disconnect_callback_;
  131. base::WeakPtrFactory<FakeTetherNetworkConnector> weak_ptr_factory_{this};
  132. };
  133. // testing::Test:
  134. void SetUp() override {
  135. NetworkHandler::Initialize();
  136. base::RunLoop().RunUntilIdle();
  137. service_path_ =
  138. cros_network_config_helper_.network_state_helper().ConfigureService(
  139. base::StringPrintf(
  140. R"({"GUID": "%s", "Type": "wifi",
  141. "State": "ready", "Strength": 100,
  142. "Connectable": true})",
  143. kWifiGuid));
  144. fake_phone_model_.SetPhoneStatusModel(CreateTestPhoneStatusModel());
  145. controller_ =
  146. base::WrapUnique<TetherControllerImpl>(new TetherControllerImpl(
  147. &fake_phone_model_, &fake_user_action_recorder_,
  148. &fake_multidevice_setup_client_,
  149. std::make_unique<FakeTetherNetworkConnector>()));
  150. controller_->AddObserver(&fake_observer_);
  151. }
  152. void TearDown() override {
  153. controller_->RemoveObserver(&fake_observer_);
  154. NetworkHandler::Shutdown();
  155. testing::Test::TearDown();
  156. }
  157. NetworkStateHandler* network_state_handler() {
  158. return cros_network_config_helper_.network_state_helper()
  159. .network_state_handler();
  160. }
  161. FakeTetherNetworkConnector* fake_tether_network_connector() {
  162. return static_cast<FakeTetherNetworkConnector*>(
  163. controller_->connector_.get());
  164. }
  165. void EnableTetherDevice() {
  166. network_state_handler()->SetTetherTechnologyState(
  167. NetworkStateHandler::TechnologyState::TECHNOLOGY_ENABLED);
  168. base::RunLoop().RunUntilIdle();
  169. }
  170. void DisconnectTetherDevice() {
  171. network_state_handler()->SetTetherTechnologyState(
  172. NetworkStateHandler::TechnologyState::TECHNOLOGY_AVAILABLE);
  173. base::RunLoop().RunUntilIdle();
  174. }
  175. void AddVisibleTetherNetwork() {
  176. network_state_handler()->AddTetherNetworkState(
  177. kTetherGuid, kTetherNetworkName, kTetherNetworkCarrier,
  178. kBatteryPercentage, kSignalStrength, kHasConnectedToHost);
  179. network_state_handler()->AssociateTetherNetworkStateWithWifiNetwork(
  180. kTetherGuid, kWifiGuid);
  181. base::RunLoop().RunUntilIdle();
  182. }
  183. void RemoveVisibleTetherNetwork() {
  184. network_state_handler()->RemoveTetherNetworkState(kTetherGuid);
  185. base::RunLoop().RunUntilIdle();
  186. }
  187. void SetTetherNetworkStateConnected() {
  188. network_state_handler()->SetTetherNetworkStateConnected(kTetherGuid);
  189. base::RunLoop().RunUntilIdle();
  190. }
  191. void SetTetherNetworkStateConnecting() {
  192. network_state_handler()->SetTetherNetworkStateConnecting(kTetherGuid);
  193. base::RunLoop().RunUntilIdle();
  194. }
  195. void SetTetherNetworkStateDisconnected() {
  196. network_state_handler()->SetTetherNetworkStateDisconnected(kTetherGuid);
  197. base::RunLoop().RunUntilIdle();
  198. }
  199. void SetTetherScanState(bool is_scanning) {
  200. network_state_handler()->SetTetherScanState(is_scanning);
  201. base::RunLoop().RunUntilIdle();
  202. }
  203. TetherController::Status GetStatus() const {
  204. return controller_->GetStatus();
  205. }
  206. void SetMultideviceSetupFeatureState(FeatureState feature_state) {
  207. fake_multidevice_setup_client_.SetFeatureState(Feature::kInstantTethering,
  208. feature_state);
  209. }
  210. void InvokeDisconnectCallbackWithRealResults() {
  211. fake_tether_network_connector()->InvokeDisconnectCallbackWithRealResults(
  212. service_path_);
  213. base::RunLoop().RunUntilIdle();
  214. }
  215. void InvokePendingSetFeatureEnabledStateCallback(
  216. bool success,
  217. bool expected_enabled = true) {
  218. if (success)
  219. SetMultideviceSetupFeatureState(FeatureState::kEnabledByUser);
  220. fake_multidevice_setup_client_.InvokePendingSetFeatureEnabledStateCallback(
  221. Feature::kInstantTethering,
  222. /*expected_enabled=*/expected_enabled, absl::nullopt, success);
  223. }
  224. void AttemptConnection() {
  225. size_t num_recorded_connection_attempts_before_call =
  226. fake_user_action_recorder_.num_tether_attempts();
  227. controller_->AttemptConnection();
  228. EXPECT_EQ(num_recorded_connection_attempts_before_call + 1,
  229. fake_user_action_recorder_.num_tether_attempts());
  230. }
  231. void Disconnect() { controller_->Disconnect(); }
  232. size_t GetNumObserverStatusChanged() const {
  233. return fake_observer_.num_status_changes();
  234. }
  235. size_t GetNumObserverScanFailed() const {
  236. return fake_observer_.num_scan_failed();
  237. }
  238. MutablePhoneModel* phone_model() { return &fake_phone_model_; }
  239. private:
  240. base::test::TaskEnvironment task_environment_;
  241. network_config::CrosNetworkConfigTestHelper cros_network_config_helper_;
  242. std::string service_path_;
  243. multidevice_setup::FakeMultiDeviceSetupClient fake_multidevice_setup_client_;
  244. MutablePhoneModel fake_phone_model_;
  245. FakeUserActionRecorder fake_user_action_recorder_;
  246. FakeObserver fake_observer_;
  247. std::unique_ptr<TetherControllerImpl> controller_;
  248. };
  249. TEST_F(TetherControllerImplTest,
  250. DisconnectCompletesAfterOnActiveNetworksChanged) {
  251. SetMultideviceSetupFeatureState(FeatureState::kEnabledByUser);
  252. EnableTetherDevice();
  253. AddVisibleTetherNetwork();
  254. // Disconnect from a connecting state.
  255. AttemptConnection();
  256. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  257. SetTetherNetworkStateConnecting();
  258. Disconnect();
  259. // Simulate OnActiveNetworksChanged() being called after Disconnect()
  260. // is requested when Bluetooth is on but hotspot is off, yielding a
  261. // ConnectionStateType::kConnecting tether network instead of a
  262. // ConnectionStateType::kDisconnected network.
  263. fake_tether_network_connector()->SetNextConnectionStateType(
  264. ConnectionStateType::kConnecting);
  265. SetTetherNetworkStateDisconnected();
  266. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  267. // Upon invoking the Disconnect callback, a refetch occurs.
  268. EXPECT_TRUE(
  269. fake_tether_network_connector()->DoesPendingDisconnectCallbackExist());
  270. InvokeDisconnectCallbackWithRealResults();
  271. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionAvailable);
  272. }
  273. TEST_F(TetherControllerImplTest, ExternalTetherChangesReflectToStatus) {
  274. EXPECT_EQ(GetStatus(), TetherController::Status::kIneligibleForFeature);
  275. SetMultideviceSetupFeatureState(FeatureState::kEnabledByUser);
  276. EXPECT_EQ(GetNumObserverStatusChanged(), 1U);
  277. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  278. // Tether device and network must be enabled for status changes other than
  279. // kIneligibleForFeature or kConnectionUnavailable to occur.
  280. EnableTetherDevice();
  281. AddVisibleTetherNetwork();
  282. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionAvailable);
  283. EXPECT_EQ(GetNumObserverStatusChanged(), 2U);
  284. // Starts connecting to tether network.
  285. SetTetherNetworkStateConnecting();
  286. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  287. EXPECT_EQ(GetNumObserverStatusChanged(), 3U);
  288. // Connected to tether network.
  289. SetTetherNetworkStateConnected();
  290. EXPECT_EQ(GetStatus(), TetherController::Status::kConnected);
  291. EXPECT_EQ(GetNumObserverStatusChanged(), 4U);
  292. // Tether network disconnects on it's own.
  293. SetTetherNetworkStateDisconnected();
  294. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionAvailable);
  295. EXPECT_EQ(GetNumObserverStatusChanged(), 5U);
  296. // Tether network becomes unavailable.
  297. RemoveVisibleTetherNetwork();
  298. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  299. EXPECT_EQ(GetNumObserverStatusChanged(), 6U);
  300. // Phone status changed to no reception.
  301. phone_model()->SetPhoneStatusModel(CreateTestPhoneStatusModel(
  302. PhoneStatusModel::MobileStatus::kSimButNoReception));
  303. EXPECT_EQ(GetStatus(), TetherController::Status::kNoReception);
  304. EXPECT_EQ(GetNumObserverStatusChanged(), 7U);
  305. // Phone status changed to no SIM.
  306. phone_model()->SetPhoneStatusModel(
  307. CreateTestPhoneStatusModel(PhoneStatusModel::MobileStatus::kNoSim));
  308. EXPECT_EQ(GetStatus(), TetherController::Status::kNoReception);
  309. EXPECT_EQ(GetNumObserverStatusChanged(), 7U);
  310. // Tether feature becomes unsupported,
  311. SetMultideviceSetupFeatureState(FeatureState::kNotSupportedByPhone);
  312. EXPECT_EQ(GetStatus(), TetherController::Status::kIneligibleForFeature);
  313. EXPECT_EQ(GetNumObserverStatusChanged(), 8U);
  314. // Tether feature becomes supported, the status becomes kNoReception again.
  315. SetMultideviceSetupFeatureState(FeatureState::kEnabledByUser);
  316. EXPECT_EQ(GetStatus(), TetherController::Status::kNoReception);
  317. EXPECT_EQ(GetNumObserverStatusChanged(), 9U);
  318. // Phone status changed to having reception. Connection is still unavailable.
  319. phone_model()->SetPhoneStatusModel(CreateTestPhoneStatusModel(
  320. PhoneStatusModel::MobileStatus::kSimWithReception));
  321. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  322. EXPECT_EQ(GetNumObserverStatusChanged(), 10U);
  323. // Phone Model is lost, connection is still unavailable.
  324. phone_model()->SetPhoneStatusModel(absl::nullopt);
  325. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  326. EXPECT_EQ(GetNumObserverStatusChanged(), 10U);
  327. // Even though there is no Phone Model, adding a visible tether network
  328. // will cause the controller to indicate a connection is available.
  329. AddVisibleTetherNetwork();
  330. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionAvailable);
  331. EXPECT_EQ(GetNumObserverStatusChanged(), 11U);
  332. // Even though there is no Phone Model, connecting to a visible tether network
  333. // externally (e.g via OS Settings) will cause the controller to indicate a
  334. // connecting tether state.
  335. SetTetherNetworkStateConnecting();
  336. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  337. EXPECT_EQ(GetNumObserverStatusChanged(), 12U);
  338. // Even though there is no Phone Model, a connection to a visible tether
  339. // network externally (e.g via OS Settings) will cause the controller to
  340. // indicate a connected tether state.
  341. SetTetherNetworkStateConnected();
  342. EXPECT_EQ(GetStatus(), TetherController::Status::kConnected);
  343. EXPECT_EQ(GetNumObserverStatusChanged(), 13U);
  344. }
  345. TEST_F(TetherControllerImplTest, AttemptConnectDisconnect) {
  346. SetMultideviceSetupFeatureState(FeatureState::kEnabledByUser);
  347. EnableTetherDevice();
  348. AddVisibleTetherNetwork();
  349. AttemptConnection();
  350. EXPECT_TRUE(
  351. fake_tether_network_connector()->DoesPendingStartConnectCallbackExist());
  352. // Upon completing the connection, the status should no longer be connecting.
  353. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  354. fake_tether_network_connector()->InvokeStartConnectCallbackWithFakeResult();
  355. EXPECT_NE(GetStatus(), TetherController::Status::kConnecting);
  356. // Disconnect from a connected state.
  357. SetTetherNetworkStateConnected();
  358. Disconnect();
  359. EXPECT_TRUE(
  360. fake_tether_network_connector()->DoesPendingDisconnectCallbackExist());
  361. fake_tether_network_connector()->InvokeDisconnectCallbackWithFakeParams();
  362. SetTetherNetworkStateDisconnected();
  363. // Disconnect from a connecting state.
  364. AttemptConnection();
  365. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  366. Disconnect();
  367. EXPECT_TRUE(
  368. fake_tether_network_connector()->DoesPendingDisconnectCallbackExist());
  369. fake_tether_network_connector()->InvokeDisconnectCallbackWithFakeParams();
  370. AttemptConnection();
  371. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  372. Disconnect();
  373. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionAvailable);
  374. EXPECT_TRUE(
  375. fake_tether_network_connector()->DoesPendingDisconnectCallbackExist());
  376. AttemptConnection();
  377. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  378. fake_tether_network_connector()->InvokeDisconnectCallbackWithFakeParams();
  379. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  380. // Disconnect from a disconnected state.
  381. RemoveVisibleTetherNetwork();
  382. AttemptConnection();
  383. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  384. Disconnect();
  385. EXPECT_FALSE(
  386. fake_tether_network_connector()->DoesPendingDisconnectCallbackExist());
  387. }
  388. TEST_F(TetherControllerImplTest, AttemptConnectFeatureOffNetworkExists) {
  389. SetMultideviceSetupFeatureState(FeatureState::kDisabledByUser);
  390. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  391. // Test enable flow when a tether device initially exists.
  392. EnableTetherDevice();
  393. AddVisibleTetherNetwork();
  394. AttemptConnection();
  395. // Should be set connecting even before feature is enabled.
  396. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  397. // Should still be connecting when feature becomes enabled.
  398. InvokePendingSetFeatureEnabledStateCallback(/*success=*/true);
  399. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  400. // Connecting to tether device.
  401. SetTetherNetworkStateConnecting();
  402. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  403. // Connected to tether network.
  404. AddVisibleTetherNetwork();
  405. SetTetherNetworkStateConnected();
  406. EXPECT_EQ(GetStatus(), TetherController::Status::kConnected);
  407. EXPECT_EQ(GetNumObserverStatusChanged(), 3U);
  408. // Tether network is lost.
  409. RemoveVisibleTetherNetwork();
  410. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  411. }
  412. TEST_F(TetherControllerImplTest, AttemptConnectFeatureFailedToEnable) {
  413. EnableTetherDevice();
  414. // Test enable flow when feature fails to turn on.
  415. SetMultideviceSetupFeatureState(FeatureState::kDisabledByUser);
  416. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  417. AttemptConnection();
  418. // Should be set connecting even before feature is enabled.
  419. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  420. // Should fail to connect if feature does not successfully turn on.
  421. InvokePendingSetFeatureEnabledStateCallback(/*success=*/false);
  422. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  423. // Test when feature is enabled externally and visible network is added
  424. // before callback runs.
  425. AttemptConnection();
  426. // Should be set connecting even before feature is enabled.
  427. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  428. // Feature enabled externally
  429. SetMultideviceSetupFeatureState(FeatureState::kEnabledByUser);
  430. AddVisibleTetherNetwork();
  431. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  432. // Should fail to connect if feature does not successfully turn on.
  433. InvokePendingSetFeatureEnabledStateCallback(/*success=*/false);
  434. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionAvailable);
  435. RemoveVisibleTetherNetwork();
  436. // Test when Mulitdevice suite disabled before callback can return.
  437. AttemptConnection();
  438. // Should be set connecting even before feature is enabled.
  439. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  440. // Disable suite externally.
  441. SetMultideviceSetupFeatureState(FeatureState::kDisabledByUser);
  442. AddVisibleTetherNetwork();
  443. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  444. }
  445. TEST_F(TetherControllerImplTest, AttemptConnectFeatureOffNoNetwork) {
  446. // Test enable flow when a tether device initially does not exist.
  447. DisconnectTetherDevice();
  448. SetMultideviceSetupFeatureState(FeatureState::kDisabledByUser);
  449. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  450. AttemptConnection();
  451. // Should be set connecting even before feature is enabled.
  452. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  453. // Should still be connecting when feature becomes enabled.
  454. InvokePendingSetFeatureEnabledStateCallback(/*success=*/true);
  455. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  456. // Tether is scanning, connection should be connecting still.
  457. SetTetherScanState(true);
  458. EXPECT_EQ(GetStatus(), TetherController::Status::kConnecting);
  459. DisconnectTetherDevice();
  460. // Tether stops scanning, attempt ends and connection should become
  461. // unavailable.
  462. SetTetherScanState(false);
  463. EXPECT_EQ(GetNumObserverScanFailed(), 1U);
  464. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  465. // Tether starts scanning after connection attempt ended.
  466. SetTetherScanState(true);
  467. EXPECT_EQ(GetNumObserverScanFailed(), 1U);
  468. EXPECT_EQ(GetStatus(), TetherController::Status::kConnectionUnavailable);
  469. }
  470. } // namespace phonehub
  471. } // namespace ash