chromium/chromeos/ash/components/tether/active_host_unittest.cc

// Copyright 2017 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/tether/active_host.h"

#include <memory>
#include <optional>

#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "chromeos/ash/components/multidevice/remote_device_ref.h"
#include "chromeos/ash/components/multidevice/remote_device_test_util.h"
#include "chromeos/ash/components/tether/fake_tether_host_fetcher.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash::tether {

namespace {

struct GetActiveHostResult {
  ActiveHost::ActiveHostStatus active_host_status;
  std::optional<multidevice::RemoteDeviceRef> remote_device;
  std::string tether_network_guid;
  std::string wifi_network_guid;

  bool operator==(const GetActiveHostResult& other) const {
    return active_host_status == other.active_host_status &&
           remote_device == other.remote_device &&
           tether_network_guid == other.tether_network_guid &&
           wifi_network_guid == other.wifi_network_guid;
  }
};

class TestObserver final : public ActiveHost::Observer {
 public:
  void OnActiveHostChanged(
      const ActiveHost::ActiveHostChangeInfo& change_info) override {
    host_changed_updates_.push_back(change_info);
  }

  std::vector<ActiveHost::ActiveHostChangeInfo>& host_changed_updates() {
    return host_changed_updates_;
  }

 private:
  std::vector<ActiveHost::ActiveHostChangeInfo> host_changed_updates_;
};

}  // namespace

class ActiveHostTest : public testing::Test {
 public:
  ActiveHostTest()
      : test_devices_(multidevice::CreateRemoteDeviceRefListForTest(4)) {}

  ActiveHostTest(const ActiveHostTest&) = delete;
  ActiveHostTest& operator=(const ActiveHostTest&) = delete;

  void SetUp() override {
    get_active_host_results_.clear();

    test_pref_service_ =
        std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
    fake_tether_host_fetcher_ =
        std::make_unique<FakeTetherHostFetcher>(test_devices_[0]);

    ActiveHost::RegisterPrefs(test_pref_service_->registry());
    active_host_ = std::make_unique<ActiveHost>(fake_tether_host_fetcher_.get(),
                                                test_pref_service_.get());

    test_observer_ = base::WrapUnique(new TestObserver);
    active_host_->AddObserver(test_observer_.get());
  }

  void OnActiveHostFetched(
      ActiveHost::ActiveHostStatus active_host_status,
      std::optional<multidevice::RemoteDeviceRef> active_host,
      const std::string& tether_network_guid,
      const std::string& wifi_network_guid) {
    get_active_host_results_.push_back(
        GetActiveHostResult{active_host_status, active_host,
                            tether_network_guid, wifi_network_guid});
  }

  void VerifyActiveHostDisconnected() {
    EXPECT_EQ(ActiveHost::ActiveHostStatus::DISCONNECTED,
              active_host_->GetActiveHostStatus());
    EXPECT_TRUE(active_host_->GetActiveHostDeviceId().empty());
    EXPECT_TRUE(active_host_->GetWifiNetworkGuid().empty());
    EXPECT_TRUE(active_host_->GetTetherNetworkGuid().empty());

    active_host_->GetActiveHost(base::BindOnce(
        &ActiveHostTest::OnActiveHostFetched, base::Unretained(this)));
    ASSERT_EQ(1u, get_active_host_results_.size());
    EXPECT_EQ((GetActiveHostResult{ActiveHost::ActiveHostStatus::DISCONNECTED,
                                   std::nullopt, std::string(), std::string()}),
              get_active_host_results_[0]);
  }

  const multidevice::RemoteDeviceRefList test_devices_;

  std::unique_ptr<sync_preferences::TestingPrefServiceSyncable>
      test_pref_service_;
  std::unique_ptr<FakeTetherHostFetcher> fake_tether_host_fetcher_;
  std::unique_ptr<TestObserver> test_observer_;

  std::vector<GetActiveHostResult> get_active_host_results_;

  std::unique_ptr<ActiveHost> active_host_;
};

TEST_F(ActiveHostTest, TestDefaultValues) {
  VerifyActiveHostDisconnected();
}

TEST_F(ActiveHostTest, TestDisconnected) {
  active_host_->SetActiveHostDisconnected();
  VerifyActiveHostDisconnected();
}

