/*
 *  Copyright 2017 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 <memory>

#include "media/base/fakemediaengine.h"
#include "ortc/ortcfactory.h"
#include "ortc/testrtpparameters.h"
#include "p2p/base/fakepackettransport.h"
#include "rtc_base/gunit.h"

namespace webrtc {

// This test uses fake packet transports and a fake media engine, in order to
// test the RtpTransport at only an API level. Any end-to-end test should go in
// ortcfactory_integrationtest.cc instead.
class RtpTransportTest : public testing::Test {
 public:
  RtpTransportTest() {
    fake_media_engine_ = new cricket::FakeMediaEngine();
    // Note: This doesn't need to use fake network classes, since it uses
    // FakePacketTransports.
    auto result = OrtcFactory::Create(
        nullptr, nullptr, nullptr, nullptr, nullptr,
        std::unique_ptr<cricket::MediaEngineInterface>(fake_media_engine_));
    ortc_factory_ = result.MoveValue();
  }

 protected:
  // Owned by |ortc_factory_|.
  cricket::FakeMediaEngine* fake_media_engine_;
  std::unique_ptr<OrtcFactoryInterface> ortc_factory_;
};

// Test GetRtpPacketTransport and GetRtcpPacketTransport, with and without RTCP
// muxing.
TEST_F(RtpTransportTest, GetPacketTransports) {
  rtc::FakePacketTransport rtp("rtp");
  rtc::FakePacketTransport rtcp("rtcp");
  // With muxed RTCP.
  RtpTransportParameters parameters;
  parameters.rtcp.mux = true;
  auto result =
      ortc_factory_->CreateRtpTransport(parameters, &rtp, nullptr, nullptr);
  ASSERT_TRUE(result.ok());
  EXPECT_EQ(&rtp, result.value()->GetRtpPacketTransport());
  EXPECT_EQ(nullptr, result.value()->GetRtcpPacketTransport());
  result.MoveValue().reset();
  // With non-muxed RTCP.
  parameters.rtcp.mux = false;
  result = ortc_factory_->CreateRtpTransport(parameters, &rtp, &rtcp, nullptr);
  ASSERT_TRUE(result.ok());
  EXPECT_EQ(&rtp, result.value()->GetRtpPacketTransport());
  EXPECT_EQ(&rtcp, result.value()->GetRtcpPacketTransport());
}

// If an RtpTransport starts out un-muxed and then starts muxing, the RTCP
// packet transport should be forgotten and GetRtcpPacketTransport should
// return null.
TEST_F(RtpTransportTest, EnablingRtcpMuxingUnsetsRtcpTransport) {
  rtc::FakePacketTransport rtp("rtp");
  rtc::FakePacketTransport rtcp("rtcp");

  // Create non-muxed.
  RtpTransportParameters parameters;
  parameters.rtcp.mux = false;
  auto result =
      ortc_factory_->CreateRtpTransport(parameters, &rtp, &rtcp, nullptr);
  ASSERT_TRUE(result.ok());
  auto rtp_transport = result.MoveValue();

  // Enable muxing.
  parameters.rtcp.mux = true;
  EXPECT_TRUE(rtp_transport->SetParameters(parameters).ok());
  EXPECT_EQ(nullptr, rtp_transport->GetRtcpPacketTransport());
}

TEST_F(RtpTransportTest, GetAndSetRtcpParameters) {
  rtc::FakePacketTransport rtp("rtp");
  rtc::FakePacketTransport rtcp("rtcp");
  // Start with non-muxed RTCP.
  RtpTransportParameters parameters;
  parameters.rtcp.mux = false;
  parameters.rtcp.cname = "teST";
  parameters.rtcp.reduced_size = false;
  auto result =
      ortc_factory_->CreateRtpTransport(parameters, &rtp, &rtcp, nullptr);
  ASSERT_TRUE(result.ok());
  auto transport = result.MoveValue();
  EXPECT_EQ(parameters, transport->GetParameters());

  // Changing the CNAME is currently unsupported.
  parameters.rtcp.cname = "different";
  EXPECT_EQ(RTCErrorType::UNSUPPORTED_OPERATION,
            transport->SetParameters(parameters).type());
  parameters.rtcp.cname = "teST";

  // Enable RTCP muxing and reduced-size RTCP.
  parameters.rtcp.mux = true;
  parameters.rtcp.reduced_size = true;
  EXPECT_TRUE(transport->SetParameters(parameters).ok());
  EXPECT_EQ(parameters, transport->GetParameters());

  // Empty CNAME should result in the existing CNAME being used.
  parameters.rtcp.cname.clear();
  EXPECT_TRUE(transport->SetParameters(parameters).ok());
  EXPECT_EQ("teST", transport->GetParameters().rtcp.cname);

  // Disabling RTCP muxing after enabling shouldn't be allowed, since enabling
  // muxing should have made the RTP transport forget about the RTCP packet
  // transport initially passed into it.
  parameters.rtcp.mux = false;
  EXPECT_EQ(RTCErrorType::INVALID_STATE,
            transport->SetParameters(parameters).type());
}

// When Send or Receive is called on a sender or receiver, the RTCP parameters
// from the RtpTransport underneath the sender should be applied to the created
// media stream. The only relevant parameters (currently) are |cname| and
// |reduced_size|.
TEST_F(RtpTransportTest, SendAndReceiveApplyRtcpParametersToMediaEngine) {
  // First, create video transport with reduced-size RTCP.
  rtc::FakePacketTransport fake_packet_transport1("1");
  RtpTransportParameters parameters;
  parameters.rtcp.mux = true;
  parameters.rtcp.reduced_size = true;
  parameters.rtcp.cname = "foo";
  auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
      parameters, &fake_packet_transport1, nullptr, nullptr);
  auto video_transport = rtp_transport_result.MoveValue();

  // Create video sender and call Send, expecting parameters to be applied.
  auto sender_result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_VIDEO,
                                                      video_transport.get());
  auto video_sender = sender_result.MoveValue();
  EXPECT_TRUE(video_sender->Send(MakeMinimalVp8Parameters()).ok());
  cricket::FakeVideoMediaChannel* fake_video_channel =
      fake_media_engine_->GetVideoChannel(0);
  ASSERT_NE(nullptr, fake_video_channel);
  EXPECT_TRUE(fake_video_channel->send_rtcp_parameters().reduced_size);
  ASSERT_EQ(1u, fake_video_channel->send_streams().size());
  const cricket::StreamParams& video_send_stream =
      fake_video_channel->send_streams()[0];
  EXPECT_EQ("foo", video_send_stream.cname);

  // Create video receiver and call Receive, expecting parameters to be applied
  // (minus |cname|, since that's the sent cname, not received).
  auto receiver_result = ortc_factory_->CreateRtpReceiver(
      cricket::MEDIA_TYPE_VIDEO, video_transport.get());
  auto video_receiver = receiver_result.MoveValue();
  EXPECT_TRUE(
      video_receiver->Receive(MakeMinimalVp8ParametersWithSsrc(0xdeadbeef))
          .ok());
  EXPECT_TRUE(fake_video_channel->recv_rtcp_parameters().reduced_size);

  // Create audio transport with non-reduced size RTCP.
  rtc::FakePacketTransport fake_packet_transport2("2");
  parameters.rtcp.reduced_size = false;
  parameters.rtcp.cname = "bar";
  rtp_transport_result = ortc_factory_->CreateRtpTransport(
      parameters, &fake_packet_transport2, nullptr, nullptr);
  auto audio_transport = rtp_transport_result.MoveValue();

  // Create audio sender and call Send, expecting parameters to be applied.
  sender_result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_AUDIO,
                                                 audio_transport.get());
  auto audio_sender = sender_result.MoveValue();
  EXPECT_TRUE(audio_sender->Send(MakeMinimalIsacParameters()).ok());

  cricket::FakeVoiceMediaChannel* fake_voice_channel =
      fake_media_engine_->GetVoiceChannel(0);
  ASSERT_NE(nullptr, fake_voice_channel);
  EXPECT_FALSE(fake_voice_channel->send_rtcp_parameters().reduced_size);
  ASSERT_EQ(1u, fake_voice_channel->send_streams().size());
  const cricket::StreamParams& audio_send_stream =
      fake_voice_channel->send_streams()[0];
  EXPECT_EQ("bar", audio_send_stream.cname);

  // Create audio receiver and call Receive, expecting parameters to be applied
  // (minus |cname|, since that's the sent cname, not received).
  receiver_result = ortc_factory_->CreateRtpReceiver(cricket::MEDIA_TYPE_AUDIO,
                                                     audio_transport.get());
  auto audio_receiver = receiver_result.MoveValue();
  EXPECT_TRUE(
      audio_receiver->Receive(MakeMinimalOpusParametersWithSsrc(0xbaadf00d))
          .ok());
  EXPECT_FALSE(fake_voice_channel->recv_rtcp_parameters().reduced_size);
}

// When SetParameters is called, the modified parameters should be applied
// to the media engine.
// TODO(deadbeef): Once the implementation supports changing the CNAME,
// test that here.
TEST_F(RtpTransportTest, SetRtcpParametersAppliesParametersToMediaEngine) {
  rtc::FakePacketTransport fake_packet_transport("fake");
  RtpTransportParameters parameters;
  parameters.rtcp.mux = true;
  parameters.rtcp.reduced_size = false;
  auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
      parameters, &fake_packet_transport, nullptr, nullptr);
  auto rtp_transport = rtp_transport_result.MoveValue();

  // Create video sender and call Send, applying an initial set of parameters.
  auto sender_result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_VIDEO,
                                                      rtp_transport.get());
  auto sender = sender_result.MoveValue();
  EXPECT_TRUE(sender->Send(MakeMinimalVp8Parameters()).ok());

  // Modify parameters and expect them to be changed at the media engine level.
  parameters.rtcp.reduced_size = true;
  EXPECT_TRUE(rtp_transport->SetParameters(parameters).ok());

  cricket::FakeVideoMediaChannel* fake_video_channel =
      fake_media_engine_->GetVideoChannel(0);
  ASSERT_NE(nullptr, fake_video_channel);
  EXPECT_TRUE(fake_video_channel->send_rtcp_parameters().reduced_size);
}

// SetParameters should set keepalive for all RTP transports.
// It is impossible to modify keepalive parameters if any streams are created.
// Note: This is an implementation detail for current way of configuring the
// keep-alive. It may change in the future.
TEST_F(RtpTransportTest, CantChangeKeepAliveAfterCreatedSendStreams) {
  rtc::FakePacketTransport fake_packet_transport("fake");
  RtpTransportParameters parameters;
  parameters.keepalive.timeout_interval_ms = 100;
  auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
      parameters, &fake_packet_transport, nullptr, nullptr);
  ASSERT_TRUE(rtp_transport_result.ok());
  std::unique_ptr<RtpTransportInterface> rtp_transport =
      rtp_transport_result.MoveValue();

  // Updating keepalive parameters is ok, since no rtp sender created.
  parameters.keepalive.timeout_interval_ms = 200;
  EXPECT_TRUE(rtp_transport->SetParameters(parameters).ok());

  // Create video sender. Note: |sender_result| scope must extend past the
  // SetParameters() call below.
  auto sender_result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_VIDEO,
                                                      rtp_transport.get());
  EXPECT_TRUE(sender_result.ok());

  // Modify parameters second time after video send stream created.
  parameters.keepalive.timeout_interval_ms = 10;
  EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION,
            rtp_transport->SetParameters(parameters).type());
}

// Note: This is an implementation detail for current way of configuring the
// keep-alive. It may change in the future.
TEST_F(RtpTransportTest, KeepAliveMustBeSameAcrossTransportController) {
  rtc::FakePacketTransport fake_packet_transport("fake");
  RtpTransportParameters parameters;
  parameters.keepalive.timeout_interval_ms = 100;

  // Manually create a controller, that can be shared by multiple transports.
  auto controller_result = ortc_factory_->CreateRtpTransportController();
  ASSERT_TRUE(controller_result.ok());
  std::unique_ptr<RtpTransportControllerInterface> controller =
      controller_result.MoveValue();

  // Create a first transport.
  auto first_transport_result = ortc_factory_->CreateRtpTransport(
      parameters, &fake_packet_transport, nullptr, controller.get());
  ASSERT_TRUE(first_transport_result.ok());

  // Update the parameters, and create another transport for the same
  // controller.
  parameters.keepalive.timeout_interval_ms = 10;
  auto seconds_transport_result = ortc_factory_->CreateRtpTransport(
      parameters, &fake_packet_transport, nullptr, controller.get());
  EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION,
            seconds_transport_result.error().type());
}

}  // namespace webrtc
