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