TEST_F(ActiveHostTest, TestConnecting) {
  active_host_->SetActiveHostConnecting(test_devices_[0].GetDeviceId(),
                                        "tetherNetworkGuid");

  EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTING,
            active_host_->GetActiveHostStatus());
  EXPECT_EQ(test_devices_[0].GetDeviceId(),
            active_host_->GetActiveHostDeviceId());
  EXPECT_EQ("tetherNetworkGuid", active_host_->GetTetherNetworkGuid());
  EXPECT_TRUE(active_host_->GetWifiNetworkGuid().empty());

  active_host_->GetActiveHost(base::BindOnce(
      &ActiveHostTest::OnActiveHostFetched, base::Unretained(this)));
  ASSERT_EQ(1u, get_active_host_results_.size());
  EXPECT_EQ(
      (GetActiveHostResult{
          ActiveHost::ActiveHostStatus::CONNECTING,
          std::make_optional<multidevice::RemoteDeviceRef>(test_devices_[0]),
          "tetherNetworkGuid", std::string()}),
      get_active_host_results_[0]);
}

TEST_F(ActiveHostTest, TestConnected) {
  active_host_->SetActiveHostConnected(test_devices_[0].GetDeviceId(),
                                       "tetherNetworkGuid", "wifiNetworkGuid");

  EXPECT_EQ(ActiveHost::ActiveHostStatus::CONNECTED,
            active_host_->GetActiveHostStatus());
  EXPECT_EQ(test_devices_[0].GetDeviceId(),
            active_host_->GetActiveHostDeviceId());
  EXPECT_EQ("tetherNetworkGuid", active_host_->GetTetherNetworkGuid());
  EXPECT_EQ("wifiNetworkGuid", active_host_->GetWifiNetworkGuid());

  active_host_->GetActiveHost(base::BindOnce(
      &ActiveHostTest::OnActiveHostFetched, base::Unretained(this)));
  ASSERT_EQ(1u, get_active_host_results_.size());
  EXPECT_EQ(
      (GetActiveHostResult{
          ActiveHost::ActiveHostStatus::CONNECTED,
          std::make_optional<multidevice::RemoteDeviceRef>(test_devices_[0]),
          "tetherNetworkGuid", "wifiNetworkGuid"}),
      get_active_host_results_[0]);
}

TEST_F(ActiveHostTest, TestObserverCalls) {
  // Start as DISCONNECTED.
  EXPECT_FALSE(test_observer_->host_changed_updates().size());

  // Go to DISCONNECTED again. This should not cause an observer callback to be
  // invoked.
  active_host_->SetActiveHostDisconnected();
  EXPECT_FALSE(test_observer_->host_changed_updates().size());

  // Transition to CONNECTING.
  active_host_->SetActiveHostConnecting(test_devices_[0].GetDeviceId(),
                                        "tetherNetworkGuid");
  EXPECT_EQ(1u, test_observer_->host_changed_updates().size());
  EXPECT_EQ(
      ActiveHost::ActiveHostChangeInfo(
          ActiveHost::ActiveHostStatus::CONNECTING,
          ActiveHost::ActiveHostStatus::DISCONNECTED,
          std::make_optional<multidevice::RemoteDeviceRef>(test_devices_[0]),
          "" /* old_active_host_id */,
          "tetherNetworkGuid" /* new_tether_network_guid */,
          "" /* old_tether_network_id */, "" /* new_wifi_network_guid */,
          "" /* old_wifi_network_guid */),
      test_observer_->host_changed_updates()[0]);

  // Transition to CONNECTED.
  active_host_->SetActiveHostConnected(test_devices_[0].GetDeviceId(),
                                       "tetherNetworkGuid", "wifiNetworkGuid");
  EXPECT_EQ(2u, test_observer_->host_changed_updates().size());
  EXPECT_EQ(
      ActiveHost::ActiveHostChangeInfo(
          ActiveHost::ActiveHostStatus::CONNECTED,
          ActiveHost::ActiveHostStatus::CONNECTING,
          std::make_optional<multidevice::RemoteDeviceRef>(test_devices_[0]),
          test_devices_[0].GetDeviceId(), "tetherNetworkGuid",
          "tetherNetworkGuid", "wifiNetworkGuid",
          "" /* old_wifi_network_guid */),
      test_observer_->host_changed_updates()[1]);

  // Transition to DISCONNECTED.
  active_host_->SetActiveHostDisconnected();
  EXPECT_EQ(3u, test_observer_->host_changed_updates().size());
  EXPECT_EQ(ActiveHost::ActiveHostChangeInfo(
                ActiveHost::ActiveHostStatus::DISCONNECTED,
                ActiveHost::ActiveHostStatus::CONNECTED, std::nullopt,
                test_devices_[0].GetDeviceId(),
                "" /* new_tether_network_guid */, "tetherNetworkGuid",
                "" /* new_wifi_network_guid */, "wifiNetworkGuid"),
            test_observer_->host_changed_updates()[2]);
}

}  // namespace ash::tether