blob: 4357bcd74a2f7e2fef085fef54027fedc3fb411b [file] [log] [blame]
mikescarlettcd0e4752016-02-08 17:35:47 -08001/*
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/p2p/quic/reliablequicstream.h"
12
kwiberg3ec46792016-04-27 07:22:53 -070013#include <memory>
mikescarlettcd0e4752016-02-08 17:35:47 -080014#include <string>
15
16#include "net/base/ip_address_number.h"
17#include "net/quic/quic_connection.h"
18#include "net/quic/quic_protocol.h"
19#include "net/quic/quic_session.h"
mikescarlettcd0e4752016-02-08 17:35:47 -080020#include "webrtc/p2p/quic/quicconnectionhelper.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020021#include "webrtc/rtc_base/buffer.h"
22#include "webrtc/rtc_base/gunit.h"
23#include "webrtc/rtc_base/sigslot.h"
24#include "webrtc/rtc_base/stream.h"
mikescarlettcd0e4752016-02-08 17:35:47 -080025
26using cricket::QuicConnectionHelper;
27using cricket::ReliableQuicStream;
28
mikescarlettf5377682016-03-29 12:14:55 -070029using net::IPAddress;
mikescarlettcd0e4752016-02-08 17:35:47 -080030using net::IPEndPoint;
mikescarlettf5377682016-03-29 12:14:55 -070031using net::PerPacketOptions;
mikescarlettcd0e4752016-02-08 17:35:47 -080032using net::Perspective;
33using net::QuicAckListenerInterface;
34using net::QuicConfig;
35using net::QuicConnection;
36using net::QuicConsumedData;
37using net::QuicCryptoStream;
38using net::QuicErrorCode;
39using net::QuicIOVector;
40using net::QuicPacketWriter;
41using net::QuicRstStreamErrorCode;
42using net::QuicSession;
43using net::QuicStreamId;
44using net::QuicStreamOffset;
45using net::SpdyPriority;
46
47using rtc::SR_SUCCESS;
48using rtc::SR_BLOCK;
49
mikescarlettf5377682016-03-29 12:14:55 -070050// Arbitrary number for a stream's write blocked priority.
51static const SpdyPriority kDefaultPriority = 3;
zhihuangf2c2f8f2016-07-13 14:13:49 -070052static const net::QuicStreamId kStreamId = 5;
mikescarlettf5377682016-03-29 12:14:55 -070053
mikescarlettcd0e4752016-02-08 17:35:47 -080054// QuicSession that does not create streams and writes data from
55// ReliableQuicStream to a string.
56class MockQuicSession : public QuicSession {
57 public:
58 MockQuicSession(QuicConnection* connection,
59 const QuicConfig& config,
60 std::string* write_buffer)
61 : QuicSession(connection, config), write_buffer_(write_buffer) {}
62
63 // Writes outgoing data from ReliableQuicStream to a string.
64 QuicConsumedData WritevData(
65 QuicStreamId id,
66 QuicIOVector iovector,
67 QuicStreamOffset offset,
68 bool fin,
mikescarlettcd0e4752016-02-08 17:35:47 -080069 QuicAckListenerInterface* ack_notifier_delegate) override {
70 if (!writable_) {
71 return QuicConsumedData(0, false);
72 }
73
74 const char* data = reinterpret_cast<const char*>(iovector.iov->iov_base);
75 size_t len = iovector.total_length;
76 write_buffer_->append(data, len);
77 return QuicConsumedData(len, false);
78 }
79
80 net::ReliableQuicStream* CreateIncomingDynamicStream(
81 QuicStreamId id) override {
zhihuangf2c2f8f2016-07-13 14:13:49 -070082 return new ReliableQuicStream(kStreamId, this);
mikescarlettcd0e4752016-02-08 17:35:47 -080083 }
84
85 net::ReliableQuicStream* CreateOutgoingDynamicStream(
86 SpdyPriority priority) override {
87 return nullptr;
88 }
89
90 QuicCryptoStream* GetCryptoStream() override { return nullptr; }
91
92 // Called by ReliableQuicStream when they want to close stream.
93 void SendRstStream(QuicStreamId id,
94 QuicRstStreamErrorCode error,
95 QuicStreamOffset bytes_written) override {}
96
97 // Sets whether data is written to buffer, or else if this is write blocked.
98 void set_writable(bool writable) { writable_ = writable; }
99
100 // Tracks whether the stream is write blocked and its priority.
101 void register_write_blocked_stream(QuicStreamId stream_id,
102 SpdyPriority priority) {
103 write_blocked_streams()->RegisterStream(stream_id, priority);
104 }
105
106 private:
107 // Stores written data from ReliableQuicStream.
108 std::string* write_buffer_;
109 // Whether data is written to write_buffer_.
110 bool writable_ = true;
111};
112
113// Packet writer that does nothing. This is required for QuicConnection but
114// isn't used for writing data.
115class DummyPacketWriter : public QuicPacketWriter {
116 public:
117 DummyPacketWriter() {}
118
119 // QuicPacketWriter overrides.
mikescarlett8d37d292016-04-29 15:35:00 -0700120 net::WriteResult WritePacket(const char* buffer,
121 size_t buf_len,
122 const IPAddress& self_address,
123 const IPEndPoint& peer_address,
124 PerPacketOptions* options) override {
mikescarlettcd0e4752016-02-08 17:35:47 -0800125 return net::WriteResult(net::WRITE_STATUS_ERROR, 0);
126 }
127
128 bool IsWriteBlockedDataBuffered() const override { return false; }
129
130 bool IsWriteBlocked() const override { return false; };
131
132 void SetWritable() override {}
133
134 net::QuicByteCount GetMaxPacketSize(
135 const net::IPEndPoint& peer_address) const override {
136 return 0;
137 }
138};
139
mikescarlettcd0e4752016-02-08 17:35:47 -0800140class ReliableQuicStreamTest : public ::testing::Test,
141 public sigslot::has_slots<> {
142 public:
143 ReliableQuicStreamTest() {}
144
145 void CreateReliableQuicStream() {
mikescarlettcd0e4752016-02-08 17:35:47 -0800146
147 // Arbitrary values for QuicConnection.
148 QuicConnectionHelper* quic_helper =
149 new QuicConnectionHelper(rtc::Thread::Current());
150 Perspective perspective = Perspective::IS_SERVER;
mikescarlettf5377682016-03-29 12:14:55 -0700151 net::IPAddress ip(0, 0, 0, 0);
mikescarlettcd0e4752016-02-08 17:35:47 -0800152
mikescarlettf5377682016-03-29 12:14:55 -0700153 bool owns_writer = true;
mikescarlettcd0e4752016-02-08 17:35:47 -0800154
155 QuicConnection* connection = new QuicConnection(
mikescarlettf5377682016-03-29 12:14:55 -0700156 0, IPEndPoint(ip, 0), quic_helper, new DummyPacketWriter(), owns_writer,
157 perspective, net::QuicSupportedVersions());
mikescarlettcd0e4752016-02-08 17:35:47 -0800158
159 session_.reset(
160 new MockQuicSession(connection, QuicConfig(), &write_buffer_));
161 stream_.reset(new ReliableQuicStream(kStreamId, session_.get()));
162 stream_->SignalDataReceived.connect(
163 this, &ReliableQuicStreamTest::OnDataReceived);
164 stream_->SignalClosed.connect(this, &ReliableQuicStreamTest::OnClosed);
mikescarlett18b67a52016-04-11 16:56:23 -0700165 stream_->SignalQueuedBytesWritten.connect(
166 this, &ReliableQuicStreamTest::OnQueuedBytesWritten);
mikescarlettcd0e4752016-02-08 17:35:47 -0800167
mikescarlettf5377682016-03-29 12:14:55 -0700168 session_->register_write_blocked_stream(stream_->id(), kDefaultPriority);
mikescarlettcd0e4752016-02-08 17:35:47 -0800169 }
170
171 void OnDataReceived(QuicStreamId id, const char* data, size_t length) {
172 ASSERT_EQ(id, stream_->id());
173 read_buffer_.append(data, length);
174 }
175
mikescarlett18b67a52016-04-11 16:56:23 -0700176 void OnClosed(QuicStreamId id, int err) { closed_ = true; }
177
178 void OnQueuedBytesWritten(QuicStreamId id, uint64_t queued_bytes_written) {
179 queued_bytes_written_ = queued_bytes_written;
180 }
mikescarlettcd0e4752016-02-08 17:35:47 -0800181
182 protected:
kwiberg3ec46792016-04-27 07:22:53 -0700183 std::unique_ptr<ReliableQuicStream> stream_;
184 std::unique_ptr<MockQuicSession> session_;
mikescarlettcd0e4752016-02-08 17:35:47 -0800185
186 // Data written by the ReliableQuicStream.
187 std::string write_buffer_;
188 // Data read by the ReliableQuicStream.
189 std::string read_buffer_;
190 // Whether the ReliableQuicStream is closed.
191 bool closed_ = false;
mikescarlett18b67a52016-04-11 16:56:23 -0700192 // Bytes written by OnCanWrite().
193 uint64_t queued_bytes_written_;
mikescarlettcd0e4752016-02-08 17:35:47 -0800194};
195
196// Write an entire string.
197TEST_F(ReliableQuicStreamTest, WriteDataWhole) {
198 CreateReliableQuicStream();
199 EXPECT_EQ(SR_SUCCESS, stream_->Write("Foo bar", 7));
200
201 EXPECT_EQ("Foo bar", write_buffer_);
202}
203
204// Write part of a string.
205TEST_F(ReliableQuicStreamTest, WriteDataPartial) {
206 CreateReliableQuicStream();
207 EXPECT_EQ(SR_SUCCESS, stream_->Write("Hello, World!", 8));
208 EXPECT_EQ("Hello, W", write_buffer_);
209}
210
211// Test that strings are buffered correctly.
212TEST_F(ReliableQuicStreamTest, BufferData) {
213 CreateReliableQuicStream();
214
215 session_->set_writable(false);
216 EXPECT_EQ(SR_BLOCK, stream_->Write("Foo bar", 7));
217
218 EXPECT_EQ(0ul, write_buffer_.size());
219 EXPECT_TRUE(stream_->HasBufferedData());
220
221 session_->set_writable(true);
222 stream_->OnCanWrite();
mikescarlett18b67a52016-04-11 16:56:23 -0700223 EXPECT_EQ(7ul, queued_bytes_written_);
mikescarlettcd0e4752016-02-08 17:35:47 -0800224
225 EXPECT_FALSE(stream_->HasBufferedData());
226 EXPECT_EQ("Foo bar", write_buffer_);
227
228 EXPECT_EQ(SR_SUCCESS, stream_->Write("xyzzy", 5));
229 EXPECT_EQ("Foo barxyzzy", write_buffer_);
230}
231
232// Read an entire string.
233TEST_F(ReliableQuicStreamTest, ReadDataWhole) {
234 CreateReliableQuicStream();
zhihuangf2c2f8f2016-07-13 14:13:49 -0700235 net::QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!");
mikescarlettcd0e4752016-02-08 17:35:47 -0800236 stream_->OnStreamFrame(frame);
237
238 EXPECT_EQ("Hello, World!", read_buffer_);
239}
240
241// Read part of a string.
242TEST_F(ReliableQuicStreamTest, ReadDataPartial) {
243 CreateReliableQuicStream();
zhihuangf2c2f8f2016-07-13 14:13:49 -0700244 net::QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!");
mikescarlettcd0e4752016-02-08 17:35:47 -0800245 frame.frame_length = 5;
246 stream_->OnStreamFrame(frame);
247
248 EXPECT_EQ("Hello", read_buffer_);
249}
250
251// Test that closing the stream results in a callback.
252TEST_F(ReliableQuicStreamTest, CloseStream) {
253 CreateReliableQuicStream();
254 EXPECT_FALSE(closed_);
255 stream_->OnClose();
256 EXPECT_TRUE(closed_);
257}