| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "services/network/public/cpp/network_quality_tracker.h" |
| |
| #include "base/macros.h" |
| #include "base/run_loop.h" |
| #include "base/test/scoped_task_environment.h" |
| #include "base/threading/thread.h" |
| #include "base/threading/thread_checker.h" |
| #include "net/nqe/effective_connection_type.h" |
| #include "net/nqe/network_quality_estimator.h" |
| #include "services/network/network_service.h" |
| #include "services/network/public/mojom/network_change_manager.mojom.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace network { |
| |
| namespace { |
| |
| class TestEffectiveConnectionTypeObserver |
| : public NetworkQualityTracker::EffectiveConnectionTypeObserver { |
| public: |
| explicit TestEffectiveConnectionTypeObserver(NetworkQualityTracker* tracker) |
| : num_notifications_(0), |
| tracker_(tracker), |
| run_loop_(std::make_unique<base::RunLoop>()), |
| effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) { |
| tracker_->AddEffectiveConnectionTypeObserver(this); |
| } |
| |
| ~TestEffectiveConnectionTypeObserver() override { |
| tracker_->RemoveEffectiveConnectionTypeObserver(this); |
| } |
| |
| // Helper to synchronously get effective connection type from |
| // NetworkQualityTracker. |
| net::EffectiveConnectionType GetEffectiveConnectionTypeSync() { |
| return tracker_->GetEffectiveConnectionType(); |
| } |
| |
| // NetworkConnectionObserver implementation: |
| void OnEffectiveConnectionTypeChanged( |
| net::EffectiveConnectionType type) override { |
| EXPECT_EQ(type, GetEffectiveConnectionTypeSync()); |
| num_notifications_++; |
| effective_connection_type_ = type; |
| run_loop_->Quit(); |
| } |
| |
| size_t num_notifications() const { return num_notifications_; } |
| |
| void WaitForNotification() { |
| run_loop_->Run(); |
| run_loop_.reset(new base::RunLoop()); |
| } |
| |
| net::EffectiveConnectionType effective_connection_type() const { |
| return effective_connection_type_; |
| } |
| |
| private: |
| static void GetEffectiveConnectionTypeCallback( |
| base::RunLoop* run_loop, |
| net::EffectiveConnectionType* out, |
| net::EffectiveConnectionType type) { |
| *out = type; |
| run_loop->Quit(); |
| } |
| |
| size_t num_notifications_; |
| NetworkQualityTracker* tracker_; |
| std::unique_ptr<base::RunLoop> run_loop_; |
| net::EffectiveConnectionType effective_connection_type_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestEffectiveConnectionTypeObserver); |
| }; |
| |
| } // namespace |
| |
| class NetworkQualityTrackerTest : public testing::Test { |
| public: |
| NetworkQualityTrackerTest() { |
| network::mojom::NetworkServicePtr network_service_ptr; |
| network::mojom::NetworkServiceRequest network_service_request = |
| mojo::MakeRequest(&network_service_ptr); |
| network_service_ = |
| network::NetworkService::Create(std::move(network_service_request), |
| /*netlog=*/nullptr); |
| tracker_ = std::make_unique<NetworkQualityTracker>( |
| base::BindRepeating(&NetworkQualityTrackerTest::mojom_network_service, |
| base::Unretained(this))); |
| observer_ = |
| std::make_unique<TestEffectiveConnectionTypeObserver>(tracker_.get()); |
| } |
| |
| ~NetworkQualityTrackerTest() override {} |
| |
| network::NetworkService* network_service() { return network_service_.get(); } |
| |
| NetworkQualityTracker* network_quality_tracker() { return tracker_.get(); } |
| |
| TestEffectiveConnectionTypeObserver* effective_connection_type_observer() { |
| return observer_.get(); |
| } |
| |
| // Simulates a connection type change and broadcast it to observers. |
| void SimulateEffectiveConnectionTypeChange( |
| net::EffectiveConnectionType type) { |
| network_service() |
| ->network_quality_estimator() |
| ->SimulateNetworkQualityChangeForTesting(type); |
| } |
| |
| private: |
| network::mojom::NetworkService* mojom_network_service() const { |
| return network_service_.get(); |
| } |
| |
| base::test::ScopedTaskEnvironment scoped_task_environment_; |
| std::unique_ptr<network::NetworkService> network_service_; |
| std::unique_ptr<NetworkQualityTracker> tracker_; |
| std::unique_ptr<TestEffectiveConnectionTypeObserver> observer_; |
| |
| DISALLOW_COPY_AND_ASSIGN(NetworkQualityTrackerTest); |
| }; |
| |
| TEST_F(NetworkQualityTrackerTest, ObserverNotified) { |
| EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN, |
| effective_connection_type_observer()->effective_connection_type()); |
| |
| SimulateEffectiveConnectionTypeChange(net::EFFECTIVE_CONNECTION_TYPE_3G); |
| |
| effective_connection_type_observer()->WaitForNotification(); |
| EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_3G, |
| effective_connection_type_observer()->effective_connection_type()); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1u, effective_connection_type_observer()->num_notifications()); |
| } |
| |
| TEST_F(NetworkQualityTrackerTest, UnregisteredObserverNotNotified) { |
| auto network_quality_observer2 = |
| std::make_unique<TestEffectiveConnectionTypeObserver>( |
| network_quality_tracker()); |
| |
| // Simulate a network quality change. |
| SimulateEffectiveConnectionTypeChange(net::EFFECTIVE_CONNECTION_TYPE_3G); |
| |
| network_quality_observer2->WaitForNotification(); |
| EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_3G, |
| network_quality_observer2->effective_connection_type()); |
| effective_connection_type_observer()->WaitForNotification(); |
| EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_3G, |
| effective_connection_type_observer()->effective_connection_type()); |
| base::RunLoop().RunUntilIdle(); |
| |
| network_quality_observer2.reset(); |
| |
| // Simulate an another network quality change. |
| SimulateEffectiveConnectionTypeChange(net::EFFECTIVE_CONNECTION_TYPE_2G); |
| effective_connection_type_observer()->WaitForNotification(); |
| EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, |
| effective_connection_type_observer()->effective_connection_type()); |
| EXPECT_EQ(2u, effective_connection_type_observer()->num_notifications()); |
| } |
| |
| } // namespace network |