OLD | NEW |
---|---|
(Empty) | |
1 /* | |
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 <string> | |
12 | |
13 #include "webrtc/p2p/quic/reliablequicstream.h" | |
14 | |
15 #include "webrtc/base/buffer.h" | |
16 #include "webrtc/base/gunit.h" | |
17 #include "webrtc/p2p/quic/quicconnectionhelper.h" | |
18 | |
19 #include "net/base/ip_address_number.h" | |
20 #include "net/quic/quic_connection.h" | |
21 #include "net/quic/quic_protocol.h" | |
22 #include "net/quic/quic_session.h" | |
23 | |
24 #include "webrtc/base/sigslot.h" | |
25 #include "webrtc/base/stream.h" | |
Taylor Brandstetter
2016/02/06 00:22:45
nit: include order
mikescarlett
2016/02/06 02:14:09
Done.
| |
26 | |
27 using cricket::QuicConnectionHelper; | |
28 using cricket::ReliableQuicStream; | |
29 | |
30 using net::FecProtection; | |
31 using net::IPAddressNumber; | |
32 using net::IPEndPoint; | |
33 using net::Perspective; | |
34 using net::QuicAckListenerInterface; | |
35 using net::QuicConfig; | |
36 using net::QuicConnection; | |
37 using net::QuicConsumedData; | |
38 using net::QuicCryptoStream; | |
39 using net::QuicErrorCode; | |
40 using net::QuicIOVector; | |
41 using net::QuicPacketWriter; | |
42 using net::QuicRstStreamErrorCode; | |
43 using net::QuicSession; | |
44 using net::QuicStreamId; | |
45 using net::QuicStreamOffset; | |
46 using net::SpdyPriority; | |
47 | |
48 using rtc::SR_SUCCESS; | |
49 using rtc::SR_BLOCK; | |
50 | |
51 // QuicSession that does not create streams and writes data from | |
52 // ReliableQuicStream to a string. | |
53 class MockQuicSession : public QuicSession { | |
54 public: | |
55 MockQuicSession(QuicConnection* connection, | |
56 const QuicConfig& config, | |
57 std::string* write_buffer) | |
58 : QuicSession(connection, config), write_buffer_(write_buffer) {} | |
59 | |
60 ~MockQuicSession() override {} | |
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, | |
68 FecProtection fec_protection, | |
69 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 { | |
82 return nullptr; | |
83 } | |
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. | |
115 class DummyPacketWriter : public QuicPacketWriter { | |
116 public: | |
117 DummyPacketWriter() {} | |
118 ~DummyPacketWriter() override {} | |
119 | |
120 // QuicPacketWriter overrides. | |
121 virtual net::WriteResult WritePacket(const char* buffer, | |
122 size_t buf_len, | |
123 const IPAddressNumber& self_address, | |
124 const IPEndPoint& peer_address) { | |
125 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 | |
140 // QuicPacketWriter is not necessary, so this creates a packet writer that | |
141 // doesn't do anything. | |
142 class DummyPacketWriterFactory : public QuicConnection::PacketWriterFactory { | |
143 public: | |
144 DummyPacketWriterFactory() {} | |
145 ~DummyPacketWriterFactory() override {} | |
146 | |
147 QuicPacketWriter* Create(QuicConnection* connection) const override { | |
148 return new DummyPacketWriter(); | |
149 } | |
150 }; | |
151 | |
152 class ReliableQuicStreamTest : public ::testing::Test, | |
153 public sigslot::has_slots<> { | |
154 public: | |
155 ReliableQuicStreamTest() {} | |
156 | |
157 ~ReliableQuicStreamTest() override {} | |
158 | |
159 void CreateReliableQuicStream() { | |
160 const net::QuicStreamId kStreamId = 5; | |
161 | |
162 // Arbitrary values for QuicConnection | |
163 QuicConnectionHelper* quic_helper = | |
164 new QuicConnectionHelper(rtc::Thread::Current()); | |
165 Perspective perspective = Perspective::IS_SERVER; | |
166 net::IPAddressNumber ip(net::kIPv4AddressSize, 0); | |
167 | |
168 bool owns_writer = false; | |
Taylor Brandstetter
2016/02/06 00:22:45
If the only purpose of this variable is to give a
mikescarlett
2016/02/06 02:14:09
I had it like that previously until Peter said the
pthatcher1
2016/02/08 19:19:59
In Java code we tend to do /* like this */. In C+
| |
169 | |
170 QuicConnection* connection = new QuicConnection( | |
171 0, IPEndPoint(ip, 0), quic_helper, DummyPacketWriterFactory(), | |
172 owns_writer, perspective, net::QuicSupportedVersions()); | |
173 | |
174 session_.reset( | |
175 new MockQuicSession(connection, QuicConfig(), &write_buffer_)); | |
176 stream_.reset(new ReliableQuicStream(kStreamId, session_.get())); | |
177 stream_->SignalDataReceived.connect( | |
178 this, &ReliableQuicStreamTest::OnDataReceived); | |
179 stream_->SignalClosed.connect(this, &ReliableQuicStreamTest::OnClosed); | |
180 | |
181 session_->register_write_blocked_stream(stream_->id(), stream_->Priority()); | |
182 } | |
183 | |
184 void OnDataReceived(QuicStreamId id, const char* data, size_t length) { | |
185 ASSERT_EQ(id, stream_->id()); | |
186 read_buffer_.append(data, length); | |
187 } | |
188 | |
189 void OnClosed(QuicStreamId id, QuicErrorCode err) { closed_ = true; } | |
190 | |
191 protected: | |
192 scoped_ptr<ReliableQuicStream> stream_; | |
193 scoped_ptr<MockQuicSession> session_; | |
194 | |
195 // Data written by the ReliableQuicStream | |
196 std::string write_buffer_ = ""; | |
197 // Data read by the ReliableQuicStream | |
198 std::string read_buffer_ = ""; | |
199 // Whether the ReliableQuicStream is closed | |
200 bool closed_ = false; | |
201 }; | |
202 | |
203 // Write an entire string. | |
204 TEST_F(ReliableQuicStreamTest, WriteDataWhole) { | |
205 CreateReliableQuicStream(); | |
206 EXPECT_EQ(SR_SUCCESS, stream_->Write("Foo bar", 7)); | |
207 | |
208 EXPECT_EQ("Foo bar", write_buffer_); | |
209 } | |
210 | |
211 // Write part of a string | |
212 TEST_F(ReliableQuicStreamTest, WriteDataPartial) { | |
213 CreateReliableQuicStream(); | |
214 EXPECT_EQ(SR_SUCCESS, stream_->Write("Hello, World!", 8)); | |
215 EXPECT_EQ("Hello, W", write_buffer_); | |
216 } | |
217 | |
218 // Test that strings are buffered correctly. | |
219 TEST_F(ReliableQuicStreamTest, BufferData) { | |
220 CreateReliableQuicStream(); | |
221 | |
222 session_->set_writable(false); | |
223 EXPECT_EQ(SR_BLOCK, stream_->Write("Foo bar", 7)); | |
224 | |
225 EXPECT_EQ(0ul, write_buffer_.size()); | |
226 EXPECT_TRUE(stream_->HasBufferedData()); | |
227 | |
228 session_->set_writable(true); | |
229 stream_->OnCanWrite(); | |
230 | |
231 EXPECT_FALSE(stream_->HasBufferedData()); | |
232 EXPECT_EQ("Foo bar", write_buffer_); | |
233 | |
234 EXPECT_EQ(SR_SUCCESS, stream_->Write("xyzzy", 5)); | |
235 EXPECT_EQ("Foo barxyzzy", write_buffer_); | |
236 } | |
237 | |
238 // Read an entire string. | |
239 TEST_F(ReliableQuicStreamTest, ReadDataWhole) { | |
240 CreateReliableQuicStream(); | |
241 net::QuicStreamFrame frame(-1, false, 0, "Hello, World!"); | |
242 stream_->OnStreamFrame(frame); | |
243 | |
244 EXPECT_EQ("Hello, World!", read_buffer_); | |
245 } | |
246 | |
247 // Read part of a string. | |
248 TEST_F(ReliableQuicStreamTest, ReadDataPartial) { | |
249 CreateReliableQuicStream(); | |
250 net::QuicStreamFrame frame(-1, false, 0, "Hello, World!"); | |
251 frame.frame_length = 5; | |
252 stream_->OnStreamFrame(frame); | |
253 | |
254 EXPECT_EQ("Hello", read_buffer_); | |
255 } | |
256 | |
257 // Test that closing the stream results in a callback. | |
258 TEST_F(ReliableQuicStreamTest, CloseStream) { | |
259 CreateReliableQuicStream(); | |
260 EXPECT_FALSE(closed_); | |
261 stream_->OnClose(); | |
262 EXPECT_TRUE(closed_); | |
263 } | |
OLD | NEW |