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

// Copyright 2016 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/network_connection_handler_tether_delegate.h"

#include <memory>

#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "chromeos/ash/components/network/network_connection_handler.h"
#include "chromeos/ash/components/tether/fake_active_host.h"
#include "chromeos/ash/components/tether/fake_tether_connector.h"
#include "chromeos/ash/components/tether/fake_tether_disconnector.h"
#include "chromeos/ash/components/tether/tether_disconnector.h"
#include "chromeos/ash/components/tether/tether_session_completion_logger.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash {

namespace tether {

namespace {

const char kSuccessResult[] = "success";

// Does nothing when a connection is requested.
class DummyTetherConnector : public FakeTetherConnector {
 public:
  // TetherConnector:
  void ConnectToNetwork(const std::string& tether_network_guid,
                        base::OnceClosure success_callback,
                        StringErrorCallback error_callback) override {}
};

// Does nothing when a disconnection is requested.
class DummyTetherDisconnector : public FakeTetherDisconnector {
 public:
  // TetherDisconnector:
  void DisconnectFromNetwork(
      const std::string& tether_network_guid,
      base::OnceClosure success_callback,
      StringErrorCallback error_callback,
      const TetherSessionCompletionLogger::SessionCompletionReason&
          session_completion_reason) override {}
};

class TestNetworkConnectionHandler : public NetworkConnectionHandler {
 public:
  TestNetworkConnectionHandler() : NetworkConnectionHandler() {}
  ~TestNetworkConnectionHandler() override = default;

  void CallTetherConnect(const std::string& tether_network_guid,
                         base::OnceClosure success_callback,
                         network_handler::ErrorCallback error_callback) {
    InitiateTetherNetworkConnection(tether_network_guid,
                                    std::move(success_callback),
                                    std::move(error_callback));
  }

  void CallTetherDisconnect(const std::string& tether_network_guid,
                            base::OnceClosure success_callback,
                            network_handler::ErrorCallback error_callback) {
    InitiateTetherNetworkDisconnection(tether_network_guid,
                                       std::move(success_callback),
                                       std::move(error_callback));
  }

  // NetworkConnectionHandler:
  void ConnectToNetwork(const std::string& service_path,
                        base::OnceClosure success_callback,
                        network_handler::ErrorCallback error_callback,
                        bool check_error_state,
                        ConnectCallbackMode mode) override {}

  void DisconnectNetwork(
      const std::string& service_path,
      base::OnceClosure success_callback,
      network_handler::ErrorCallback error_callback) override {}

  void Init(
      NetworkStateHandler* network_state_handler,
      NetworkConfigurationHandler* network_configuration_handler,
      ManagedNetworkConfigurationHandler* managed_network_configuration_handler,
      CellularConnectionHandler* cellular_connection_handler) override {}

  void OnAutoConnectedInitiated(int auto_connect_reasons) override {}
};

}  // namespace

class NetworkConnectionHandlerTetherDelegateTest : public testing::Test {
 public:
  NetworkConnectionHandlerTetherDelegateTest(
      const NetworkConnectionHandlerTetherDelegateTest&) = delete;
  NetworkConnectionHandlerTetherDelegateTest& operator=(
      const NetworkConnectionHandlerTetherDelegateTest&) = delete;

 protected:
  NetworkConnectionHandlerTetherDelegateTest() = default;

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

    test_network_connection_handler_ =
        base::WrapUnique(new TestNetworkConnectionHandler());

    fake_active_host_ = std::make_unique<FakeActiveHost>();
    fake_tether_connector_ = std::make_unique<FakeTetherConnector>();
    fake_tether_disconnector_ = std::make_unique<FakeTetherDisconnector>();

    delegate_ = std::make_unique<NetworkConnectionHandlerTetherDelegate>(
        test_network_connection_handler_.get(), fake_active_host_.get(),
        fake_tether_connector_.get(), fake_tether_disconnector_.get());
  }

  void TearDown() override {
    // No more callbacks should occur after deletion.
    delegate_.reset();
    EXPECT_EQ(std::string(), GetResultAndReset());
  }

  void CallTetherConnect(const std::string& guid) {
    test_network_connection_handler_->CallTetherConnect(
        guid,
        base::BindOnce(&NetworkConnectionHandlerTetherDelegateTest::OnSuccess,
                       base::Unretained(this)),
        base::BindOnce(&NetworkConnectionHandlerTetherDelegateTest::OnError,
                       base::Unretained(this)));
  }

