// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/third_party/quiche/src/quic/core/quic_trace_visitor.h"

#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"

namespace quic {
namespace {

const QuicByteCount kTransferSize = 1000 * kMaxOutgoingPacketSize;
const QuicByteCount kTestStreamNumber = 3;
const QuicTime::Delta kDelay = QuicTime::Delta::FromMilliseconds(20);

// The trace for this test is generated using a simulator transfer.
class QuicTraceVisitorTest : public QuicTest {
 public:
  QuicTraceVisitorTest() {
    QuicConnectionId connection_id = test::TestConnectionId();
    simulator::Simulator simulator;
    simulator::QuicEndpoint client(&simulator, "Client", "Server",
                                   Perspective::IS_CLIENT, connection_id);
    simulator::QuicEndpoint server(&simulator, "Server", "Client",
                                   Perspective::IS_SERVER, connection_id);

    const QuicBandwidth kBandwidth = QuicBandwidth::FromKBitsPerSecond(1000);
    const QuicByteCount kBdp = kBandwidth * (2 * kDelay);

    // Create parameters such that some loss is observed.
    simulator::Switch network_switch(&simulator, "Switch", 8, 0.5 * kBdp);
    simulator::SymmetricLink client_link(&client, network_switch.port(1),
                                         2 * kBandwidth, kDelay);
    simulator::SymmetricLink server_link(&server, network_switch.port(2),
                                         kBandwidth, kDelay);

    QuicTraceVisitor visitor(client.connection());
    client.connection()->set_debug_visitor(&visitor);

    // Transfer about a megabyte worth of data from client to server.
    const QuicTime::Delta kDeadline =
        3 * kBandwidth.TransferTime(kTransferSize);
    client.AddBytesToTransfer(kTransferSize);
    bool simulator_result = simulator.RunUntilOrTimeout(
        [&]() { return server.bytes_received() >= kTransferSize; }, kDeadline);
    CHECK(simulator_result);

    // Save the trace and ensure some loss was observed.
    trace_.Swap(visitor.trace());
    CHECK_NE(0u, client.connection()->GetStats().packets_retransmitted);
    packets_sent_ = client.connection()->GetStats().packets_sent;
  }

  std::vector<quic_trace::Event> AllEventsWithType(
      quic_trace::EventType event_type) {
    std::vector<quic_trace::Event> result;
    for (const auto& event : trace_.events()) {
      if (event.event_type() == event_type) {
        result.push_back(event);
      }
    }
    return result;
  }

 protected:
  quic_trace::Trace trace_;
  QuicPacketCount packets_sent_;
};

TEST_F(QuicTraceVisitorTest, ConnectionId) {
  char expected_cid[] = {0, 0, 0, 0, 0, 0, 0, 42};
  EXPECT_EQ(std::string(expected_cid, sizeof(expected_cid)),
            trace_.destination_connection_id());
}

TEST_F(QuicTraceVisitorTest, Version) {
  std::string version = trace_.protocol_version();
  ASSERT_EQ(4u, version.size());
  EXPECT_EQ('Q', version[0]);
}

// Check that basic metadata about sent packets is recorded.
TEST_F(QuicTraceVisitorTest, SentPacket) {
  auto sent_packets = AllEventsWithType(quic_trace::PACKET_SENT);
  EXPECT_EQ(packets_sent_, sent_packets.size());
  ASSERT_GT(sent_packets.size(), 0u);

  EXPECT_EQ(sent_packets[0].packet_size(), kDefaultMaxPacketSize);
  EXPECT_EQ(sent_packets[0].packet_number(), 1u);
}

// Ensure that every stream frame that was sent is recorded.
TEST_F(QuicTraceVisitorTest, SentStream) {
  auto sent_packets = AllEventsWithType(quic_trace::PACKET_SENT);

  QuicIntervalSet<QuicStreamOffset> offsets;
  for (const quic_trace::Event& packet : sent_packets) {
    for (const quic_trace::Frame& frame : packet.frames()) {
      if (frame.frame_type() != quic_trace::STREAM) {
        continue;
      }

      const quic_trace::StreamFrameInfo& info = frame.stream_frame_info();
      if (info.stream_id() != kTestStreamNumber) {
        continue;
      }

      ASSERT_GT(info.length(), 0u);
      offsets.Add(info.offset(), info.offset() + info.length());
    }
  }

  ASSERT_EQ(1u, offsets.Size());
  EXPECT_EQ(0u, offsets.begin()->min());
  EXPECT_EQ(kTransferSize, offsets.rbegin()->max());
}

// Ensure that all packets are either acknowledged or lost.
TEST_F(QuicTraceVisitorTest, AckPackets) {
  QuicIntervalSet<QuicPacketNumber> packets;
  for (const quic_trace::Event& packet : trace_.events()) {
    if (packet.event_type() == quic_trace::PACKET_RECEIVED) {
      for (const quic_trace::Frame& frame : packet.frames()) {
        if (frame.frame_type() != quic_trace::ACK) {
          continue;
        }

        const quic_trace::AckInfo& info = frame.ack_info();
        for (const auto& block : info.acked_packets()) {
          packets.Add(QuicPacketNumber(block.first_packet()),
                      QuicPacketNumber(block.last_packet()) + 1);
        }
      }
    }
    if (packet.event_type() == quic_trace::PACKET_LOST) {
      packets.Add(QuicPacketNumber(packet.packet_number()),
                  QuicPacketNumber(packet.packet_number()) + 1);
    }
  }

  ASSERT_EQ(1u, packets.Size());
  EXPECT_EQ(QuicPacketNumber(1u), packets.begin()->min());
  // We leave some room (20 packets) for the packets which did not receive
  // conclusive status at the end of simulation.
  EXPECT_GT(packets.rbegin()->max(), QuicPacketNumber(packets_sent_ - 20));
}

TEST_F(QuicTraceVisitorTest, TransportState) {
  auto acks = AllEventsWithType(quic_trace::PACKET_RECEIVED);
  ASSERT_EQ(1, acks[0].frames_size());
  ASSERT_EQ(quic_trace::ACK, acks[0].frames(0).frame_type());

  // Check that min-RTT at the end is a reasonable approximation.
  EXPECT_LE((4 * kDelay).ToMicroseconds() * 1.,
            acks.rbegin()->transport_state().min_rtt_us());
  EXPECT_GE((4 * kDelay).ToMicroseconds() * 1.25,
            acks.rbegin()->transport_state().min_rtt_us());
}

}  // namespace
}  // namespace quic
