910e62b5创建于 1月15日历史提交
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/services/sharing/sharing_impl.h"

#include <utility>

#include "ash/public/cpp/network_config_service.h"
#include "base/functional/callback_helpers.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "chrome/services/sharing/nearby/nearby_connections.h"
#include "chrome/services/sharing/nearby/nearby_presence.h"
#include "chrome/services/sharing/nearby/test_support/fake_adapter.h"
#include "chrome/services/sharing/nearby/test_support/fake_nearby_presence_credential_storage.h"
#include "chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.h"
#include "chromeos/ash/services/nearby/public/cpp/fake_firewall_hole_factory.h"
#include "chromeos/ash/services/nearby/public/cpp/fake_mdns_manager.h"
#include "chromeos/ash/services/nearby/public/cpp/fake_tcp_socket_factory.h"
#include "chromeos/ash/services/nearby/public/mojom/firewall_hole.mojom.h"
#include "chromeos/ash/services/nearby/public/mojom/mdns.mojom.h"
#include "chromeos/ash/services/nearby/public/mojom/nearby_decoder.mojom.h"
#include "chromeos/ash/services/nearby/public/mojom/nearby_presence_credential_storage.mojom.h"
#include "chromeos/ash/services/nearby/public/mojom/quick_start_decoder.mojom.h"
#include "chromeos/ash/services/nearby/public/mojom/sharing.mojom.h"
#include "chromeos/ash/services/nearby/public/mojom/tcp_socket_factory.mojom.h"
#include "chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

// Noop implementation for tests.
class FakeWifiDirectManager
    : public ash::wifi_direct::mojom::WifiDirectManager {
  // ash::wifi_direct::mojom::WifiDirectManager
  void CreateWifiDirectGroup(
      ash::wifi_direct::mojom::WifiCredentialsPtr credentials,
      CreateWifiDirectGroupCallback callback) override {
    // Noop
  }
  void ConnectToWifiDirectGroup(
      ash::wifi_direct::mojom::WifiCredentialsPtr credentials,
      std::optional<uint32_t> frequency,
      ConnectToWifiDirectGroupCallback callback) override {
    // Noop
  }
  void GetWifiP2PCapabilities(
      GetWifiP2PCapabilitiesCallback callback) override {
    // Noop
  }
};

}  // namespace

namespace sharing {

class SharingImplTest : public testing::Test {
 public:
  ~SharingImplTest() override {
    // Let libjingle threads finish.
    base::RunLoop().RunUntilIdle();
  }

  void SetUp() override {
    service_ =
        std::make_unique<SharingImpl>(remote_.BindNewPipeAndPassReceiver(),
                                      /*io_task_runner=*/nullptr);

    // Set up CrosNetworkConfig mojo service.
    cros_network_config_test_helper_ =
        std::make_unique<ash::network_config::CrosNetworkConfigTestHelper>();
    mojo::PendingRemote<chromeos::network_config::mojom::CrosNetworkConfig>
        cros_network_config_remote;
    ash::GetNetworkConfigService(
        cros_network_config_remote.InitWithNewPipeAndPassReceiver());

    // Set up firewall hole factory mojo service.
    mojo::PendingRemote<::sharing::mojom::FirewallHoleFactory>
        firewall_hole_factory_remote;
    firewall_hole_factory_self_owned_receiver_ref_ =
        mojo::MakeSelfOwnedReceiver(
            std::make_unique<ash::nearby::FakeFirewallHoleFactory>(),
            firewall_hole_factory_remote.InitWithNewPipeAndPassReceiver());

    // Set up TCP socket factory mojo service.
    mojo::PendingRemote<::sharing::mojom::TcpSocketFactory>
        tcp_socket_factory_remote;
    tcp_socket_factory_self_owned_receiver_ref_ = mojo::MakeSelfOwnedReceiver(
        std::make_unique<ash::nearby::FakeTcpSocketFactory>(
            /*default_local_addr=*/net::IPEndPoint(
                net::IPAddress(192, 168, 86, 75), 44444)),
        tcp_socket_factory_remote.InitWithNewPipeAndPassReceiver());

    // Set up Mdns manager mojo service.
    mojo::PendingRemote<::sharing::mojom::MdnsManager> mdns_manager_remote;
    mdns_manager_self_owned_receiver_ref_ = mojo::MakeSelfOwnedReceiver(
        std::make_unique<ash::nearby::FakeMdnsManager>(),
        mdns_manager_remote.InitWithNewPipeAndPassReceiver());

    // Set up fake WiFiDirect mojo services.
    mojo::PendingRemote<ash::wifi_direct::mojom::WifiDirectManager>
        wifi_direct_manager_remote;
    wifi_direct_manager_self_owned_receiver_ref_ = mojo::MakeSelfOwnedReceiver(
        std::make_unique<FakeWifiDirectManager>(),
        wifi_direct_manager_remote.InitWithNewPipeAndPassReceiver());
    mojo::PendingRemote<::sharing::mojom::FirewallHoleFactory>
        wifi_direct_firewall_hole_factory_remote;
    wifi_direct_firewall_hole_factory_self_owned_receiver_ref_ =
        mojo::MakeSelfOwnedReceiver(
            std::make_unique<ash::nearby::FakeFirewallHoleFactory>(),
            wifi_direct_firewall_hole_factory_remote
                .InitWithNewPipeAndPassReceiver());

    Connect(
        connections_.BindNewPipeAndPassReceiver(),
        presence_.BindNewPipeAndPassReceiver(),
        decoder_.BindNewPipeAndPassReceiver(),
        quick_start_decoder_.BindNewPipeAndPassReceiver(),
        bluetooth_adapter_.adapter_.BindNewPipeAndPassRemote(),
        nearby_presence_credential_storage_.receiver()
            .BindNewPipeAndPassRemote(),
        webrtc_dependencies_.socket_manager_.BindNewPipeAndPassRemote(),
        webrtc_dependencies_.mdns_responder_factory_.BindNewPipeAndPassRemote(),
        webrtc_dependencies_.ice_config_fetcher_.BindNewPipeAndPassRemote(),
        webrtc_dependencies_.messenger_.BindNewPipeAndPassRemote(),
        std::move(cros_network_config_remote),
        std::move(firewall_hole_factory_remote),
        std::move(tcp_socket_factory_remote), std::move(mdns_manager_remote),
        std::move(wifi_direct_manager_remote),
        std::move(wifi_direct_firewall_hole_factory_remote));

    ASSERT_TRUE(AreNearbyInstancesActive());
    ASSERT_TRUE(connections_.is_connected());
    ASSERT_TRUE(presence_.is_connected());
    ASSERT_TRUE(decoder_.is_connected());
    ASSERT_TRUE(quick_start_decoder_.is_connected());
  }

