blob: f9fb5cd7cd63b7cd7eea04c4c2b9e1c8d59ee5a2 [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
13#include <string>
14
15#include "net/base/ip_address_number.h"
16#include "net/quic/quic_connection.h"
17#include "net/quic/quic_protocol.h"
18#include "net/quic/quic_session.h"
19#include "webrtc/base/buffer.h"
20#include "webrtc/base/gunit.h"
21#include "webrtc/base/sigslot.h"
22#include "webrtc/base/stream.h"
23#include "webrtc/p2p/quic/quicconnectionhelper.h"
24
25using cricket::QuicConnectionHelper;
26using cricket::ReliableQuicStream;
27
28using net::FecProtection;
29using net::IPAddressNumber;
30using net::IPEndPoint;
31using net::Perspective;
32using net::QuicAckListenerInterface;
33using net::QuicConfig;
34using net::QuicConnection;
35using net::QuicConsumedData;
36using net::QuicCryptoStream;
37using net::QuicErrorCode;
38using net::QuicIOVector;
39using net::QuicPacketWriter;
40using net::QuicRstStreamErrorCode;
41using net::QuicSession;
42using net::QuicStreamId;
43using net::QuicStreamOffset;
44using net::SpdyPriority;
45
46using rtc::SR_SUCCESS;
47using rtc::SR_BLOCK;
48
49// QuicSession that does not create streams and writes data from
50// ReliableQuicStream to a string.
51class MockQuicSession : public QuicSession {
52 public:
53 MockQuicSession(QuicConnection* connection,
54 const QuicConfig& config,
55 std::string* write_buffer)
56 : QuicSession(connection, config), write_buffer_(write_buffer) {}
57
58 // Writes outgoing data from ReliableQuicStream to a string.
59 QuicConsumedData WritevData(
60 QuicStreamId id,
61 QuicIOVector iovector,
62 QuicStreamOffset offset,
63 bool fin,
64 FecProtection fec_protection,
65 QuicAckListenerInterface* ack_notifier_delegate) override {
66 if (!writable_) {
67 return QuicConsumedData(0, false);
68 }
69
70 const char* data = reinterpret_cast<const char*>(iovector.iov->iov_base);
71 size_t len = iovector.total_length;
72 write_buffer_->append(data, len);
73 return QuicConsumedData(len, false);
74 }
75
76 net::ReliableQuicStream* CreateIncomingDynamicStream(
77 QuicStreamId id) override {
78 return nullptr;
79 }
80
81 net::ReliableQuicStream* CreateOutgoingDynamicStream(
82 SpdyPriority priority) override {
83 return nullptr;
84 }
85
86 QuicCryptoStream* GetCryptoStream() override { return nullptr; }
87
88 // Called by ReliableQuicStream when they want to close stream.
89 void SendRstStream(QuicStreamId id,
90 QuicRstStreamErrorCode error,
91 QuicStreamOffset bytes_written) override {}
92
93 // Sets whether data is written to buffer, or else if this is write blocked.
94 void set_writable(bool writable) { writable_ = writable; }
95
96 // Tracks whether the stream is write blocked and its priority.
97 void register_write_blocked_stream(QuicStreamId stream_id,
98 SpdyPriority priority) {
99 write_blocked_streams()->RegisterStream(stream_id, priority);
100 }
101
102 private:
103 // Stores written data from ReliableQuicStream.
104 std::string* write_buffer_;
105 // Whether data is written to write_buffer_.
106 bool writable_ = true;
107};
108
109// Packet writer that does nothing. This is required for QuicConnection but
110// isn't used for writing data.
111class DummyPacketWriter : public QuicPacketWriter {
112 public:
113 DummyPacketWriter() {}
114
115 // QuicPacketWriter overrides.
116 virtual net::WriteResult WritePacket(const char* buffer,
117 size_t buf_len,
118 const IPAddressNumber& self_address,
119 const IPEndPoint& peer_address) {
120 return net::WriteResult(net::WRITE_STATUS_ERROR, 0);
121 }
122
123 bool IsWriteBlockedDataBuffered() const override { return false; }
124
125 bool IsWriteBlocked() const override { return false; };
126
127 void SetWritable() override {}
128
129 net::QuicByteCount GetMaxPacketSize(
130 const net::IPEndPoint& peer_address) const override {
131 return 0;
132 }
133};
134
135// QuicPacketWriter is not necessary, so this creates a packet writer that
136// doesn't do anything.
137class DummyPacketWriterFactory : public QuicConnection::PacketWriterFactory {
138 public:
139 DummyPacketWriterFactory() {}
140
141 QuicPacketWriter* Create(QuicConnection* connection) const override {
142 return new DummyPacketWriter();
143 }
144};
145
146class ReliableQuicStreamTest : public ::testing::Test,
147 public sigslot::has_slots<> {
148 public:
149 ReliableQuicStreamTest() {}
150
151 void CreateReliableQuicStream() {
152 const net::QuicStreamId kStreamId = 5;
153
154 // Arbitrary values for QuicConnection.
155 QuicConnectionHelper* quic_helper =
156 new QuicConnectionHelper(rtc::Thread::Current());
157 Perspective perspective = Perspective::IS_SERVER;
158 net::IPAddressNumber ip(net::kIPv4AddressSize, 0);
159
160 bool owns_writer = false;
161
162 QuicConnection* connection = new QuicConnection(
163 0, IPEndPoint(ip, 0), quic_helper, DummyPacketWriterFactory(),
164 owns_writer, perspective, net::QuicSupportedVersions());
165
166 session_.reset(
167 new MockQuicSession(connection, QuicConfig(), &write_buffer_));
168 stream_.reset(new ReliableQuicStream(kStreamId, session_.get()));
169 stream_->SignalDataReceived.connect(
170 this, &ReliableQuicStreamTest::OnDataReceived);
171 stream_->SignalClosed.connect(this, &ReliableQuicStreamTest::OnClosed);
172
173 session_->register_write_blocked_stream(stream_->id(), stream_->Priority());
174 }
175
176 void OnDataReceived(QuicStreamId id, const char* data, size_t length) {
177 ASSERT_EQ(id, stream_->id());
178 read_buffer_.append(data, length);
179 }
180
181 void OnClosed(QuicStreamId id, QuicErrorCode err) { closed_ = true; }
182
183 protected:
184 scoped_ptr<ReliableQuicStream> stream_;
185 scoped_ptr<MockQuicSession> session_;
186
187 // Data written by the ReliableQuicStream.
188 std::string write_buffer_;
189 // Data read by the ReliableQuicStream.
190 std::string read_buffer_;
191 // Whether the ReliableQuicStream is closed.
192 bool closed_ = false;
193};
194
195// Write an entire string.
196TEST_F(ReliableQuicStreamTest, WriteDataWhole) {
197 CreateReliableQuicStream();
198 EXPECT_EQ(SR_SUCCESS, stream_->Write("Foo bar", 7));
199
200 EXPECT_EQ("Foo bar", write_buffer_);
201}
202
203// Write part of a string.
204TEST_F(ReliableQuicStreamTest, WriteDataPartial) {
205 CreateReliableQuicStream();
206 EXPECT_EQ(SR_SUCCESS, stream_->Write("Hello, World!", 8));
207 EXPECT_EQ("Hello, W", write_buffer_);
208}
209
210// Test that strings are buffered correctly.
211TEST_F(ReliableQuicStreamTest, BufferData) {
212 CreateReliableQuicStream();
213
214 session_->set_writable(false);
215 EXPECT_EQ(SR_BLOCK, stream_->Write("Foo bar", 7));
216
217 EXPECT_EQ(0ul, write_buffer_.size());
218 EXPECT_TRUE(stream_->HasBufferedData());
219
220 session_->set_writable(true);
221 stream_->OnCanWrite();
222
223 EXPECT_FALSE(stream_->HasBufferedData());
224 EXPECT_EQ("Foo bar", write_buffer_);
225
226 EXPECT_EQ(SR_SUCCESS, stream_->Write("xyzzy", 5));
227 EXPECT_EQ("Foo barxyzzy", write_buffer_);
228}
229
230// Read an entire string.
231TEST_F(ReliableQuicStreamTest, ReadDataWhole) {
232 CreateReliableQuicStream();
233 net::QuicStreamFrame frame(-1, false, 0, "Hello, World!");
234 stream_->OnStreamFrame(frame);
235
236 EXPECT_EQ("Hello, World!", read_buffer_);
237}
238
239// Read part of a string.
240TEST_F(ReliableQuicStreamTest, ReadDataPartial) {
241 CreateReliableQuicStream();
242 net::QuicStreamFrame frame(-1, false, 0, "Hello, World!");
243 frame.frame_length = 5;
244 stream_->OnStreamFrame(frame);
245
246 EXPECT_EQ("Hello", read_buffer_);
247}
248
249// Test that closing the stream results in a callback.
250TEST_F(ReliableQuicStreamTest, CloseStream) {
251 CreateReliableQuicStream();
252 EXPECT_FALSE(closed_);
253 stream_->OnClose();
254 EXPECT_TRUE(closed_);
255}