Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(567)

Side by Side Diff: net/quic/quic_http_stream_test.cc

Issue 11364068: Add a QuicHttpStream class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix bugs Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/quic/quic_http_stream.h"
6
7 #include <vector>
8
9 #include "net/base/net_errors.h"
10 #include "net/base/test_completion_callback.h"
11 #include "net/base/upload_data.h"
12 #include "net/base/upload_data_stream.h"
13 #include "net/http/http_response_headers.h"
14 #include "net/quic/quic_client_session.h"
15 #include "net/quic/quic_connection.h"
16 #include "net/quic/quic_connection_helper.h"
17 #include "net/quic/test_tools/mock_clock.h"
18 #include "net/quic/test_tools/quic_test_utils.h"
19 #include "net/quic/test_tools/test_task_runner.h"
20 #include "net/socket/socket_test_util.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 using testing::_;
25
26 namespace net {
27
28 class QuicConnectionPeer {
29 public:
30 static void SetScheduler(QuicConnection* connection,
31 QuicSendScheduler* scheduler) {
32 connection->scheduler_.reset(scheduler);
33 }
34 };
35
36 namespace test {
37
38 const char kUploadData[] = "hello world!";
39
40 class TestSession : public QuicClientSession {
41 public:
42 virtual QuicCryptoClientStream* GetCryptoStream() {
43 return QuicClientSession::GetCryptoStream();
44 }
45 };
46
47 class TestConnection : public QuicConnection {
48 public:
49 TestConnection(QuicGuid guid,
50 IPEndPoint address,
51 QuicConnectionHelper* helper)
52 : QuicConnection(guid, address, helper) {
53 }
54
55 void SetScheduler(QuicSendScheduler* scheduler) {
56 QuicConnectionPeer::SetScheduler(this, scheduler);
57 }
58 };
59
60 class QuicHttpStreamTest : public ::testing::Test {
61 protected:
62 const static bool kFin = true;
63 const static bool kNoFin = false;
64 // Holds a packet to be written to the wire, and the IO mode that should
65 // be used by the mock socket when performing the write.
66 struct PacketToWrite {
67 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
68 : mode(mode),
69 packet(packet) {
70 }
71 IoMode mode;
72 QuicEncryptedPacket* packet;
73 };
74
75 QuicHttpStreamTest()
76 : net_log_(BoundNetLog()),
77 read_buffer_(new IOBufferWithSize(4096)),
78 guid_(2),
79 framer_(QuicDecrypter::Create(kNULL), QuicEncrypter::Create(kNULL)),
80 creator_(guid_, &framer_) {
81 IPAddressNumber ip;
82 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
83 peer_addr_ = IPEndPoint(ip, 443);
84 self_addr_ = IPEndPoint(ip, 8435);
85 Initialize();
86 }
87
88 ~QuicHttpStreamTest() {
89 for (size_t i = 0; i < writes_.size(); i++) {
90 delete writes_[i].packet;
91 }
92 }
93
94 // Adds a packet to the list of expected writes.
95 void AddWrite(IoMode mode, QuicEncryptedPacket* packet) {
96 writes_.push_back(PacketToWrite(mode, packet));
97 }
98
99 // Returns the packet to be written at position |pos|.
100 QuicEncryptedPacket* GetWrite(size_t pos) {
101 return writes_[pos].packet;
102 }
103
104 bool AtEof() {
105 return socket_data_->at_read_eof() && socket_data_->at_write_eof();
106 }
107
108 void ProcessPacket(const QuicEncryptedPacket& packet) {
109 connection_->ProcessUdpPacket(self_addr_, peer_addr_, packet);
110 }
111
112 // Configures the test fixture to use the list of expected writes.
113 void Initialize() {
114 mock_writes_.reset(new MockWrite[writes_.size()]);
115 for (size_t i = 0; i < writes_.size(); i++) {
116 mock_writes_[i] = MockWrite(writes_[i].mode,
117 writes_[i].packet->data(),
118 writes_[i].packet->length());
119 };
120
121 socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
122 writes_.size()));
123
124 socket_.reset(new MockUDPClientSocket(socket_data_.get(),
125 net_log_.net_log()));
126 socket_->Connect(peer_addr_);
127 runner_ = new TestTaskRunner(&clock_);
128 helper_ = new QuicConnectionHelper(runner_.get(), &clock_, socket_.get());
129 scheduler_ = new MockScheduler();
130 EXPECT_CALL(*scheduler_, TimeUntilSend(_)).
131 WillRepeatedly(testing::Return(QuicTime::Delta()));
132 connection_ = new TestConnection(guid_, peer_addr_, helper_);
133 connection_->set_visitor(&visitor_);
134 connection_->SetScheduler(scheduler_);
135 session_.reset(new QuicClientSession(connection_));
136 CryptoHandshakeMessage message;
137 message.tag = kSHLO;
138 session_->GetCryptoStream()->OnHandshakeMessage(message);
139 EXPECT_TRUE(session_->IsCryptoHandshakeComplete());
140 stream_.reset(new QuicHttpStream(session_->CreateOutgoingReliableStream()));
141 }
142
143 // Returns a newly created packet to send kData on stream 1.
144 QuicEncryptedPacket* ConstructDataPacket(
145 QuicPacketSequenceNumber sequence_number,
146 bool fin,
147 QuicStreamOffset offset,
148 base::StringPiece data) {
149 InitializeHeader(sequence_number);
150 QuicStreamFrame frame(3, fin, offset, data);
151 return ConstructPacket(header_, QuicFrame(&frame));
152 }
153
154 // Returns a newly created packet to send ack data.
155 QuicEncryptedPacket* ConstructAckPacket(
156 QuicPacketSequenceNumber sequence_number,
157 QuicPacketSequenceNumber largest_received,
158 QuicPacketSequenceNumber least_unacked) {
159 InitializeHeader(sequence_number);
160
161 QuicAckFrame ack(largest_received, QuicTime(), least_unacked);
162 ack.congestion_info.type = kFixRate;
163 ack.congestion_info.fix_rate.bitrate_in_bytes_per_second = 100000;
164
165 return ConstructPacket(header_, QuicFrame(&ack));
166 }
167
168 // Returns a newly created packet to send a connection close frame.
169 QuicEncryptedPacket* ConstructClosePacket(
170 QuicPacketSequenceNumber sequence_number,
171 bool with_ack) {
172 InitializeHeader(sequence_number);
173
174 QuicFrames frames;
175 QuicAckFrame ack(0, QuicTime(), 0);
176 if (with_ack) {
177 ack.congestion_info.type = kFixRate;
178 ack.congestion_info.fix_rate.bitrate_in_bytes_per_second = 100000;
179 } else {
180 ack.congestion_info.type = kNone;
181 }
182 QuicConnectionCloseFrame close;
183 close.error_code = QUIC_CONNECTION_TIMED_OUT;
184 close.ack_frame = ack;
185
186 return ConstructPacket(header_, QuicFrame(&close));
187 }
188
189 BoundNetLog net_log_;
190 MockScheduler* scheduler_;
191 scoped_refptr<TestTaskRunner> runner_;
192 QuicConnectionHelper* helper_;
193 scoped_array<MockWrite> mock_writes_;
194 MockClock clock_;
195 TestConnection* connection_;
196 testing::StrictMock<MockConnectionVisitor> visitor_;
197 scoped_ptr<QuicHttpStream> stream_;
198 scoped_ptr<QuicClientSession> session_;
199 TestCompletionCallback callback_;
200 HttpRequestInfo request_;
201 HttpRequestHeaders headers_;
202 HttpResponseInfo response_;
203 scoped_refptr<IOBufferWithSize> read_buffer_;
204
205 private:
206 void InitializeHeader(QuicPacketSequenceNumber sequence_number) {
207 header_.guid = guid_;
208 header_.packet_sequence_number = sequence_number;
209 header_.flags = PACKET_FLAGS_NONE;
210 header_.fec_group = 0;
211 }
212
213 QuicEncryptedPacket* ConstructPacket(const QuicPacketHeader& header,
214 const QuicFrame& frame) {
215 QuicFrames frames;
216 frames.push_back(frame);
217 QuicPacket* packet;
218 framer_.ConstructFrameDataPacket(header_, frames, &packet);
219 QuicEncryptedPacket* encrypted = framer_.EncryptPacket(*packet);
220 delete packet;
221 return encrypted;
222 }
223
224 QuicGuid guid_;
225 QuicFramer framer_;
226 IPEndPoint self_addr_;
227 IPEndPoint peer_addr_;
228 QuicPacketCreator creator_;
229 QuicPacketHeader header_;
230 scoped_ptr<MockUDPClientSocket> socket_;
231 scoped_ptr<StaticSocketDataProvider> socket_data_;
232 std::vector<PacketToWrite> writes_;
233 };
234
235 TEST_F(QuicHttpStreamTest, RenewStreamForAuth) {
236 EXPECT_EQ(NULL, stream_->RenewStreamForAuth());
237 }
238
239 TEST_F(QuicHttpStreamTest, CanFindEndOfResponse) {
240 EXPECT_TRUE(stream_->CanFindEndOfResponse());
241 }
242
243 TEST_F(QuicHttpStreamTest, IsMoreDataBuffered) {
244 EXPECT_FALSE(stream_->IsMoreDataBuffered());
245 }
246
247 TEST_F(QuicHttpStreamTest, IsConnectionReusable) {
248 EXPECT_FALSE(stream_->IsConnectionReusable());
249 }
250
251 TEST_F(QuicHttpStreamTest, GetRequest) {
252 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, kFin, 0,
253 "GET / HTTP/1.1\r\n\r\n"));
254 AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 0));
255 Initialize();
256
257 request_.method = "GET";
258 request_.url = GURL("http://www.google.com/");
259
260 EXPECT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
261 callback_.callback()));
262 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
263 callback_.callback()));
264 EXPECT_EQ(&response_, stream_->GetResponseInfo());
265
266 // Ack the request.
267 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 1, 0));
268 ProcessPacket(*ack);
269
270 EXPECT_EQ(ERR_IO_PENDING,
271 stream_->ReadResponseHeaders(callback_.callback()));
272
273 // Send the response without a body.
274 char kResponseHeaders[] = "HTTP/1.1 404 OK\r\n"
275 "Content-Type: text/plain\r\n\r\n";
276 scoped_ptr<QuicEncryptedPacket> resp(
277 ConstructDataPacket(2, kFin, 0, kResponseHeaders));
278 ProcessPacket(*resp);
279
280 // Now that the headers have been processed, the callback will return.
281 EXPECT_EQ(OK, callback_.WaitForResult());
282 ASSERT_TRUE(response_.headers != NULL);
283 EXPECT_EQ(404, response_.headers->response_code());
284 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
285
286 // There is no body, so this should return immediately.
287 EXPECT_EQ(0, stream_->ReadResponseBody(read_buffer_.get(),
288 read_buffer_->size(),
289 callback_.callback()));
290 EXPECT_TRUE(stream_->IsResponseBodyComplete());
291 EXPECT_TRUE(AtEof());
292 }
293
294 TEST_F(QuicHttpStreamTest, SendPostRequest) {
295 char kRequestData[] = "POST / HTTP/1.1\r\n\r\n";
296 AddWrite(SYNCHRONOUS, ConstructDataPacket(1, false, 0, kRequestData));
297 AddWrite(SYNCHRONOUS, ConstructDataPacket(2, true, strlen(kRequestData),
298 kUploadData));
299 AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 0));
300 AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 3, 0));
301
302 Initialize();
303
304 UploadData* upload_data = new UploadData();
305 upload_data->AppendBytes(kUploadData, strlen(kUploadData));
306 UploadDataStream upload_data_stream(upload_data);
307 request_.method = "POST";
308 request_.url = GURL("http://www.google.com/");
309 request_.upload_data_stream = &upload_data_stream;
310 ASSERT_EQ(OK, request_.upload_data_stream->InitSync());
311
312 EXPECT_EQ(OK, stream_->InitializeStream(&request_, net_log_,
313 callback_.callback()));
314 EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_,
315 callback_.callback()));
316 EXPECT_EQ(&response_, stream_->GetResponseInfo());
317
318 // Ack both packets in the request.
319 scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 2, 1));
320 ProcessPacket(*ack);
321
322 // Send the response headers (but not the body).
323 char kResponseHeaders[] = "HTTP/1.1 200 OK\r\n"
324 "Content-Type: text/plain\r\n\r\n";
325 scoped_ptr<QuicEncryptedPacket> resp(
326 ConstructDataPacket(2, kNoFin, 0, kResponseHeaders));
327 ProcessPacket(*resp);
328
329 // Since the headers have already arrived, this should return immediately.
330 EXPECT_EQ(OK, stream_->ReadResponseHeaders(callback_.callback()));
331 ASSERT_TRUE(response_.headers != NULL);
332 EXPECT_EQ(200, response_.headers->response_code());
333 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
334
335 // Send the response body.
336 char kResponseBody[] = "Hello world!";
337 scoped_ptr<QuicEncryptedPacket> resp_body(
338 ConstructDataPacket(3, kFin, strlen(kResponseHeaders), kResponseBody));
339 ProcessPacket(*resp_body);
340
341 // Since the body has already arrived, this should return immediately.
342 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)),
343 stream_->ReadResponseBody(read_buffer_.get(), read_buffer_->size(),
344 callback_.callback()));
345
346 EXPECT_TRUE(stream_->IsResponseBodyComplete());
347 EXPECT_TRUE(AtEof());
348 }
349
350 } // namespace test
351
352 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698