  void Connect(
      mojo::PendingReceiver<nearby::connections::mojom::NearbyConnections>
          connections_receiver,
      mojo::PendingReceiver<ash::nearby::presence::mojom::NearbyPresence>
          presence_receiver,
      mojo::PendingReceiver<::sharing::mojom::NearbySharingDecoder>
          decoder_receiver,
      mojo::PendingReceiver<ash::quick_start::mojom::QuickStartDecoder>
          quick_start_decoder_receiver,
      mojo::PendingRemote<bluetooth::mojom::Adapter> bluetooth_adapter,
      mojo::PendingRemote<
          ash::nearby::presence::mojom::NearbyPresenceCredentialStorage>
          nearby_presence_credential_storage,
      mojo::PendingRemote<network::mojom::P2PSocketManager> socket_manager,
      mojo::PendingRemote<::sharing::mojom::MdnsResponderFactory>
          mdns_responder_factory,
      mojo::PendingRemote<::sharing::mojom::IceConfigFetcher>
          ice_config_fetcher,
      mojo::PendingRemote<::sharing::mojom::WebRtcSignalingMessenger>
          webrtc_signaling_messenger,
      mojo::PendingRemote<chromeos::network_config::mojom::CrosNetworkConfig>
          cros_network_config,
      mojo::PendingRemote<::sharing::mojom::FirewallHoleFactory>
          firewall_hole_factory,
      mojo::PendingRemote<::sharing::mojom::TcpSocketFactory>
          tcp_socket_factory,
      mojo::PendingRemote<::sharing::mojom::MdnsManager> mdns_manager,
      mojo::PendingRemote<ash::wifi_direct::mojom::WifiDirectManager>
          wifi_direct_manager,
      mojo::PendingRemote<::sharing::mojom::FirewallHoleFactory>
          wifi_direct_firewall_hole_factory) {
    auto webrtc_dependencies = ::sharing::mojom::WebRtcDependencies::New(
        std::move(socket_manager), std::move(mdns_responder_factory),
        std::move(ice_config_fetcher), std::move(webrtc_signaling_messenger));
    auto wifilan_dependencies = ::sharing::mojom::WifiLanDependencies::New(
        std::move(cros_network_config), std::move(firewall_hole_factory),
        std::move(tcp_socket_factory), std::move(mdns_manager));
    auto wifidirect_dependencies =
        ::sharing::mojom::WifiDirectDependencies::New(
            std::move(wifi_direct_manager),
            std::move(wifi_direct_firewall_hole_factory));
    auto dependencies = ::sharing::mojom::NearbyDependencies::New(
        std::move(bluetooth_adapter), std::move(webrtc_dependencies),
        std::move(wifilan_dependencies), std::move(wifidirect_dependencies),
        std::move(nearby_presence_credential_storage),
        nearby::api::LogMessage::Severity::kInfo);
    base::RunLoop run_loop;
    service_->Connect(std::move(dependencies), std::move(connections_receiver),
                      std::move(presence_receiver), std::move(decoder_receiver),
                      std::move(quick_start_decoder_receiver));

    // Run Mojo connection handlers.
    base::RunLoop().RunUntilIdle();
  }

