/*
 *  Copyright 2016 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 "webrtc/p2p/quic/reliablequicstream.h"

#include <memory>
#include <string>

#include "net/base/ip_address_number.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_session.h"
#include "webrtc/base/buffer.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/sigslot.h"
#include "webrtc/base/stream.h"
#include "webrtc/p2p/quic/quicconnectionhelper.h"

using cricket::QuicConnectionHelper;
using cricket::ReliableQuicStream;

using net::IPAddress;
using net::IPEndPoint;
using net::PerPacketOptions;
using net::Perspective;
using net::QuicAckListenerInterface;
using net::QuicConfig;
using net::QuicConnection;
using net::QuicConsumedData;
using net::QuicCryptoStream;
using net::QuicErrorCode;
using net::QuicIOVector;
using net::QuicPacketWriter;
using net::QuicRstStreamErrorCode;
using net::QuicSession;
using net::QuicStreamId;
using net::QuicStreamOffset;
using net::SpdyPriority;

using rtc::SR_SUCCESS;
using rtc::SR_BLOCK;

// Arbitrary number for a stream's write blocked priority.
static const SpdyPriority kDefaultPriority = 3;

// QuicSession that does not create streams and writes data from
// ReliableQuicStream to a string.
class MockQuicSession : public QuicSession {
 public:
  MockQuicSession(QuicConnection* connection,
                  const QuicConfig& config,
                  std::string* write_buffer)
      : QuicSession(connection, config), write_buffer_(write_buffer) {}

  // Writes outgoing data from ReliableQuicStream to a string.
  QuicConsumedData WritevData(
      QuicStreamId id,
      QuicIOVector iovector,
      QuicStreamOffset offset,
      bool fin,
      QuicAckListenerInterface* ack_notifier_delegate) override {
    if (!writable_) {
      return QuicConsumedData(0, false);
    }

    const char* data = reinterpret_cast<const char*>(iovector.iov->iov_base);
    size_t len = iovector.total_length;
    write_buffer_->append(data, len);
    return QuicConsumedData(len, false);
  }

  net::ReliableQuicStream* CreateIncomingDynamicStream(
      QuicStreamId id) override {
    return nullptr;
  }

  net::ReliableQuicStream* CreateOutgoingDynamicStream(
      SpdyPriority priority) override {
    return nullptr;
  }

  QuicCryptoStream* GetCryptoStream() override { return nullptr; }

  // Called by ReliableQuicStream when they want to close stream.
  void SendRstStream(QuicStreamId id,
                     QuicRstStreamErrorCode error,
                     QuicStreamOffset bytes_written) override {}

  // Sets whether data is written to buffer, or else if this is write blocked.
  void set_writable(bool writable) { writable_ = writable; }

  // Tracks whether the stream is write blocked and its priority.
  void register_write_blocked_stream(QuicStreamId stream_id,
                                     SpdyPriority priority) {
    write_blocked_streams()->RegisterStream(stream_id, priority);
  }

 private:
  // Stores written data from ReliableQuicStream.
  std::string* write_buffer_;
  // Whether data is written to write_buffer_.
  bool writable_ = true;
};

// Packet writer that does nothing. This is required for QuicConnection but
// isn't used for writing data.
class DummyPacketWriter : public QuicPacketWriter {
 public:
  DummyPacketWriter() {}

  // QuicPacketWriter overrides.
  net::WriteResult WritePacket(const char* buffer,
                               size_t buf_len,
                               const IPAddress& self_address,
                               const IPEndPoint& peer_address,
                               PerPacketOptions* options) override {
    return net::WriteResult(net::WRITE_STATUS_ERROR, 0);
  }

  bool IsWriteBlockedDataBuffered() const override { return false; }

  bool IsWriteBlocked() const override { return false; };

  void SetWritable() override {}

  net::QuicByteCount GetMaxPacketSize(
      const net::IPEndPoint& peer_address) const override {
    return 0;
  }
};

class ReliableQuicStreamTest : public ::testing::Test,
                               public sigslot::has_slots<> {
 public:
  ReliableQuicStreamTest() {}

  void CreateReliableQuicStream() {
    const net::QuicStreamId kStreamId = 5;

    // Arbitrary values for QuicConnection.
    QuicConnectionHelper* quic_helper =
        new QuicConnectionHelper(rtc::Thread::Current());
    Perspective perspective = Perspective::IS_SERVER;
    net::IPAddress ip(0, 0, 0, 0);

    bool owns_writer = true;

    QuicConnection* connection = new QuicConnection(
        0, IPEndPoint(ip, 0), quic_helper, new DummyPacketWriter(), owns_writer,
        perspective, net::QuicSupportedVersions());

    session_.reset(
        new MockQuicSession(connection, QuicConfig(), &write_buffer_));
    stream_.reset(new ReliableQuicStream(kStreamId, session_.get()));
    stream_->SignalDataReceived.connect(
        this, &ReliableQuicStreamTest::OnDataReceived);
    stream_->SignalClosed.connect(this, &ReliableQuicStreamTest::OnClosed);
    stream_->SignalQueuedBytesWritten.connect(
        this, &ReliableQuicStreamTest::OnQueuedBytesWritten);

    session_->register_write_blocked_stream(stream_->id(), kDefaultPriority);
  }

  void OnDataReceived(QuicStreamId id, const char* data, size_t length) {
    ASSERT_EQ(id, stream_->id());
    read_buffer_.append(data, length);
  }

  void OnClosed(QuicStreamId id, int err) { closed_ = true; }

  void OnQueuedBytesWritten(QuicStreamId id, uint64_t queued_bytes_written) {
    queued_bytes_written_ = queued_bytes_written;
  }

 protected:
  std::unique_ptr<ReliableQuicStream> stream_;
  std::unique_ptr<MockQuicSession> session_;

  // Data written by the ReliableQuicStream.
  std::string write_buffer_;
  // Data read by the ReliableQuicStream.
  std::string read_buffer_;
  // Whether the ReliableQuicStream is closed.
  bool closed_ = false;
  // Bytes written by OnCanWrite().
  uint64_t queued_bytes_written_;
};

// Write an entire string.
TEST_F(ReliableQuicStreamTest, WriteDataWhole) {
  CreateReliableQuicStream();
  EXPECT_EQ(SR_SUCCESS, stream_->Write("Foo bar", 7));

  EXPECT_EQ("Foo bar", write_buffer_);
}

// Write part of a string.
TEST_F(ReliableQuicStreamTest, WriteDataPartial) {
  CreateReliableQuicStream();
  EXPECT_EQ(SR_SUCCESS, stream_->Write("Hello, World!", 8));
  EXPECT_EQ("Hello, W", write_buffer_);
}

// Test that strings are buffered correctly.
TEST_F(ReliableQuicStreamTest, BufferData) {
  CreateReliableQuicStream();

  session_->set_writable(false);
  EXPECT_EQ(SR_BLOCK, stream_->Write("Foo bar", 7));

  EXPECT_EQ(0ul, write_buffer_.size());
  EXPECT_TRUE(stream_->HasBufferedData());

  session_->set_writable(true);
  stream_->OnCanWrite();
  EXPECT_EQ(7ul, queued_bytes_written_);

  EXPECT_FALSE(stream_->HasBufferedData());
  EXPECT_EQ("Foo bar", write_buffer_);

  EXPECT_EQ(SR_SUCCESS, stream_->Write("xyzzy", 5));
  EXPECT_EQ("Foo barxyzzy", write_buffer_);
}

// Read an entire string.
TEST_F(ReliableQuicStreamTest, ReadDataWhole) {
  CreateReliableQuicStream();
  net::QuicStreamFrame frame(-1, false, 0, "Hello, World!");
  stream_->OnStreamFrame(frame);

  EXPECT_EQ("Hello, World!", read_buffer_);
}

// Read part of a string.
TEST_F(ReliableQuicStreamTest, ReadDataPartial) {
  CreateReliableQuicStream();
  net::QuicStreamFrame frame(-1, false, 0, "Hello, World!");
  frame.frame_length = 5;
  stream_->OnStreamFrame(frame);

  EXPECT_EQ("Hello", read_buffer_);
}

// Test that closing the stream results in a callback.
TEST_F(ReliableQuicStreamTest, CloseStream) {
  CreateReliableQuicStream();
  EXPECT_FALSE(closed_);
  stream_->OnClose();
  EXPECT_TRUE(closed_);
}