  void CallTetherDisconnect(const std::string& guid) {
    test_network_connection_handler_->CallTetherDisconnect(
        guid,
        base::BindOnce(&NetworkConnectionHandlerTetherDelegateTest::OnSuccess,
                       base::Unretained(this)),
        base::BindOnce(&NetworkConnectionHandlerTetherDelegateTest::OnError,
                       base::Unretained(this)));
  }

  void OnSuccess() { result_ = kSuccessResult; }

  void OnError(const std::string& error) { result_ = error; }

  std::string GetResultAndReset() {
    std::string result;
    result.swap(result_);
    return result;
  }

  std::unique_ptr<TestNetworkConnectionHandler>
      test_network_connection_handler_;
  std::unique_ptr<FakeActiveHost> fake_active_host_;
  std::unique_ptr<FakeTetherConnector> fake_tether_connector_;
  std::unique_ptr<FakeTetherDisconnector> fake_tether_disconnector_;

  std::string result_;

  std::unique_ptr<NetworkConnectionHandlerTetherDelegate> delegate_;
};

TEST_F(NetworkConnectionHandlerTetherDelegateTest,
       TestConnect_NotAlreadyConnected) {
  CallTetherConnect("tetherNetworkGuid");
  EXPECT_EQ("tetherNetworkGuid",
            fake_tether_connector_->last_connected_tether_network_guid());
  EXPECT_EQ(kSuccessResult, GetResultAndReset());
}

TEST_F(NetworkConnectionHandlerTetherDelegateTest,
       TestConnect_AlreadyConnectedToSameDevice) {
  fake_active_host_->SetActiveHostConnected("activeHostId", "tetherNetworkGuid",
                                            "wifiNetworkGuid");
  CallTetherConnect("tetherNetworkGuid");
  EXPECT_TRUE(
      fake_tether_connector_->last_connected_tether_network_guid().empty());
  EXPECT_TRUE(fake_tether_disconnector_->last_disconnected_tether_network_guid()
                  .empty());
  EXPECT_EQ(NetworkConnectionHandler::kErrorConnected, GetResultAndReset());
}

TEST_F(NetworkConnectionHandlerTetherDelegateTest,
       TestConnect_AlreadyConnectedToDifferentDevice) {
  fake_active_host_->SetActiveHostConnected("activeHostId", "tetherNetworkGuid",
                                            "wifiNetworkGuid");

  CallTetherConnect("newTetherNetworkGuid");
  EXPECT_EQ("tetherNetworkGuid",
            fake_tether_disconnector_->last_disconnected_tether_network_guid());
  EXPECT_EQ("newTetherNetworkGuid",
            fake_tether_connector_->last_connected_tether_network_guid());
  EXPECT_EQ(kSuccessResult, GetResultAndReset());
}

TEST_F(NetworkConnectionHandlerTetherDelegateTest, TestDisconnect) {
  CallTetherDisconnect("tetherNetworkGuid");
  EXPECT_EQ("tetherNetworkGuid",
            fake_tether_disconnector_->last_disconnected_tether_network_guid());
  EXPECT_EQ(
      TetherSessionCompletionLogger::SessionCompletionReason::USER_DISCONNECTED,
      *fake_tether_disconnector_->last_session_completion_reason());
  EXPECT_EQ(kSuccessResult, GetResultAndReset());
}

TEST_F(NetworkConnectionHandlerTetherDelegateTest,
       TestPendingCallbacksInvokedWhenDeleted) {
  delegate_.reset();

  // Use "dummy" connector/disconnector.
  std::unique_ptr<DummyTetherConnector> dummy_connector =
      base::WrapUnique(new DummyTetherConnector());
  std::unique_ptr<DummyTetherDisconnector> dummy_disconnector =
      base::WrapUnique(new DummyTetherDisconnector());

  test_network_connection_handler_ =
      base::WrapUnique(new TestNetworkConnectionHandler());
  delegate_ = std::make_unique<NetworkConnectionHandlerTetherDelegate>(
      test_network_connection_handler_.get(), fake_active_host_.get(),
      dummy_connector.get(), dummy_disconnector.get());

  CallTetherConnect("tetherNetworkGuid");

  // No callbacks should have been invoked.
  EXPECT_TRUE(result_.empty());

  // Now, delete the delegate. It should fire the error callback.
  delegate_.reset();
  EXPECT_EQ(NetworkConnectionHandler::kErrorConnectFailed, GetResultAndReset());
}

}  // namespace tether

}  // namespace ash