/*
 *  Copyright 2009 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "p2p/base/wrapping_active_ice_controller.h"

#include <memory>
#include <utility>
#include <vector>

#include "p2p/base/connection.h"
#include "p2p/base/mock_ice_agent.h"
#include "p2p/base/mock_ice_controller.h"
#include "rtc_base/fake_clock.h"
#include "rtc_base/gunit.h"
#include "rtc_base/thread.h"

namespace {

using ::cricket::Connection;
using ::cricket::IceConfig;
using ::cricket::IceControllerFactoryArgs;
using ::cricket::IceControllerInterface;
using ::cricket::IceMode;
using ::cricket::IceRecheckEvent;
using ::cricket::IceSwitchReason;
using ::cricket::MockIceAgent;
using ::cricket::MockIceController;
using ::cricket::MockIceControllerFactory;
using ::cricket::NominationMode;
using ::cricket::WrappingActiveIceController;

using ::testing::_;
using ::testing::NiceMock;
using ::testing::Ref;
using ::testing::Return;
using ::testing::Sequence;

using ::rtc::AutoThread;
using ::rtc::Event;
using ::rtc::ScopedFakeClock;
using ::webrtc::TimeDelta;

using NiceMockIceController = NiceMock<MockIceController>;

static const Connection* kConnection =
    reinterpret_cast<const Connection*>(0xabcd);
static const Connection* kConnectionTwo =
    reinterpret_cast<const Connection*>(0xbcde);
static const Connection* kConnectionThree =
    reinterpret_cast<const Connection*>(0xcdef);

static const std::vector<const Connection*> kEmptyConnsList =
    std::vector<const Connection*>();

static const TimeDelta kTick = TimeDelta::Millis(1);

TEST(WrappingActiveIceControllerTest, CreateLegacyIceControllerFromFactory) {
  AutoThread main;
  MockIceAgent agent;
  IceControllerFactoryArgs args;
  MockIceControllerFactory legacy_controller_factory;
  EXPECT_CALL(legacy_controller_factory, RecordIceControllerCreated()).Times(1);
  WrappingActiveIceController controller(&agent, &legacy_controller_factory,
                                         args);
}

TEST(WrappingActiveIceControllerTest, PassthroughIceControllerInterface) {
  AutoThread main;
  MockIceAgent agent;
  std::unique_ptr<MockIceController> will_move =
      std::make_unique<MockIceController>(IceControllerFactoryArgs{});
  MockIceController* wrapped = will_move.get();
  WrappingActiveIceController controller(&agent, std::move(will_move));

  IceConfig config{};
  EXPECT_CALL(*wrapped, SetIceConfig(Ref(config)));
  controller.SetIceConfig(config);

  EXPECT_CALL(*wrapped,
              GetUseCandidateAttr(kConnection, NominationMode::AGGRESSIVE,
                                  IceMode::ICEMODE_LITE))
      .WillOnce(Return(true));
  EXPECT_TRUE(controller.GetUseCandidateAttribute(
      kConnection, NominationMode::AGGRESSIVE, IceMode::ICEMODE_LITE));

  EXPECT_CALL(*wrapped, AddConnection(kConnection));
  controller.OnConnectionAdded(kConnection);

  EXPECT_CALL(*wrapped, OnConnectionDestroyed(kConnection));
  controller.OnConnectionDestroyed(kConnection);

  EXPECT_CALL(*wrapped, SetSelectedConnection(kConnection));
  controller.OnConnectionSwitched(kConnection);

  EXPECT_CALL(*wrapped, MarkConnectionPinged(kConnection));
  controller.OnConnectionPinged(kConnection);

  EXPECT_CALL(*wrapped, FindNextPingableConnection())
      .WillOnce(Return(kConnection));
  EXPECT_EQ(controller.FindNextPingableConnection(), kConnection);
}

TEST(WrappingActiveIceControllerTest, HandlesImmediateSwitchRequest) {
  AutoThread main;
  ScopedFakeClock clock;
  NiceMock<MockIceAgent> agent;
  std::unique_ptr<NiceMockIceController> will_move =
      std::make_unique<NiceMockIceController>(IceControllerFactoryArgs{});
  NiceMockIceController* wrapped = will_move.get();
  WrappingActiveIceController controller(&agent, std::move(will_move));

  IceSwitchReason reason = IceSwitchReason::NOMINATION_ON_CONTROLLED_SIDE;
  std::vector<const Connection*> conns_to_forget{kConnectionTwo};
  int recheck_delay_ms = 10;
  IceControllerInterface::SwitchResult switch_result{
      kConnection,
      IceRecheckEvent(IceSwitchReason::ICE_CONTROLLER_RECHECK,
                      recheck_delay_ms),
      conns_to_forget};

  // ICE controller should switch to given connection immediately.
  Sequence check_then_switch;
  EXPECT_CALL(*wrapped, ShouldSwitchConnection(reason, kConnection))
      .InSequence(check_then_switch)
      .WillOnce(Return(switch_result));
  EXPECT_CALL(agent, SwitchSelectedConnection(kConnection, reason))
      .InSequence(check_then_switch);
  EXPECT_CALL(agent, ForgetLearnedStateForConnections(conns_to_forget));

  EXPECT_TRUE(controller.OnImmediateSwitchRequest(reason, kConnection));

  // No rechecks before recheck delay.
  clock.AdvanceTime(TimeDelta::Millis(recheck_delay_ms - 1));

  // ICE controller should recheck for best connection after the recheck delay.
  Sequence recheck_sort;
  EXPECT_CALL(agent, UpdateConnectionStates()).InSequence(recheck_sort);
  EXPECT_CALL(*wrapped,
              SortAndSwitchConnection(IceSwitchReason::ICE_CONTROLLER_RECHECK))
      .InSequence(recheck_sort)
      .WillOnce(Return(IceControllerInterface::SwitchResult{}));
  EXPECT_CALL(agent, ForgetLearnedStateForConnections(kEmptyConnsList));

  clock.AdvanceTime(kTick);
}

TEST(WrappingActiveIceControllerTest, HandlesImmediateSortAndSwitchRequest) {
  AutoThread main;
  ScopedFakeClock clock;
  NiceMock<MockIceAgent> agent;
  std::unique_ptr<NiceMockIceController> will_move =
      std::make_unique<NiceMockIceController>(IceControllerFactoryArgs{});
  NiceMockIceController* wrapped = will_move.get();
  WrappingActiveIceController controller(&agent, std::move(will_move));

  IceSwitchReason reason = IceSwitchReason::NEW_CONNECTION_FROM_LOCAL_CANDIDATE;
  std::vector<const Connection*> conns_to_forget{kConnectionTwo};
  std::vector<const Connection*> conns_to_prune{kConnectionThree};
  int recheck_delay_ms = 10;
  IceControllerInterface::SwitchResult switch_result{
      kConnection,
      IceRecheckEvent(IceSwitchReason::ICE_CONTROLLER_RECHECK,
                      recheck_delay_ms),
      conns_to_forget};

  Sequence sort_and_switch;
  EXPECT_CALL(agent, UpdateConnectionStates()).InSequence(sort_and_switch);
  EXPECT_CALL(*wrapped, SortAndSwitchConnection(reason))
      .InSequence(sort_and_switch)
      .WillOnce(Return(switch_result));
  EXPECT_CALL(agent, SwitchSelectedConnection(kConnection, reason))
      .InSequence(sort_and_switch);
  EXPECT_CALL(*wrapped, PruneConnections())
      .InSequence(sort_and_switch)
      .WillOnce(Return(conns_to_prune));
  EXPECT_CALL(agent, PruneConnections(conns_to_prune))
      .InSequence(sort_and_switch);

  controller.OnImmediateSortAndSwitchRequest(reason);

  // No rechecks before recheck delay.
  clock.AdvanceTime(TimeDelta::Millis(recheck_delay_ms - 1));

  // ICE controller should recheck for best connection after the recheck delay.
  Sequence recheck_sort;
  EXPECT_CALL(agent, UpdateConnectionStates()).InSequence(recheck_sort);
  EXPECT_CALL(*wrapped,
              SortAndSwitchConnection(IceSwitchReason::ICE_CONTROLLER_RECHECK))
      .InSequence(recheck_sort)
      .WillOnce(Return(IceControllerInterface::SwitchResult{}));
  EXPECT_CALL(*wrapped, PruneConnections())
      .InSequence(recheck_sort)
      .WillOnce(Return(kEmptyConnsList));
  EXPECT_CALL(agent, PruneConnections(kEmptyConnsList))
      .InSequence(recheck_sort);

  clock.AdvanceTime(kTick);
}

TEST(WrappingActiveIceControllerTest, HandlesSortAndSwitchRequest) {
  AutoThread main;
  ScopedFakeClock clock;

  // Block the main task queue until ready.
  Event init;
  TimeDelta init_delay = TimeDelta::Millis(10);
  main.PostTask([&init, &init_delay] { init.Wait(init_delay); });

  NiceMock<MockIceAgent> agent;
  std::unique_ptr<NiceMockIceController> will_move =
      std::make_unique<NiceMockIceController>(IceControllerFactoryArgs{});
  NiceMockIceController* wrapped = will_move.get();
  WrappingActiveIceController controller(&agent, std::move(will_move));

  IceSwitchReason reason = IceSwitchReason::NETWORK_PREFERENCE_CHANGE;

  // No action should occur immediately
  EXPECT_CALL(agent, UpdateConnectionStates()).Times(0);
  EXPECT_CALL(*wrapped, SortAndSwitchConnection(_)).Times(0);
  EXPECT_CALL(agent, SwitchSelectedConnection(_, _)).Times(0);

  controller.OnSortAndSwitchRequest(reason);

  std::vector<const Connection*> conns_to_forget{kConnectionTwo};
  int recheck_delay_ms = 10;
  IceControllerInterface::SwitchResult switch_result{
      kConnection,
      IceRecheckEvent(IceSwitchReason::ICE_CONTROLLER_RECHECK,
                      recheck_delay_ms),
      conns_to_forget};

  // Sort and switch should take place as the subsequent task.
  Sequence sort_and_switch;
  EXPECT_CALL(agent, UpdateConnectionStates()).InSequence(sort_and_switch);
  EXPECT_CALL(*wrapped, SortAndSwitchConnection(reason))
      .InSequence(sort_and_switch)
      .WillOnce(Return(switch_result));
  EXPECT_CALL(agent, SwitchSelectedConnection(kConnection, reason))
      .InSequence(sort_and_switch);

  // Unblock the init task.
  clock.AdvanceTime(init_delay);
}

TEST(WrappingActiveIceControllerTest, StartPingingAfterSortAndSwitch) {
  AutoThread main;
  ScopedFakeClock clock;

  // Block the main task queue until ready.
  Event init;
  TimeDelta init_delay = TimeDelta::Millis(10);
  main.PostTask([&init, &init_delay] { init.Wait(init_delay); });

  NiceMock<MockIceAgent> agent;
  std::unique_ptr<NiceMockIceController> will_move =
      std::make_unique<NiceMockIceController>(IceControllerFactoryArgs{});
  NiceMockIceController* wrapped = will_move.get();
  WrappingActiveIceController controller(&agent, std::move(will_move));

  // Pinging does not start automatically, unless triggered through a sort.
  EXPECT_CALL(*wrapped, HasPingableConnection()).Times(0);
  EXPECT_CALL(*wrapped, SelectConnectionToPing(_)).Times(0);
  EXPECT_CALL(agent, OnStartedPinging()).Times(0);

  controller.OnSortAndSwitchRequest(IceSwitchReason::DATA_RECEIVED);

  // Pinging does not start if no pingable connection.
  EXPECT_CALL(*wrapped, HasPingableConnection()).WillOnce(Return(false));
  EXPECT_CALL(*wrapped, SelectConnectionToPing(_)).Times(0);
  EXPECT_CALL(agent, OnStartedPinging()).Times(0);

  // Unblock the init task.
  clock.AdvanceTime(init_delay);

  int recheck_delay_ms = 10;
  IceControllerInterface::PingResult ping_result(kConnection, recheck_delay_ms);

  // Pinging starts when there is a pingable connection.
  Sequence start_pinging;
  EXPECT_CALL(*wrapped, HasPingableConnection())
      .InSequence(start_pinging)
      .WillOnce(Return(true));
  EXPECT_CALL(agent, OnStartedPinging()).InSequence(start_pinging);
  EXPECT_CALL(agent, GetLastPingSentMs())
      .InSequence(start_pinging)
      .WillOnce(Return(123));
  EXPECT_CALL(*wrapped, SelectConnectionToPing(123))
      .InSequence(start_pinging)
      .WillOnce(Return(ping_result));
  EXPECT_CALL(agent, SendPingRequest(kConnection)).InSequence(start_pinging);

  controller.OnSortAndSwitchRequest(IceSwitchReason::DATA_RECEIVED);
  clock.AdvanceTime(kTick);

  // ICE controller should recheck and ping after the recheck delay.
  // No ping should be sent if no connection selected to ping.
  EXPECT_CALL(agent, GetLastPingSentMs()).WillOnce(Return(456));
  EXPECT_CALL(*wrapped, SelectConnectionToPing(456))
      .WillOnce(Return(IceControllerInterface::PingResult(
          /* connection= */ nullptr, recheck_delay_ms)));
  EXPECT_CALL(agent, SendPingRequest(kConnection)).Times(0);

  clock.AdvanceTime(TimeDelta::Millis(recheck_delay_ms));
}

}  // namespace
