blob: bcbc5a514e89fe9f891589046ebb41852438dc65 [file] [log] [blame]
QUICHE team75854e62020-09-09 14:42:28 -07001// Copyright (c) 2019 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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "quic/qbone/qbone_stream.h"
QUICHE team75854e62020-09-09 14:42:28 -07006
7#include <utility>
8
vasilvv1436e342020-10-09 12:31:16 -07009#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -050010#include "quic/core/crypto/quic_random.h"
11#include "quic/core/quic_session.h"
12#include "quic/core/quic_simple_buffer_allocator.h"
13#include "quic/core/quic_utils.h"
14#include "quic/platform/api/quic_test.h"
15#include "quic/platform/api/quic_test_loopback.h"
16#include "quic/qbone/qbone_constants.h"
17#include "quic/qbone/qbone_session_base.h"
18#include "quic/test_tools/mock_clock.h"
19#include "quic/test_tools/quic_test_utils.h"
20#include "spdy/core/spdy_protocol.h"
QUICHE team75854e62020-09-09 14:42:28 -070021
22namespace quic {
23
24namespace {
25
26using ::testing::_;
27using ::testing::StrictMock;
28
29// MockQuicSession that does not create streams and writes data from
30// QuicStream to a string.
31class MockQuicSession : public QboneSessionBase {
32 public:
33 MockQuicSession(QuicConnection* connection, const QuicConfig& config)
34 : QboneSessionBase(connection,
35 nullptr /*visitor*/,
36 config,
37 CurrentSupportedVersions(),
38 nullptr /*writer*/) {}
39
40 ~MockQuicSession() override {}
41
42 // Writes outgoing data from QuicStream to a string.
vasilvv7df418b2020-10-13 13:47:09 -070043 QuicConsumedData WritevData(QuicStreamId id,
44 size_t write_length,
45 QuicStreamOffset offset,
46 StreamSendingState state,
47 TransmissionType type,
48 absl::optional<EncryptionLevel> level) override {
QUICHE team75854e62020-09-09 14:42:28 -070049 if (!writable_) {
50 return QuicConsumedData(0, false);
51 }
52
53 return QuicConsumedData(write_length, state != StreamSendingState::NO_FIN);
54 }
55
56 QboneReadOnlyStream* CreateIncomingStream(QuicStreamId id) override {
57 return nullptr;
58 }
59
QUICHE team75854e62020-09-09 14:42:28 -070060 // Called by QuicStream when they want to close stream.
61 MOCK_METHOD(void,
renjietang052df7c2020-10-13 14:46:09 -070062 MaybeSendRstStreamFrame,
63 (QuicStreamId stream_id,
64 QuicRstStreamErrorCode error,
65 QuicStreamOffset bytes_written),
66 (override));
67 MOCK_METHOD(void,
68 MaybeSendStopSendingFrame,
69 (QuicStreamId stream_id, QuicRstStreamErrorCode error),
70 (override));
QUICHE team75854e62020-09-09 14:42:28 -070071
72 // Sets whether data is written to buffer, or else if this is write blocked.
73 void set_writable(bool writable) { writable_ = writable; }
74
75 // Tracks whether the stream is write blocked and its priority.
76 void RegisterReliableStream(QuicStreamId stream_id) {
77 // The priority effectively does not matter. Put all streams on the same
78 // priority.
79 write_blocked_streams()->RegisterStream(
80 stream_id,
81 /*is_static_stream=*/false,
82 /* precedence= */ spdy::SpdyStreamPrecedence(3));
83 }
84
85 // The session take ownership of the stream.
86 void ActivateReliableStream(std::unique_ptr<QuicStream> stream) {
87 ActivateStream(std::move(stream));
88 }
89
90 std::unique_ptr<QuicCryptoStream> CreateCryptoStream() override {
renjietang8f166792020-11-09 16:24:06 -080091 return std::make_unique<test::MockQuicCryptoStream>(this);
QUICHE team75854e62020-09-09 14:42:28 -070092 }
93
vasilvv1436e342020-10-09 12:31:16 -070094 MOCK_METHOD(void, ProcessPacketFromPeer, (absl::string_view), (override));
95 MOCK_METHOD(void, ProcessPacketFromNetwork, (absl::string_view), (override));
QUICHE team75854e62020-09-09 14:42:28 -070096
97 private:
98 // Whether data is written to write_buffer_.
99 bool writable_ = true;
100};
101
102// Packet writer that does nothing. This is required for QuicConnection but
103// isn't used for writing data.
104class DummyPacketWriter : public QuicPacketWriter {
105 public:
106 DummyPacketWriter() {}
107
108 // QuicPacketWriter overrides.
109 WriteResult WritePacket(const char* buffer,
110 size_t buf_len,
111 const QuicIpAddress& self_address,
112 const QuicSocketAddress& peer_address,
113 PerPacketOptions* options) override {
114 return WriteResult(WRITE_STATUS_ERROR, 0);
115 }
116
117 bool IsWriteBlocked() const override { return false; };
118
119 void SetWritable() override {}
120
121 QuicByteCount GetMaxPacketSize(
122 const QuicSocketAddress& peer_address) const override {
123 return 0;
124 }
125
126 bool SupportsReleaseTime() const override { return false; }
127
128 bool IsBatchMode() const override { return false; }
129
130 QuicPacketBuffer GetNextWriteLocation(
131 const QuicIpAddress& self_address,
132 const QuicSocketAddress& peer_address) override {
133 return {nullptr, nullptr};
134 }
135
136 WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); }
137};
138
139class QboneReadOnlyStreamTest : public ::testing::Test,
140 public QuicConnectionHelperInterface {
141 public:
142 void CreateReliableQuicStream() {
143 // Arbitrary values for QuicConnection.
144 Perspective perspective = Perspective::IS_SERVER;
145 bool owns_writer = true;
146
147 alarm_factory_ = std::make_unique<test::MockAlarmFactory>();
148
149 connection_.reset(new QuicConnection(
150 test::TestConnectionId(0), QuicSocketAddress(TestLoopback(), 0),
wub5df36632020-10-01 14:42:17 -0700151 QuicSocketAddress(TestLoopback(), 0),
QUICHE team75854e62020-09-09 14:42:28 -0700152 this /*QuicConnectionHelperInterface*/, alarm_factory_.get(),
153 new DummyPacketWriter(), owns_writer, perspective,
154 ParsedVersionOfIndex(CurrentSupportedVersions(), 0)));
155 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
156 session_ = std::make_unique<StrictMock<MockQuicSession>>(connection_.get(),
157 QuicConfig());
renjietang8f166792020-11-09 16:24:06 -0800158 session_->Initialize();
QUICHE team75854e62020-09-09 14:42:28 -0700159 stream_ = new QboneReadOnlyStream(kStreamId, session_.get());
160 session_->ActivateReliableStream(
161 std::unique_ptr<QboneReadOnlyStream>(stream_));
162 }
163
164 ~QboneReadOnlyStreamTest() override {}
165
166 const QuicClock* GetClock() const override { return &clock_; }
167
168 QuicRandom* GetRandomGenerator() override {
169 return QuicRandom::GetInstance();
170 }
171
172 QuicBufferAllocator* GetStreamSendBufferAllocator() override {
173 return &buffer_allocator_;
174 }
175
176 protected:
177 // The QuicSession will take the ownership.
178 QboneReadOnlyStream* stream_;
179 std::unique_ptr<StrictMock<MockQuicSession>> session_;
180 std::unique_ptr<QuicAlarmFactory> alarm_factory_;
181 std::unique_ptr<QuicConnection> connection_;
182 // Used to implement the QuicConnectionHelperInterface.
183 SimpleBufferAllocator buffer_allocator_;
184 MockClock clock_;
185 const QuicStreamId kStreamId = QuicUtils::GetFirstUnidirectionalStreamId(
186 CurrentSupportedVersions()[0].transport_version,
187 Perspective::IS_CLIENT);
188};
189
190// Read an entire string.
191TEST_F(QboneReadOnlyStreamTest, ReadDataWhole) {
192 std::string packet = "Stuff";
193 CreateReliableQuicStream();
194 QuicStreamFrame frame(kStreamId, true, 0, packet);
195 EXPECT_CALL(*session_, ProcessPacketFromPeer("Stuff"));
196 stream_->OnStreamFrame(frame);
197}
198
199// Test buffering.
200TEST_F(QboneReadOnlyStreamTest, ReadBuffered) {
201 CreateReliableQuicStream();
202 std::string packet = "Stuf";
203 {
204 QuicStreamFrame frame(kStreamId, false, 0, packet);
205 stream_->OnStreamFrame(frame);
206 }
207 // We didn't write 5 bytes yet...
208
209 packet = "f";
210 EXPECT_CALL(*session_, ProcessPacketFromPeer("Stuff"));
211 {
212 QuicStreamFrame frame(kStreamId, true, 4, packet);
213 stream_->OnStreamFrame(frame);
214 }
215}
216
217TEST_F(QboneReadOnlyStreamTest, ReadOutOfOrder) {
218 CreateReliableQuicStream();
219 std::string packet = "f";
220 {
221 QuicStreamFrame frame(kStreamId, true, 4, packet);
222 stream_->OnStreamFrame(frame);
223 }
224
225 packet = "S";
226 {
227 QuicStreamFrame frame(kStreamId, false, 0, packet);
228 stream_->OnStreamFrame(frame);
229 }
230
231 packet = "tuf";
232 EXPECT_CALL(*session_, ProcessPacketFromPeer("Stuff"));
233 {
234 QuicStreamFrame frame(kStreamId, false, 1, packet);
235 stream_->OnStreamFrame(frame);
236 }
237}
238
239// Test buffering too many bytes.
240TEST_F(QboneReadOnlyStreamTest, ReadBufferedTooLarge) {
241 CreateReliableQuicStream();
242 std::string packet = "0123456789";
243 int iterations = (QboneConstants::kMaxQbonePacketBytes / packet.size()) + 2;
renjietang861766b2021-02-02 09:59:04 -0800244 EXPECT_CALL(*session_, MaybeSendStopSendingFrame(
245 kStreamId, QUIC_BAD_APPLICATION_PAYLOAD));
246 EXPECT_CALL(*session_, MaybeSendRstStreamFrame(
247 kStreamId, QUIC_BAD_APPLICATION_PAYLOAD, _));
QUICHE team75854e62020-09-09 14:42:28 -0700248 for (int i = 0; i < iterations; ++i) {
249 QuicStreamFrame frame(kStreamId, i == (iterations - 1), i * packet.size(),
250 packet);
251 if (!stream_->reading_stopped()) {
252 stream_->OnStreamFrame(frame);
253 }
254 }
255 // We should have nothing written to the network and the stream
256 // should have stopped reading.
257 EXPECT_TRUE(stream_->reading_stopped());
258}
259
260} // namespace
261
262} // namespace quic