| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chromeos/ash/components/network/technology_state_controller.h" |
| |
| #include "base/test/bind.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/task_environment.h" |
| #include "base/values.h" |
| #include "chromeos/ash/components/dbus/shill/shill_clients.h" |
| #include "chromeos/ash/components/dbus/shill/shill_manager_client.h" |
| #include "chromeos/ash/components/network/enterprise_managed_metadata_store.h" |
| #include "chromeos/ash/components/network/hotspot_allowed_flag_handler.h" |
| #include "chromeos/ash/components/network/hotspot_capabilities_provider.h" |
| #include "chromeos/ash/components/network/hotspot_controller.h" |
| #include "chromeos/ash/components/network/hotspot_state_handler.h" |
| #include "chromeos/ash/components/network/metrics/connection_results.h" |
| #include "chromeos/ash/components/network/metrics/hotspot_feature_usage_metrics.h" |
| #include "chromeos/ash/components/network/network_state_handler.h" |
| #include "chromeos/ash/components/network/network_state_test_helper.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/cros_system_api/dbus/shill/dbus-constants.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| const char kEnableWifiResultHistogram[] = |
| "Network.Ash.WiFi.EnabledState.Enable.Result"; |
| const char kEnableWifiResultCodeHistogram[] = |
| "Network.Ash.WiFi.EnabledState.Enable.ResultCode"; |
| |
| } // namespace |
| |
| class TechnologyStateControllerTest : public ::testing::Test { |
| public: |
| void SetUp() override { |
| enterprise_managed_metadata_store_ = |
| std::make_unique<EnterpriseManagedMetadataStore>(); |
| hotspot_capabilities_provider_ = |
| std::make_unique<HotspotCapabilitiesProvider>(); |
| hotspot_allowed_flag_handler_ = |
| std::make_unique<HotspotAllowedFlagHandler>(); |
| hotspot_capabilities_provider_->Init( |
| network_state_test_helper_.network_state_handler(), |
| hotspot_allowed_flag_handler_.get()); |
| hotspot_feature_usage_metrics_ = |
| std::make_unique<HotspotFeatureUsageMetrics>(); |
| hotspot_feature_usage_metrics_->Init( |
| enterprise_managed_metadata_store_.get(), |
| hotspot_capabilities_provider_.get()); |
| technology_state_controller_ = |
| std::make_unique<TechnologyStateController>(); |
| technology_state_controller_->Init( |
| network_state_test_helper_.network_state_handler()); |
| hotspot_state_handler_ = std::make_unique<HotspotStateHandler>(); |
| hotspot_state_handler_->Init(); |
| hotspot_controller_ = std::make_unique<HotspotController>(); |
| hotspot_controller_->Init(hotspot_capabilities_provider_.get(), |
| hotspot_feature_usage_metrics_.get(), |
| hotspot_state_handler_.get(), |
| technology_state_controller_.get()); |
| } |
| |
| void TearDown() override { |
| network_state_test_helper_.ClearDevices(); |
| network_state_test_helper_.ClearServices(); |
| hotspot_controller_.reset(); |
| hotspot_feature_usage_metrics_.reset(); |
| hotspot_capabilities_provider_.reset(); |
| hotspot_allowed_flag_handler_.reset(); |
| hotspot_state_handler_.reset(); |
| enterprise_managed_metadata_store_.reset(); |
| technology_state_controller_.reset(); |
| } |
| |
| // Returns the pair of prepare_success and wifi_turned_off result of the |
| // TechnologStateHandler::PrepareEnableHotspot method. |
| std::pair<bool, bool> PrepareEnableHotspot() { |
| base::RunLoop run_loop; |
| bool prepare_success, wifi_turned_off; |
| technology_state_controller_->PrepareEnableHotspot( |
| base::BindLambdaForTesting([&](bool success, bool wifi_off) { |
| prepare_success = success; |
| wifi_turned_off = wifi_off; |
| run_loop.Quit(); |
| })); |
| run_loop.Run(); |
| return std::make_pair(prepare_success, wifi_turned_off); |
| } |
| |
| protected: |
| base::test::TaskEnvironment task_environment_{ |
| base::test::TaskEnvironment::TimeSource::MOCK_TIME}; |
| base::HistogramTester histogram_tester_; |
| std::unique_ptr<HotspotController> hotspot_controller_; |
| std::unique_ptr<EnterpriseManagedMetadataStore> |
| enterprise_managed_metadata_store_; |
| std::unique_ptr<HotspotCapabilitiesProvider> hotspot_capabilities_provider_; |
| std::unique_ptr<HotspotAllowedFlagHandler> hotspot_allowed_flag_handler_; |
| std::unique_ptr<HotspotFeatureUsageMetrics> hotspot_feature_usage_metrics_; |
| std::unique_ptr<HotspotStateHandler> hotspot_state_handler_; |
| std::unique_ptr<TechnologyStateController> technology_state_controller_; |
| NetworkStateTestHelper network_state_test_helper_{ |
| /*use_default_devices_and_services=*/false}; |
| }; |
| |
| TEST_F(TechnologyStateControllerTest, ChangeWifiTechnology) { |
| // Disable Wifi technology. Will immediately set the state to DISABLING. |
| technology_state_controller_->SetTechnologiesEnabled( |
| NetworkTypePattern::WiFi(), /*enabled=*/false, |
| network_handler::ErrorCallback()); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_DISABLING, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| |
| // Run the message loop. When Shill updates the enabled technologies since |
| // the state should transition to AVAILABLE. |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_AVAILABLE, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| |
| // Enable Wifi technology. Will immediately set the state to ENABLING. |
| technology_state_controller_->SetTechnologiesEnabled( |
| NetworkTypePattern::WiFi(), /*enabled=*/true, |
| network_handler::ErrorCallback()); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_ENABLING, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| |
| // Run the message loop. State should change to ENABLED. |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_ENABLED, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| } |
| |
| TEST_F(TechnologyStateControllerTest, ChangePhysicalTechnologies) { |
| // Disable Physical technologies which includes WiFi(), Cellular() and |
| // Ethernet() |
| technology_state_controller_->SetTechnologiesEnabled( |
| NetworkTypePattern::Physical(), /*enabled=*/false, |
| network_handler::ErrorCallback()); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_DISABLING, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_DISABLING, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::Cellular())); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_DISABLING, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::Ethernet())); |
| |
| // Run the message loop. When Shill updates the enabled technologies since |
| // the state should transition to AVAILABLE. |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_AVAILABLE, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_AVAILABLE, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::Cellular())); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_AVAILABLE, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::Ethernet())); |
| |
| // Enable Physical technologies. Will immediately set the state to ENABLING. |
| technology_state_controller_->SetTechnologiesEnabled( |
| NetworkTypePattern::Physical(), /*enabled=*/true, |
| network_handler::ErrorCallback()); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_ENABLING, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_ENABLING, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::Cellular())); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_ENABLING, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::Ethernet())); |
| |
| // Run the message loop. State should change to ENABLED. |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_ENABLED, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_ENABLED, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::Cellular())); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_ENABLED, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::Ethernet())); |
| } |
| |
| TEST_F(TechnologyStateControllerTest, EnableWifiWhenHotspotOn) { |
| technology_state_controller_->SetTechnologiesEnabled( |
| NetworkTypePattern::WiFi(), /*enabled=*/false, |
| network_handler::ErrorCallback()); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_AVAILABLE, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| |
| // Simulate that there's an active hotspot |
| auto status_dict = base::Value::Dict().Set( |
| shill::kTetheringStatusStateProperty, shill::kTetheringStateActive); |
| network_state_test_helper_.manager_test()->SetManagerProperty( |
| shill::kTetheringStatusProperty, base::Value(std::move(status_dict))); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Simulate disable hotspot will fail. |
| network_state_test_helper_.manager_test()->SetSimulateTetheringEnableResult( |
| FakeShillSimulatedResult::kSuccess, "network_failure"); |
| |
| std::string error; |
| base::RunLoop run_loop; |
| technology_state_controller_->SetTechnologiesEnabled( |
| NetworkTypePattern::WiFi(), /*enabled=*/true, |
| base::BindLambdaForTesting([&](const std::string& error_name) { |
| error = error_name; |
| run_loop.Quit(); |
| })); |
| run_loop.Run(); |
| EXPECT_EQ(TechnologyStateController::kErrorDisableHotspot, error); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_AVAILABLE, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| histogram_tester_.ExpectTotalCount(kEnableWifiResultCodeHistogram, 1); |
| histogram_tester_.ExpectBucketCount( |
| kEnableWifiResultCodeHistogram, |
| ShillConnectResult::kErrorDisableHotspotFailed, 1); |
| histogram_tester_.ExpectTotalCount(kEnableWifiResultHistogram, 1); |
| histogram_tester_.ExpectBucketCount(kEnableWifiResultHistogram, false, 1); |
| |
| // Simulate disable hotspot will succeed. |
| network_state_test_helper_.manager_test()->SetSimulateTetheringEnableResult( |
| FakeShillSimulatedResult::kSuccess, shill::kTetheringEnableResultSuccess); |
| technology_state_controller_->SetTechnologiesEnabled( |
| NetworkTypePattern::WiFi(), /*enabled=*/true, |
| network_handler::ErrorCallback()); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_ENABLED, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| histogram_tester_.ExpectTotalCount(kEnableWifiResultCodeHistogram, 2); |
| histogram_tester_.ExpectBucketCount(kEnableWifiResultCodeHistogram, |
| ShillConnectResult::kSuccess, 1); |
| histogram_tester_.ExpectTotalCount(kEnableWifiResultHistogram, 2); |
| histogram_tester_.ExpectBucketCount(kEnableWifiResultHistogram, true, 1); |
| } |
| |
| TEST_F(TechnologyStateControllerTest, PrepareEnableHotspot) { |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_ENABLED, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| |
| std::pair<bool, bool> result = PrepareEnableHotspot(); |
| // Verifies that |prepare_success| will return true. |
| EXPECT_TRUE(result.first); |
| // Verifies that |wifi_turned_off| will return true since Wifi was on. |
| EXPECT_TRUE(result.second); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_AVAILABLE, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| |
| result = PrepareEnableHotspot(); |
| // Verifies that |prepare_success| will return true. |
| EXPECT_TRUE(result.first); |
| // Verifies that |wifi_turned_off| will return false since Wifi was off. |
| EXPECT_FALSE(result.second); |
| EXPECT_EQ( |
| NetworkStateHandler::TECHNOLOGY_AVAILABLE, |
| network_state_test_helper_.network_state_handler()->GetTechnologyState( |
| NetworkTypePattern::WiFi())); |
| } |
| |
| } // namespace ash |