blob: dcd80bd72ac3ee181335d6c70dac4d4a9e385a5a [file] [log] [blame]
wubf975eac2019-08-19 19:41:01 -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
5#include "net/third_party/quiche/src/quic/qbone/qbone_stream.h"
6
bnc463f2352019-10-10 04:49:34 -07007#include <utility>
8
wubf975eac2019-08-19 19:41:01 -07009#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
10#include "net/third_party/quiche/src/quic/core/quic_session.h"
11#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
12#include "net/third_party/quiche/src/quic/core/quic_utils.h"
wubf975eac2019-08-19 19:41:01 -070013#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_test_loopback.h"
15#include "net/third_party/quiche/src/quic/qbone/qbone_constants.h"
16#include "net/third_party/quiche/src/quic/qbone/qbone_session_base.h"
17#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
18#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
dmcardled70b99e2019-12-12 09:52:39 -080019#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
wubf975eac2019-08-19 19:41:01 -070020#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
21
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.
renjietang7c239172020-02-21 13:50:39 -080043 QuicConsumedData WritevData(QuicStreamId id,
wubf975eac2019-08-19 19:41:01 -070044 size_t write_length,
45 QuicStreamOffset offset,
renjietang7c239172020-02-21 13:50:39 -080046 StreamSendingState state,
47 bool is_retransmission) override {
wubf975eac2019-08-19 19:41:01 -070048 if (!writable_) {
49 return QuicConsumedData(0, false);
50 }
51
52 return QuicConsumedData(write_length, state != StreamSendingState::NO_FIN);
53 }
54
55 QboneReadOnlyStream* CreateIncomingStream(QuicStreamId id) override {
56 return nullptr;
57 }
58
59 const QuicCryptoStream* GetCryptoStream() const override { return nullptr; }
60 QuicCryptoStream* GetMutableCryptoStream() override { return nullptr; }
61
62 // Called by QuicStream when they want to close stream.
63 MOCK_METHOD3(SendRstStream,
64 void(QuicStreamId, QuicRstStreamErrorCode, QuicStreamOffset));
65
66 // Sets whether data is written to buffer, or else if this is write blocked.
67 void set_writable(bool writable) { writable_ = writable; }
68
69 // Tracks whether the stream is write blocked and its priority.
70 void RegisterReliableStream(QuicStreamId stream_id) {
71 // The priority effectively does not matter. Put all streams on the same
72 // priority.
73 write_blocked_streams()->RegisterStream(
74 stream_id,
75 /*is_static_stream=*/false,
76 /* precedence= */ spdy::SpdyStreamPrecedence(3));
77 }
78
79 // The session take ownership of the stream.
80 void ActivateReliableStream(std::unique_ptr<QuicStream> stream) {
81 ActivateStream(std::move(stream));
82 }
83
84 std::unique_ptr<QuicCryptoStream> CreateCryptoStream() override {
85 return nullptr;
86 }
87
dmcardled70b99e2019-12-12 09:52:39 -080088 MOCK_METHOD1(ProcessPacketFromPeer, void(quiche::QuicheStringPiece));
89 MOCK_METHOD1(ProcessPacketFromNetwork, void(quiche::QuicheStringPiece));
wubf975eac2019-08-19 19:41:01 -070090
91 private:
92 // Whether data is written to write_buffer_.
93 bool writable_ = true;
94};
95
96// Packet writer that does nothing. This is required for QuicConnection but
97// isn't used for writing data.
98class DummyPacketWriter : public QuicPacketWriter {
99 public:
100 DummyPacketWriter() {}
101
102 // QuicPacketWriter overrides.
103 WriteResult WritePacket(const char* buffer,
104 size_t buf_len,
105 const QuicIpAddress& self_address,
106 const QuicSocketAddress& peer_address,
107 PerPacketOptions* options) override {
108 return WriteResult(WRITE_STATUS_ERROR, 0);
109 }
110
111 bool IsWriteBlocked() const override { return false; };
112
113 void SetWritable() override {}
114
115 QuicByteCount GetMaxPacketSize(
116 const QuicSocketAddress& peer_address) const override {
117 return 0;
118 }
119
120 bool SupportsReleaseTime() const override { return false; }
121
122 bool IsBatchMode() const override { return false; }
123
124 char* GetNextWriteLocation(const QuicIpAddress& self_address,
125 const QuicSocketAddress& peer_address) override {
126 return nullptr;
127 }
128
129 WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); }
130};
131
132class QboneReadOnlyStreamTest : public ::testing::Test,
133 public QuicConnectionHelperInterface {
134 public:
135 void CreateReliableQuicStream() {
136 // Arbitrary values for QuicConnection.
137 Perspective perspective = Perspective::IS_SERVER;
138 bool owns_writer = true;
139
vasilvv0fc587f2019-09-06 13:33:08 -0700140 alarm_factory_ = std::make_unique<test::MockAlarmFactory>();
wubf975eac2019-08-19 19:41:01 -0700141
142 connection_.reset(new QuicConnection(
143 test::TestConnectionId(0), QuicSocketAddress(TestLoopback(), 0),
144 this /*QuicConnectionHelperInterface*/, alarm_factory_.get(),
145 new DummyPacketWriter(), owns_writer, perspective,
146 ParsedVersionOfIndex(CurrentSupportedVersions(), 0)));
147 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
vasilvv0fc587f2019-09-06 13:33:08 -0700148 session_ = std::make_unique<StrictMock<MockQuicSession>>(connection_.get(),
149 QuicConfig());
wubf975eac2019-08-19 19:41:01 -0700150 stream_ = new QboneReadOnlyStream(kStreamId, session_.get());
151 session_->ActivateReliableStream(
152 std::unique_ptr<QboneReadOnlyStream>(stream_));
153 }
154
155 ~QboneReadOnlyStreamTest() override {}
156
157 const QuicClock* GetClock() const override { return &clock_; }
158
159 QuicRandom* GetRandomGenerator() override {
160 return QuicRandom::GetInstance();
161 }
162
163 QuicBufferAllocator* GetStreamSendBufferAllocator() override {
164 return &buffer_allocator_;
165 }
166
167 protected:
168 // The QuicSession will take the ownership.
169 QboneReadOnlyStream* stream_;
170 std::unique_ptr<StrictMock<MockQuicSession>> session_;
171 std::unique_ptr<QuicAlarmFactory> alarm_factory_;
172 std::unique_ptr<QuicConnection> connection_;
173 // Used to implement the QuicConnectionHelperInterface.
174 SimpleBufferAllocator buffer_allocator_;
175 MockClock clock_;
176 const QuicStreamId kStreamId = QuicUtils::GetFirstUnidirectionalStreamId(
177 CurrentSupportedVersions()[0].transport_version,
178 Perspective::IS_CLIENT);
179};
180
181// Read an entire string.
182TEST_F(QboneReadOnlyStreamTest, ReadDataWhole) {
183 string packet = "Stuff";
184 CreateReliableQuicStream();
185 QuicStreamFrame frame(kStreamId, true, 0, packet);
186 EXPECT_CALL(*session_, ProcessPacketFromPeer("Stuff"));
187 stream_->OnStreamFrame(frame);
188}
189
190// Test buffering.
191TEST_F(QboneReadOnlyStreamTest, ReadBuffered) {
192 CreateReliableQuicStream();
193 string packet = "Stuf";
194 {
195 QuicStreamFrame frame(kStreamId, false, 0, packet);
196 stream_->OnStreamFrame(frame);
197 }
198 // We didn't write 5 bytes yet...
199
200 packet = "f";
201 EXPECT_CALL(*session_, ProcessPacketFromPeer("Stuff"));
202 {
203 QuicStreamFrame frame(kStreamId, true, 4, packet);
204 stream_->OnStreamFrame(frame);
205 }
206}
207
208TEST_F(QboneReadOnlyStreamTest, ReadOutOfOrder) {
209 CreateReliableQuicStream();
210 string packet = "f";
211 {
212 QuicStreamFrame frame(kStreamId, true, 4, packet);
213 stream_->OnStreamFrame(frame);
214 }
215
216 packet = "S";
217 {
218 QuicStreamFrame frame(kStreamId, false, 0, packet);
219 stream_->OnStreamFrame(frame);
220 }
221
222 packet = "tuf";
223 EXPECT_CALL(*session_, ProcessPacketFromPeer("Stuff"));
224 {
225 QuicStreamFrame frame(kStreamId, false, 1, packet);
226 stream_->OnStreamFrame(frame);
227 }
228}
229
230// Test buffering too many bytes.
231TEST_F(QboneReadOnlyStreamTest, ReadBufferedTooLarge) {
232 CreateReliableQuicStream();
233 string packet = "0123456789";
234 int iterations = (QboneConstants::kMaxQbonePacketBytes / packet.size()) + 2;
235 EXPECT_CALL(*session_,
236 SendRstStream(kStreamId, QUIC_BAD_APPLICATION_PAYLOAD, _));
237 for (int i = 0; i < iterations; ++i) {
238 QuicStreamFrame frame(kStreamId, i == (iterations - 1), i * packet.size(),
239 packet);
240 if (!stream_->reading_stopped()) {
241 stream_->OnStreamFrame(frame);
242 }
243 }
244 // We should have nothing written to the network and the stream
245 // should have stopped reading.
246 EXPECT_TRUE(stream_->reading_stopped());
247}
248
249} // namespace
250
251} // namespace quic