  void ShutDown() {
    service_->ShutDown(base::DoNothing());

    // Run Mojo disconnection handlers.
    base::RunLoop().RunUntilIdle();
  }

  bool AreNearbyInstancesActive() {
    return service_->nearby_connections_ && service_->nearby_presence_ &&
           service_->nearby_decoder_ && service_->quick_start_decoder_;
  }

  void EnsureDependenciesAreDisconnected() {
    // Run mojo disconnect handlers.
    base::RunLoop().RunUntilIdle();

    EXPECT_FALSE(AreNearbyInstancesActive());
  }

 protected:
  base::test::TaskEnvironment task_environment_;
  mojo::Remote<mojom::Sharing> remote_;
  std::unique_ptr<SharingImpl> service_;

  mojo::Remote<nearby::connections::mojom::NearbyConnections> connections_;
  mojo::Remote<ash::nearby::presence::mojom::NearbyPresence> presence_;
  mojo::Remote<::sharing::mojom::NearbySharingDecoder> decoder_;
  mojo::Remote<ash::quick_start::mojom::QuickStartDecoder> quick_start_decoder_;
  bluetooth::FakeAdapter bluetooth_adapter_;
  ash::nearby::presence::FakeNearbyPresenceCredentialStorage
      nearby_presence_credential_storage_;
  sharing::MockWebRtcDependencies webrtc_dependencies_;
  std::unique_ptr<ash::network_config::CrosNetworkConfigTestHelper>
      cros_network_config_test_helper_;
  mojo::SelfOwnedReceiverRef<::sharing::mojom::FirewallHoleFactory>
      firewall_hole_factory_self_owned_receiver_ref_;
  mojo::SelfOwnedReceiverRef<::sharing::mojom::TcpSocketFactory>
      tcp_socket_factory_self_owned_receiver_ref_;
  mojo::SelfOwnedReceiverRef<::sharing::mojom::MdnsManager>
      mdns_manager_self_owned_receiver_ref_;
  mojo::SelfOwnedReceiverRef<ash::wifi_direct::mojom::WifiDirectManager>
      wifi_direct_manager_self_owned_receiver_ref_;
  mojo::SelfOwnedReceiverRef<::sharing::mojom::FirewallHoleFactory>
      wifi_direct_firewall_hole_factory_self_owned_receiver_ref_;
};

TEST_F(SharingImplTest, ConnectAndShutDown) {
  ShutDown();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_BluetoothDisconnects) {
  bluetooth_adapter_.adapter_.reset();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_CredentialStorageDisconnects) {
  nearby_presence_credential_storage_.receiver().reset();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_WebRtcSignalingMessengerDisconnects) {
  webrtc_dependencies_.messenger_.reset();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest,
       NearbyConnections_WebRtcMdnsResponderFactoryDisconnects) {
  webrtc_dependencies_.mdns_responder_factory_.reset();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_WebRtcP2PSocketManagerDisconnects) {
  webrtc_dependencies_.socket_manager_.reset();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_WebRtcIceConfigFetcherDisconnects) {
  webrtc_dependencies_.ice_config_fetcher_.reset();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_CrosNetworkConfigDisconnects) {
  cros_network_config_test_helper_.reset();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_FirewallHoleFactoryDisconnects) {
  firewall_hole_factory_self_owned_receiver_ref_->Close();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_TcpSocketFactoryDisconnects) {
  tcp_socket_factory_self_owned_receiver_ref_->Close();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_MdnsManagerDisconnects) {
  mdns_manager_self_owned_receiver_ref_->Close();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_WifiDirectManagerDisconnects) {
  wifi_direct_manager_self_owned_receiver_ref_->Close();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest,
       NearbyConnections_WifiDirectFirewallHoleFactoryDisconnects) {
  wifi_direct_firewall_hole_factory_self_owned_receiver_ref_->Close();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_ConnectionsReset) {
  connections_.reset();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_PresenceReset) {
  presence_.reset();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_DecoderReset) {
  decoder_.reset();
  EnsureDependenciesAreDisconnected();
}

TEST_F(SharingImplTest, NearbyConnections_QuickStartDecoderReset) {
  quick_start_decoder_.reset();
  EnsureDependenciesAreDisconnected();
}

}  // namespace sharing