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.
5 #include "net/tools/quic/quic_reliable_server_stream.h"
7 #include "base/strings/string_number_conversions.h"
8 #include "net/quic/quic_spdy_compressor.h"
9 #include "net/quic/quic_utils.h"
10 #include "net/quic/test_tools/quic_test_utils.h"
11 #include "net/tools/flip_server/epoll_server.h"
12 #include "net/tools/quic/quic_in_memory_cache.h"
13 #include "net/tools/quic/quic_spdy_server_stream.h"
14 #include "net/tools/quic/spdy_utils.h"
15 #include "net/tools/quic/test_tools/quic_test_utils.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using base::StringPiece
;
20 using net::tools::test::MockConnection
;
21 using net::test::MockSession
;
24 using testing::AnyNumber
;
25 using testing::Invoke
;
26 using testing::InvokeArgument
;
27 using testing::InSequence
;
28 using testing::Return
;
30 using testing::StrictMock
;
31 using testing::WithArgs
;
37 class QuicReliableServerStreamPeer
{
39 static BalsaHeaders
* GetMutableHeaders(
40 QuicReliableServerStream
* stream
) {
41 return &(stream
->headers_
);
47 class QuicReliableServerStreamTest
: public ::testing::Test
{
49 QuicReliableServerStreamTest()
50 : session_(new MockConnection(1, IPEndPoint(), 0, &eps_
, true), true),
51 body_("hello world") {
52 BalsaHeaders request_headers
;
53 request_headers
.SetRequestFirstlineFromStringPieces(
54 "POST", "https://www.google.com/", "HTTP/1.1");
55 request_headers
.ReplaceOrAppendHeader("content-length", "11");
57 headers_string_
= SpdyUtils::SerializeRequestHeaders(request_headers
);
58 stream_
.reset(new QuicSpdyServerStream(3, &session_
));
61 QuicConsumedData
ValidateHeaders(StringPiece headers
) {
62 headers_string_
= SpdyUtils::SerializeResponseHeaders(
64 QuicSpdyDecompressor decompressor
;
65 TestDecompressorVisitor visitor
;
67 // First the header id, then the compressed data.
68 EXPECT_EQ(1, headers
[0]);
69 EXPECT_EQ(0, headers
[1]);
70 EXPECT_EQ(0, headers
[2]);
71 EXPECT_EQ(0, headers
[3]);
72 EXPECT_EQ(static_cast<size_t>(headers
.length() - 4),
73 decompressor
.DecompressData(headers
.substr(4), &visitor
));
75 EXPECT_EQ(headers_string_
, visitor
.data());
77 return QuicConsumedData(headers
.size(), false);
80 static void SetUpTestCase() {
81 QuicInMemoryCache::GetInstance()->ResetForTests();
84 virtual void SetUp() {
85 QuicInMemoryCache
* cache
= QuicInMemoryCache::GetInstance();
87 BalsaHeaders request_headers
, response_headers
;
88 StringPiece
body("Yum");
89 request_headers
.SetRequestFirstlineFromStringPieces(
91 "https://www.google.com/foo",
93 response_headers
.SetRequestFirstlineFromStringPieces("HTTP/1.1",
96 response_headers
.AppendHeader("content-length",
97 base::IntToString(body
.length()));
99 // Check if response already exists and matches.
100 const QuicInMemoryCache::Response
* cached_response
=
101 cache
->GetResponse(request_headers
);
102 if (cached_response
!= NULL
) {
103 string cached_response_headers_str
, response_headers_str
;
104 cached_response
->headers().DumpToString(&cached_response_headers_str
);
105 response_headers
.DumpToString(&response_headers_str
);
106 CHECK_EQ(cached_response_headers_str
, response_headers_str
);
107 CHECK_EQ(cached_response
->body(), body
);
111 cache
->AddResponse(request_headers
, response_headers
, body
);
114 BalsaHeaders response_headers_
;
116 StrictMock
<MockSession
> session_
;
117 scoped_ptr
<QuicReliableServerStream
> stream_
;
118 string headers_string_
;
122 QuicConsumedData
ConsumeAllData(QuicStreamId id
, StringPiece data
,
123 QuicStreamOffset offset
, bool fin
) {
124 return QuicConsumedData(data
.size(), fin
);
127 TEST_F(QuicReliableServerStreamTest
, TestFraming
) {
128 EXPECT_CALL(session_
, WriteData(_
, _
, _
, _
)).Times(AnyNumber()).
129 WillRepeatedly(Invoke(ConsumeAllData
));
131 EXPECT_EQ(headers_string_
.size(), stream_
->ProcessData(
132 headers_string_
.c_str(), headers_string_
.size()));
133 EXPECT_EQ(body_
.size(), stream_
->ProcessData(body_
.c_str(), body_
.size()));
134 EXPECT_EQ(11u, stream_
->headers().content_length());
135 EXPECT_EQ("https://www.google.com/", stream_
->headers().request_uri());
136 EXPECT_EQ("POST", stream_
->headers().request_method());
137 EXPECT_EQ(body_
, stream_
->body());
140 TEST_F(QuicReliableServerStreamTest
, TestFramingOnePacket
) {
141 EXPECT_CALL(session_
, WriteData(_
, _
, _
, _
)).Times(AnyNumber()).
142 WillRepeatedly(Invoke(ConsumeAllData
));
144 string message
= headers_string_
+ body_
;
146 EXPECT_EQ(message
.size(), stream_
->ProcessData(
147 message
.c_str(), message
.size()));
148 EXPECT_EQ(11u, stream_
->headers().content_length());
149 EXPECT_EQ("https://www.google.com/",
150 stream_
->headers().request_uri());
151 EXPECT_EQ("POST", stream_
->headers().request_method());
152 EXPECT_EQ(body_
, stream_
->body());
155 TEST_F(QuicReliableServerStreamTest
, TestFramingExtraData
) {
156 string large_body
= "hello world!!!!!!";
158 // We'll automatically write out an error (headers + body)
159 EXPECT_CALL(session_
, WriteData(_
, _
, _
, _
)).Times(2).
160 WillRepeatedly(Invoke(ConsumeAllData
));
162 EXPECT_EQ(headers_string_
.size(), stream_
->ProcessData(
163 headers_string_
.c_str(), headers_string_
.size()));
164 // Content length is still 11. This will register as an error and we won't
166 stream_
->ProcessData(large_body
.c_str(), large_body
.size());
167 stream_
->TerminateFromPeer(true);
168 EXPECT_EQ(11u, stream_
->headers().content_length());
169 EXPECT_EQ("https://www.google.com/", stream_
->headers().request_uri());
170 EXPECT_EQ("POST", stream_
->headers().request_method());
173 TEST_F(QuicReliableServerStreamTest
, TestSendResponse
) {
174 BalsaHeaders
* request_headers
=
175 QuicReliableServerStreamPeer::GetMutableHeaders(stream_
.get());
176 request_headers
->SetRequestFirstlineFromStringPieces(
178 "https://www.google.com/foo",
181 response_headers_
.SetResponseFirstlineFromStringPieces(
182 "HTTP/1.1", "200", "OK");
183 response_headers_
.ReplaceOrAppendHeader("content-length", "3");
186 EXPECT_CALL(session_
, WriteData(_
, _
, _
, _
)).Times(1)
187 .WillOnce(WithArgs
<1>(Invoke(
188 this, &QuicReliableServerStreamTest::ValidateHeaders
)));
189 StringPiece kBody
= "Yum";
190 EXPECT_CALL(session_
, WriteData(_
, kBody
, _
, _
)).Times(1).
191 WillOnce(Return(QuicConsumedData(3, true)));
193 stream_
->SendResponse();
194 EXPECT_TRUE(stream_
->read_side_closed());
195 EXPECT_TRUE(stream_
->write_side_closed());
198 TEST_F(QuicReliableServerStreamTest
, TestSendErrorResponse
) {
199 response_headers_
.SetResponseFirstlineFromStringPieces(
200 "HTTP/1.1", "500", "Server Error");
201 response_headers_
.ReplaceOrAppendHeader("content-length", "3");
204 EXPECT_CALL(session_
, WriteData(_
, _
, _
, _
)).Times(1)
205 .WillOnce(WithArgs
<1>(Invoke(
206 this, &QuicReliableServerStreamTest::ValidateHeaders
)));
207 StringPiece kBody
= "bad";
208 EXPECT_CALL(session_
, WriteData(_
, kBody
, _
, _
)).Times(1).
209 WillOnce(Return(QuicConsumedData(3, true)));
211 stream_
->SendErrorResponse();
212 EXPECT_TRUE(stream_
->read_side_closed());
213 EXPECT_TRUE(stream_
->write_side_closed());