blob: cf9f5e92ddfb06507e242706700d6fbf91d109f8 [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"
20#include "webrtc/base/buffer.h"
21#include "webrtc/base/gunit.h"
22#include "webrtc/base/sigslot.h"
23#include "webrtc/base/stream.h"
24#include "webrtc/p2p/quic/quicconnectionhelper.h"
25
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;
52
mikescarlettcd0e4752016-02-08 17:35:47 -080053// QuicSession that does not create streams and writes data from
54// ReliableQuicStream to a string.
55class MockQuicSession : public QuicSession {
56 public:
57 MockQuicSession(QuicConnection* connection,
58 const QuicConfig& config,
59 std::string* write_buffer)
60 : QuicSession(connection, config), write_buffer_(write_buffer) {}
61
62 // Writes outgoing data from ReliableQuicStream to a string.
63 QuicConsumedData WritevData(
64 QuicStreamId id,
65 QuicIOVector iovector,
66 QuicStreamOffset offset,
67 bool fin,
mikescarlettcd0e4752016-02-08 17:35:47 -080068 QuicAckListenerInterface* ack_notifier_delegate) override {
69 if (!writable_) {
70 return QuicConsumedData(0, false);
71 }
72
73 const char* data = reinterpret_cast<const char*>(iovector.iov->iov_base);
74 size_t len = iovector.total_length;
75 write_buffer_->append(data, len);
76 return QuicConsumedData(len, false);
77 }
78
79 net::ReliableQuicStream* CreateIncomingDynamicStream(
80 QuicStreamId id) override {
deadbeefa2cd6362016-07-13 13:57:32 -070081 return nullptr;
mikescarlettcd0e4752016-02-08 17:35:47 -080082 }
83
84 net::ReliableQuicStream* CreateOutgoingDynamicStream(
85 SpdyPriority priority) override {
86 return nullptr;
87 }
88
89 QuicCryptoStream* GetCryptoStream() override { return nullptr; }
90
91 // Called by ReliableQuicStream when they want to close stream.
92 void SendRstStream(QuicStreamId id,
93 QuicRstStreamErrorCode error,
94 QuicStreamOffset bytes_written) override {}
95
96 // Sets whether data is written to buffer, or else if this is write blocked.
97 void set_writable(bool writable) { writable_ = writable; }
98
99 // Tracks whether the stream is write blocked and its priority.
100 void register_write_blocked_stream(QuicStreamId stream_id,
101 SpdyPriority priority) {
102 write_blocked_streams()->RegisterStream(stream_id, priority);
103 }
104
105 private:
106 // Stores written data from ReliableQuicStream.
107 std::string* write_buffer_;
108 // Whether data is written to write_buffer_.
109 bool writable_ = true;
110};
111
112// Packet writer that does nothing. This is required for QuicConnection but
113// isn't used for writing data.
114class DummyPacketWriter : public QuicPacketWriter {
115 public:
116 DummyPacketWriter() {}
117
118 // QuicPacketWriter overrides.
mikescarlett8d37d292016-04-29 15:35:00 -0700119 net::WriteResult WritePacket(const char* buffer,
120 size_t buf_len,
121 const IPAddress& self_address,
122 const IPEndPoint& peer_address,
123 PerPacketOptions* options) override {
mikescarlettcd0e4752016-02-08 17:35:47 -0800124 return net::WriteResult(net::WRITE_STATUS_ERROR, 0);
125 }
126
127 bool IsWriteBlockedDataBuffered() const override { return false; }
128
129 bool IsWriteBlocked() const override { return false; };
130
131 void SetWritable() override {}
132
133 net::QuicByteCount GetMaxPacketSize(
134 const net::IPEndPoint& peer_address) const override {
135 return 0;
136 }
137};
138
mikescarlettcd0e4752016-02-08 17:35:47 -0800139class ReliableQuicStreamTest : public ::testing::Test,
140 public sigslot::has_slots<> {
141 public:
142 ReliableQuicStreamTest() {}
143
144 void CreateReliableQuicStream() {
deadbeefa2cd6362016-07-13 13:57:32 -0700145 const net::QuicStreamId kStreamId = 5;
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();
deadbeefa2cd6362016-07-13 13:57:32 -0700235 net::QuicStreamFrame frame(-1, 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();
deadbeefa2cd6362016-07-13 13:57:32 -0700244 net::QuicStreamFrame frame(-1, 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}