xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_trace_visitor_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/quic_trace_visitor.h"
6 
7 #include "quiche/quic/core/quic_constants.h"
8 #include "quiche/quic/platform/api/quic_test.h"
9 #include "quiche/quic/test_tools/quic_test_utils.h"
10 #include "quiche/quic/test_tools/simulator/quic_endpoint.h"
11 #include "quiche/quic/test_tools/simulator/simulator.h"
12 #include "quiche/quic/test_tools/simulator/switch.h"
13 
14 namespace quic::test {
15 namespace {
16 
17 const QuicByteCount kTransferSize = 1000 * kMaxOutgoingPacketSize;
18 const QuicByteCount kTestStreamNumber = 3;
19 const QuicTime::Delta kDelay = QuicTime::Delta::FromMilliseconds(20);
20 
21 // The trace for this test is generated using a simulator transfer.
22 class QuicTraceVisitorTest : public QuicTest {
23  public:
QuicTraceVisitorTest()24   QuicTraceVisitorTest() {
25     QuicConnectionId connection_id = test::TestConnectionId();
26     simulator::Simulator simulator;
27     simulator::QuicEndpoint client(&simulator, "Client", "Server",
28                                    Perspective::IS_CLIENT, connection_id);
29     simulator::QuicEndpoint server(&simulator, "Server", "Client",
30                                    Perspective::IS_SERVER, connection_id);
31 
32     const QuicBandwidth kBandwidth = QuicBandwidth::FromKBitsPerSecond(1000);
33     const QuicByteCount kBdp = kBandwidth * (2 * kDelay);
34 
35     // Create parameters such that some loss is observed.
36     simulator::Switch network_switch(&simulator, "Switch", 8, 0.5 * kBdp);
37     simulator::SymmetricLink client_link(&client, network_switch.port(1),
38                                          2 * kBandwidth, kDelay);
39     simulator::SymmetricLink server_link(&server, network_switch.port(2),
40                                          kBandwidth, kDelay);
41 
42     QuicTraceVisitor visitor(client.connection());
43     client.connection()->set_debug_visitor(&visitor);
44 
45     // Transfer about a megabyte worth of data from client to server.
46     const QuicTime::Delta kDeadline =
47         3 * kBandwidth.TransferTime(kTransferSize);
48     client.AddBytesToTransfer(kTransferSize);
49     bool simulator_result = simulator.RunUntilOrTimeout(
50         [&]() { return server.bytes_received() >= kTransferSize; }, kDeadline);
51     QUICHE_CHECK(simulator_result);
52 
53     // Save the trace and ensure some loss was observed.
54     trace_.Swap(visitor.trace());
55     QUICHE_CHECK_NE(0u, client.connection()->GetStats().packets_retransmitted);
56     packets_sent_ = client.connection()->GetStats().packets_sent;
57   }
58 
AllEventsWithType(quic_trace::EventType event_type)59   std::vector<quic_trace::Event> AllEventsWithType(
60       quic_trace::EventType event_type) {
61     std::vector<quic_trace::Event> result;
62     for (const auto& event : trace_.events()) {
63       if (event.event_type() == event_type) {
64         result.push_back(event);
65       }
66     }
67     return result;
68   }
69 
70  protected:
71   quic_trace::Trace trace_;
72   QuicPacketCount packets_sent_;
73 };
74 
TEST_F(QuicTraceVisitorTest,ConnectionId)75 TEST_F(QuicTraceVisitorTest, ConnectionId) {
76   char expected_cid[] = {0, 0, 0, 0, 0, 0, 0, 42};
77   EXPECT_EQ(std::string(expected_cid, sizeof(expected_cid)),
78             trace_.destination_connection_id());
79 }
80 
TEST_F(QuicTraceVisitorTest,Version)81 TEST_F(QuicTraceVisitorTest, Version) {
82   std::string version = trace_.protocol_version();
83   ASSERT_EQ(4u, version.size());
84   // Ensure version isn't all-zeroes.
85   EXPECT_TRUE(version[0] != 0 || version[1] != 0 || version[2] != 0 ||
86               version[3] != 0);
87 }
88 
89 // Check that basic metadata about sent packets is recorded.
TEST_F(QuicTraceVisitorTest,SentPacket)90 TEST_F(QuicTraceVisitorTest, SentPacket) {
91   auto sent_packets = AllEventsWithType(quic_trace::PACKET_SENT);
92   EXPECT_EQ(packets_sent_, sent_packets.size());
93   ASSERT_GT(sent_packets.size(), 0u);
94 
95   EXPECT_EQ(sent_packets[0].packet_size(), kDefaultMaxPacketSize);
96   EXPECT_EQ(sent_packets[0].packet_number(), 1u);
97 }
98 
99 // Ensure that every stream frame that was sent is recorded.
TEST_F(QuicTraceVisitorTest,SentStream)100 TEST_F(QuicTraceVisitorTest, SentStream) {
101   auto sent_packets = AllEventsWithType(quic_trace::PACKET_SENT);
102 
103   QuicIntervalSet<QuicStreamOffset> offsets;
104   for (const quic_trace::Event& packet : sent_packets) {
105     for (const quic_trace::Frame& frame : packet.frames()) {
106       if (frame.frame_type() != quic_trace::STREAM) {
107         continue;
108       }
109 
110       const quic_trace::StreamFrameInfo& info = frame.stream_frame_info();
111       if (info.stream_id() != kTestStreamNumber) {
112         continue;
113       }
114 
115       ASSERT_GT(info.length(), 0u);
116       offsets.Add(info.offset(), info.offset() + info.length());
117     }
118   }
119 
120   ASSERT_EQ(1u, offsets.Size());
121   EXPECT_EQ(0u, offsets.begin()->min());
122   EXPECT_EQ(kTransferSize, offsets.rbegin()->max());
123 }
124 
125 // Ensure that all packets are either acknowledged or lost.
TEST_F(QuicTraceVisitorTest,AckPackets)126 TEST_F(QuicTraceVisitorTest, AckPackets) {
127   QuicIntervalSet<QuicPacketNumber> packets;
128   for (const quic_trace::Event& packet : trace_.events()) {
129     if (packet.event_type() == quic_trace::PACKET_RECEIVED) {
130       for (const quic_trace::Frame& frame : packet.frames()) {
131         if (frame.frame_type() != quic_trace::ACK) {
132           continue;
133         }
134 
135         const quic_trace::AckInfo& info = frame.ack_info();
136         for (const auto& block : info.acked_packets()) {
137           packets.Add(QuicPacketNumber(block.first_packet()),
138                       QuicPacketNumber(block.last_packet()) + 1);
139         }
140       }
141     }
142     if (packet.event_type() == quic_trace::PACKET_LOST) {
143       packets.Add(QuicPacketNumber(packet.packet_number()),
144                   QuicPacketNumber(packet.packet_number()) + 1);
145     }
146   }
147 
148   ASSERT_EQ(1u, packets.Size());
149   EXPECT_EQ(QuicPacketNumber(1u), packets.begin()->min());
150   // We leave some room (20 packets) for the packets which did not receive
151   // conclusive status at the end of simulation.
152   EXPECT_GT(packets.rbegin()->max(), QuicPacketNumber(packets_sent_ - 20));
153 }
154 
TEST_F(QuicTraceVisitorTest,TransportState)155 TEST_F(QuicTraceVisitorTest, TransportState) {
156   auto acks = AllEventsWithType(quic_trace::PACKET_RECEIVED);
157   ASSERT_EQ(1, acks[0].frames_size());
158   ASSERT_EQ(quic_trace::ACK, acks[0].frames(0).frame_type());
159 
160   // Check that min-RTT at the end is a reasonable approximation.
161   EXPECT_LE((4 * kDelay).ToMicroseconds() * 1.,
162             acks.rbegin()->transport_state().min_rtt_us());
163   EXPECT_GE((4 * kDelay).ToMicroseconds() * 1.25,
164             acks.rbegin()->transport_state().min_rtt_us());
165 }
166 
TEST_F(QuicTraceVisitorTest,EncryptionLevels)167 TEST_F(QuicTraceVisitorTest, EncryptionLevels) {
168   for (const auto& event : trace_.events()) {
169     switch (event.event_type()) {
170       case quic_trace::PACKET_SENT:
171       case quic_trace::PACKET_RECEIVED:
172       case quic_trace::PACKET_LOST:
173         ASSERT_TRUE(event.has_encryption_level());
174         ASSERT_NE(event.encryption_level(), quic_trace::ENCRYPTION_UNKNOWN);
175         break;
176 
177       default:
178         break;
179     }
180   }
181 }
182 
183 }  // namespace
184 }  // namespace quic::test
185