blob: 65e400e86d98676e85cdecaec1aa2e516dba877a [file] [log] [blame]
// Copyright 2019 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 <memory>
#include "ash/public/cpp/network_config_service.h"
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "chromeos/components/sync_wifi/fake_pending_network_configuration_tracker.h"
#include "chromeos/components/sync_wifi/fake_timer_factory.h"
#include "chromeos/components/sync_wifi/network_identifier.h"
#include "chromeos/components/sync_wifi/network_test_helper.h"
#include "chromeos/components/sync_wifi/pending_network_configuration_tracker_impl.h"
#include "chromeos/components/sync_wifi/synced_network_metrics_logger.h"
#include "chromeos/components/sync_wifi/synced_network_updater_impl.h"
#include "chromeos/components/sync_wifi/test_data_generator.h"
#include "chromeos/dbus/shill/fake_shill_simulated_result.h"
#include "chromeos/network/network_handler.h"
#include "chromeos/network/network_metadata_store.h"
#include "chromeos/services/network_config/cros_network_config.h"
#include "chromeos/services/network_config/in_process_instance.h"
#include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
namespace chromeos {
class NetworkDeviceHandler;
class NetworkProfileHandler;
class NetworkConfigurationHandler;
class NetworkConnectionHandler;
class ManagedNetworkConfigurationHandler;
namespace sync_wifi {
namespace {
const char kFredSsid[] = "Fred";
const char kMangoSsid[] = "Mango";
const chromeos::NetworkState* FindLocalNetworkById(
const NetworkIdentifier& id) {
chromeos::NetworkStateHandler::NetworkStateList network_list;
chromeos::NetworkHandler::Get()
->network_state_handler()
->GetNetworkListByType(
chromeos::NetworkTypePattern::WiFi(), /* configured_only= */ true,
/* visible_only= */ false, /* limit= */ 0, &network_list);
for (const chromeos::NetworkState* network : network_list) {
if (network->GetHexSsid() == id.hex_ssid() &&
network->security_class() == id.security_type()) {
return network;
}
}
return nullptr;
}
} // namespace
class SyncedNetworkUpdaterImplTest : public testing::Test {
public:
SyncedNetworkUpdaterImplTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::DEFAULT,
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
local_test_helper_ = std::make_unique<NetworkTestHelper>();
ash::GetNetworkConfigService(
remote_cros_network_config_.BindNewPipeAndPassReceiver());
}
~SyncedNetworkUpdaterImplTest() override { local_test_helper_.reset(); }
void SetUp() override {
testing::Test::SetUp();
local_test_helper_->SetUp();
network_state_helper()->ResetDevicesAndServices();
base::RunLoop().RunUntilIdle();
auto tracker_unique_ptr =
std::make_unique<FakePendingNetworkConfigurationTracker>();
tracker_ = tracker_unique_ptr.get();
timer_factory_ = std::make_unique<FakeTimerFactory>();
metrics_logger_ = std::make_unique<SyncedNetworkMetricsLogger>(
/*network_state_handler=*/nullptr,
/*network_connection_handler=*/nullptr);
updater_ = std::make_unique<SyncedNetworkUpdaterImpl>(
std::move(tracker_unique_ptr), remote_cros_network_config_.get(),
timer_factory_.get(), metrics_logger_.get());
}
void TearDown() override {
chromeos::NetworkHandler::Shutdown();
testing::Test::TearDown();
}
FakePendingNetworkConfigurationTracker* tracker() { return tracker_; }
FakeTimerFactory* timer_factory() { return timer_factory_.get(); }
SyncedNetworkUpdaterImpl* updater() { return updater_.get(); }
chromeos::NetworkStateTestHelper* network_state_helper() {
return local_test_helper_->network_state_test_helper();
}
NetworkIdentifier fred_network_id() { return fred_network_id_; }
NetworkIdentifier mango_network_id() { return mango_network_id_; }
private:
base::test::TaskEnvironment task_environment_;
std::unique_ptr<NetworkTestHelper> local_test_helper_;
std::unique_ptr<FakeTimerFactory> timer_factory_;
FakePendingNetworkConfigurationTracker* tracker_;
std::unique_ptr<SyncedNetworkMetricsLogger> metrics_logger_;
std::unique_ptr<SyncedNetworkUpdaterImpl> updater_;
mojo::Remote<chromeos::network_config::mojom::CrosNetworkConfig>
remote_cros_network_config_;
NetworkIdentifier fred_network_id_ = GeneratePskNetworkId(kFredSsid);
NetworkIdentifier mango_network_id_ = GeneratePskNetworkId(kMangoSsid);
DISALLOW_COPY_AND_ASSIGN(SyncedNetworkUpdaterImplTest);
};
TEST_F(SyncedNetworkUpdaterImplTest, TestAdd_OneNetwork) {
base::HistogramTester histogram_tester;
sync_pb::WifiConfigurationSpecifics specifics =
GenerateTestWifiSpecifics(fred_network_id());
NetworkIdentifier id = NetworkIdentifier::FromProto(specifics);
updater()->AddOrUpdateNetwork(specifics);
EXPECT_TRUE(tracker()->GetPendingUpdateById(id));
base::RunLoop().RunUntilIdle();
const chromeos::NetworkState* network = FindLocalNetworkById(id);
EXPECT_TRUE(network);
EXPECT_FALSE(tracker()->GetPendingUpdateById(id));
EXPECT_TRUE(
NetworkHandler::Get()->network_metadata_store()->GetIsConfiguredBySync(
network->guid()));
histogram_tester.ExpectBucketCount(kApplyResultHistogram, true, 1);
}
TEST_F(SyncedNetworkUpdaterImplTest, TestAdd_ThenRemove) {
base::HistogramTester histogram_tester;
EXPECT_FALSE(FindLocalNetworkById(fred_network_id()));
updater()->AddOrUpdateNetwork(GenerateTestWifiSpecifics(fred_network_id()));
EXPECT_TRUE(tracker()->GetPendingUpdateById(fred_network_id()));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(FindLocalNetworkById(fred_network_id()));
updater()->RemoveNetwork(fred_network_id());
PendingNetworkConfigurationUpdate* update =
tracker()->GetPendingUpdateById(fred_network_id());
EXPECT_TRUE(update);
EXPECT_FALSE(update->specifics());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(tracker()->GetPendingUpdateById(fred_network_id()));
EXPECT_FALSE(FindLocalNetworkById(fred_network_id()));
histogram_tester.ExpectBucketCount(kApplyResultHistogram, true, 2);
}
TEST_F(SyncedNetworkUpdaterImplTest, TestAdd_TwoNetworks) {
base::HistogramTester histogram_tester;
updater()->AddOrUpdateNetwork(GenerateTestWifiSpecifics(fred_network_id()));
updater()->AddOrUpdateNetwork(GenerateTestWifiSpecifics(mango_network_id()));
EXPECT_TRUE(tracker()->GetPendingUpdateById(fred_network_id()));
EXPECT_TRUE(tracker()->GetPendingUpdateById(mango_network_id()));
base::RunLoop().RunUntilIdle();
const chromeos::NetworkState* fred_network =
FindLocalNetworkById(fred_network_id());
const chromeos::NetworkState* mango_network =
FindLocalNetworkById(mango_network_id());
EXPECT_TRUE(fred_network);
EXPECT_TRUE(mango_network);
EXPECT_TRUE(
NetworkHandler::Get()->network_metadata_store()->GetIsConfiguredBySync(
fred_network->guid()));
EXPECT_TRUE(
NetworkHandler::Get()->network_metadata_store()->GetIsConfiguredBySync(
mango_network->guid()));
EXPECT_FALSE(tracker()->GetPendingUpdateById(fred_network_id()));
EXPECT_FALSE(tracker()->GetPendingUpdateById(mango_network_id()));
histogram_tester.ExpectBucketCount(kApplyResultHistogram, true, 2);
}
TEST_F(SyncedNetworkUpdaterImplTest, TestFailToAdd_Error) {
base::HistogramTester histogram_tester;
network_state_helper()->manager_test()->SetSimulateConfigurationResult(
chromeos::FakeShillSimulatedResult::kFailure);
updater()->AddOrUpdateNetwork(GenerateTestWifiSpecifics(fred_network_id()));
EXPECT_TRUE(tracker()->GetPendingUpdateById(fred_network_id()));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(FindLocalNetworkById(fred_network_id()));
// The tracker should no longer be tracking the update because it reached the
// max failed number of attempts.
EXPECT_FALSE(tracker()->GetPendingUpdateById(fred_network_id()));
// Our test tracker holds on to the number of completed attempts after an
// update has been removed, and that should be equal to kMaxRetries (3).
EXPECT_EQ(3, tracker()->GetCompletedAttempts(fred_network_id()));
histogram_tester.ExpectBucketCount(kApplyResultHistogram, false, 1);
histogram_tester.ExpectBucketCount(
kApplyFailureReasonHistogram, ApplyNetworkFailureReason::kFailedToAdd, 3);
}
TEST_F(SyncedNetworkUpdaterImplTest, TestFailToAdd_Timeout) {
base::HistogramTester histogram_tester;
network_state_helper()->manager_test()->SetSimulateConfigurationResult(
chromeos::FakeShillSimulatedResult::kTimeout);
updater()->AddOrUpdateNetwork(GenerateTestWifiSpecifics(fred_network_id()));
EXPECT_TRUE(tracker()->GetPendingUpdateById(fred_network_id()));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(tracker()->GetPendingUpdateById(fred_network_id()));
EXPECT_EQ(0, tracker()->GetCompletedAttempts(fred_network_id()));
timer_factory()->FireAll();
EXPECT_TRUE(tracker()->GetPendingUpdateById(fred_network_id()));
EXPECT_EQ(1, tracker()->GetCompletedAttempts(fred_network_id()));
timer_factory()->FireAll();
EXPECT_TRUE(tracker()->GetPendingUpdateById(fred_network_id()));
EXPECT_EQ(2, tracker()->GetCompletedAttempts(fred_network_id()));
timer_factory()->FireAll();
EXPECT_EQ(3, tracker()->GetCompletedAttempts(fred_network_id()));
EXPECT_FALSE(tracker()->GetPendingUpdateById(fred_network_id()));
histogram_tester.ExpectBucketCount(kApplyResultHistogram, false, 1);
histogram_tester.ExpectBucketCount(kApplyFailureReasonHistogram,
ApplyNetworkFailureReason::kTimedout, 3);
}
TEST_F(SyncedNetworkUpdaterImplTest, TestFailToAdd_Timeout_ThenSucceed) {
base::HistogramTester histogram_tester;
network_state_helper()->manager_test()->SetSimulateConfigurationResult(
chromeos::FakeShillSimulatedResult::kTimeout);
updater()->AddOrUpdateNetwork(GenerateTestWifiSpecifics(fred_network_id()));
EXPECT_TRUE(tracker()->GetPendingUpdateById(fred_network_id()));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(tracker()->GetPendingUpdateById(fred_network_id()));
EXPECT_EQ(0, tracker()->GetCompletedAttempts(fred_network_id()));
timer_factory()->FireAll();
EXPECT_TRUE(tracker()->GetPendingUpdateById(fred_network_id()));
EXPECT_EQ(1, tracker()->GetCompletedAttempts(fred_network_id()));
network_state_helper()->manager_test()->SetSimulateConfigurationResult(
chromeos::FakeShillSimulatedResult::kSuccess);
timer_factory()->FireAll();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(tracker()->GetPendingUpdateById(fred_network_id()));
EXPECT_TRUE(FindLocalNetworkById(fred_network_id()));
histogram_tester.ExpectBucketCount(kApplyResultHistogram, false, 0);
histogram_tester.ExpectBucketCount(kApplyResultHistogram, true, 1);
histogram_tester.ExpectBucketCount(kApplyFailureReasonHistogram,
ApplyNetworkFailureReason::kTimedout, 2);
}
TEST_F(SyncedNetworkUpdaterImplTest, TestFailToRemove) {
base::HistogramTester histogram_tester;
network_state_helper()->profile_test()->SetSimulateDeleteResult(
chromeos::FakeShillSimulatedResult::kFailure);
updater()->AddOrUpdateNetwork(GenerateTestWifiSpecifics(fred_network_id()));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(FindLocalNetworkById(fred_network_id()));
EXPECT_FALSE(tracker()->GetPendingUpdateById(fred_network_id()));
updater()->RemoveNetwork(fred_network_id());
EXPECT_TRUE(tracker()->GetPendingUpdateById(fred_network_id()));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(FindLocalNetworkById(fred_network_id()));
EXPECT_FALSE(tracker()->GetPendingUpdateById(fred_network_id()));
EXPECT_EQ(3, tracker()->GetCompletedAttempts(fred_network_id()));
histogram_tester.ExpectBucketCount(kApplyResultHistogram, false, 1);
histogram_tester.ExpectBucketCount(kApplyFailureReasonHistogram,
ApplyNetworkFailureReason::kFailedToRemove,
3);
}
} // namespace sync_wifi
} // namespace chromeos