// 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 "quiche/quic/core/quic_trace_visitor.h"

#include "quiche/quic/core/quic_constants.h"
#include "quiche/quic/platform/api/quic_test.h"
#include "quiche/quic/test_tools/quic_test_utils.h"
#include "quiche/quic/test_tools/simulator/quic_endpoint.h"
#include "quiche/quic/test_tools/simulator/simulator.h"
#include "quiche/quic/test_tools/simulator/switch.h"

namespace quic::test {
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);
    QUICHE_CHECK(simulator_result);

    // Save the trace and ensure some loss was observed.
    trace_.Swap(visitor.trace());
    QUICHE_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());
  // Ensure version isn't all-zeroes.
  EXPECT_TRUE(version[0] != 0 || version[1] != 0 || version[2] != 0 ||
              version[3] != 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());
}

TEST_F(QuicTraceVisitorTest, EncryptionLevels) {
  for (const auto& event : trace_.events()) {
    switch (event.event_type()) {
      case quic_trace::PACKET_SENT:
      case quic_trace::PACKET_RECEIVED:
      case quic_trace::PACKET_LOST:
        ASSERT_TRUE(event.has_encryption_level());
        ASSERT_NE(event.encryption_level(), quic_trace::ENCRYPTION_UNKNOWN);
        break;

      default:
        break;
    }
  }
}

}  // namespace
}  // namespace quic::test
