| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/tools/quic/quic_spdy_server_stream.h" | 5 #include "net/tools/quic/quic_spdy_server_stream.h" |
| 6 | 6 |
| 7 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
| 8 #include "base/strings/string_piece.h" | 8 #include "base/strings/string_piece.h" |
| 9 #include "net/quic/quic_connection.h" | 9 #include "net/quic/quic_connection.h" |
| 10 #include "net/quic/quic_protocol.h" | 10 #include "net/quic/quic_protocol.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 using testing::StrictMock; | 32 using testing::StrictMock; |
| 33 using testing::WithArgs; | 33 using testing::WithArgs; |
| 34 | 34 |
| 35 namespace net { | 35 namespace net { |
| 36 namespace tools { | 36 namespace tools { |
| 37 namespace test { | 37 namespace test { |
| 38 | 38 |
| 39 class QuicSpdyServerStreamPeer : public QuicSpdyServerStream { | 39 class QuicSpdyServerStreamPeer : public QuicSpdyServerStream { |
| 40 public: | 40 public: |
| 41 QuicSpdyServerStreamPeer(QuicStreamId stream_id, QuicSession* session) | 41 QuicSpdyServerStreamPeer(QuicStreamId stream_id, QuicSession* session) |
| 42 : QuicSpdyServerStream(stream_id, session) { | 42 : QuicSpdyServerStream(stream_id, session) {} |
| 43 } | |
| 44 | 43 |
| 45 using QuicSpdyServerStream::SendResponse; | 44 using QuicSpdyServerStream::SendResponse; |
| 46 using QuicSpdyServerStream::SendErrorResponse; | 45 using QuicSpdyServerStream::SendErrorResponse; |
| 47 | 46 |
| 48 BalsaHeaders* mutable_headers() { | 47 BalsaHeaders* mutable_headers() { return &headers_; } |
| 49 return &headers_; | |
| 50 } | |
| 51 | 48 |
| 52 static void SendResponse(QuicSpdyServerStream* stream) { | 49 static void SendResponse(QuicSpdyServerStream* stream) { |
| 53 stream->SendResponse(); | 50 stream->SendResponse(); |
| 54 } | 51 } |
| 55 | 52 |
| 56 static void SendErrorResponse(QuicSpdyServerStream* stream) { | 53 static void SendErrorResponse(QuicSpdyServerStream* stream) { |
| 57 stream->SendResponse(); | 54 stream->SendResponse(); |
| 58 } | 55 } |
| 59 | 56 |
| 60 static const string& body(QuicSpdyServerStream* stream) { | 57 static const string& body(QuicSpdyServerStream* stream) { |
| 61 return stream->body_; | 58 return stream->body_; |
| 62 } | 59 } |
| 63 | 60 |
| 64 static const BalsaHeaders& headers(QuicSpdyServerStream* stream) { | 61 static const BalsaHeaders& headers(QuicSpdyServerStream* stream) { |
| 65 return stream->headers_; | 62 return stream->headers_; |
| 66 } | 63 } |
| 67 }; | 64 }; |
| 68 | 65 |
| 69 namespace { | 66 namespace { |
| 70 | 67 |
| 71 class QuicSpdyServerStreamTest : public ::testing::TestWithParam<QuicVersion> { | 68 class QuicSpdyServerStreamTest : public ::testing::TestWithParam<QuicVersion> { |
| 72 public: | 69 public: |
| 73 QuicSpdyServerStreamTest() | 70 QuicSpdyServerStreamTest() |
| 74 : connection_(new StrictMock<MockConnection>( | 71 : connection_( |
| 75 true, SupportedVersions(GetParam()))), | 72 new StrictMock<MockConnection>(true, |
| 73 SupportedVersions(GetParam()))), |
| 76 session_(connection_), | 74 session_(connection_), |
| 77 body_("hello world") { | 75 body_("hello world") { |
| 78 BalsaHeaders request_headers; | 76 BalsaHeaders request_headers; |
| 79 request_headers.SetRequestFirstlineFromStringPieces( | 77 request_headers.SetRequestFirstlineFromStringPieces( |
| 80 "POST", "https://www.google.com/", "HTTP/1.1"); | 78 "POST", "https://www.google.com/", "HTTP/1.1"); |
| 81 request_headers.ReplaceOrAppendHeader("content-length", "11"); | 79 request_headers.ReplaceOrAppendHeader("content-length", "11"); |
| 82 | 80 |
| 83 headers_string_ = SpdyUtils::SerializeRequestHeaders(request_headers); | 81 headers_string_ = SpdyUtils::SerializeRequestHeaders(request_headers); |
| 84 | 82 |
| 85 // New streams rely on having the peer's flow control receive window | 83 // New streams rely on having the peer's flow control receive window |
| 86 // negotiated in the config. | 84 // negotiated in the config. |
| 87 const uint32 kInitialWindow = 10 * kMaxPacketSize; | 85 const uint32 kInitialWindow = 10 * kMaxPacketSize; |
| 88 session_.config()->SetInitialFlowControlWindowToSend( | 86 session_.config()->SetInitialFlowControlWindowToSend(kInitialWindow); |
| 89 kInitialWindow); | |
| 90 stream_.reset(new QuicSpdyServerStreamPeer(3, &session_)); | 87 stream_.reset(new QuicSpdyServerStreamPeer(3, &session_)); |
| 91 } | 88 } |
| 92 | 89 |
| 93 static void SetUpTestCase() { | 90 static void SetUpTestCase() { QuicInMemoryCachePeer::ResetForTests(); } |
| 94 QuicInMemoryCachePeer::ResetForTests(); | |
| 95 } | |
| 96 | 91 |
| 97 virtual void SetUp() { | 92 virtual void SetUp() { |
| 98 QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance(); | 93 QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance(); |
| 99 | 94 |
| 100 BalsaHeaders request_headers, response_headers; | 95 BalsaHeaders request_headers, response_headers; |
| 101 StringPiece body("Yum"); | 96 StringPiece body("Yum"); |
| 102 request_headers.SetRequestFirstlineFromStringPieces( | 97 request_headers.SetRequestFirstlineFromStringPieces( |
| 103 "GET", | 98 "GET", "https://www.google.com/foo", "HTTP/1.1"); |
| 104 "https://www.google.com/foo", | 99 response_headers.SetRequestFirstlineFromStringPieces( |
| 105 "HTTP/1.1"); | 100 "HTTP/1.1", "200", "OK"); |
| 106 response_headers.SetRequestFirstlineFromStringPieces("HTTP/1.1", | |
| 107 "200", | |
| 108 "OK"); | |
| 109 response_headers.AppendHeader("content-length", | 101 response_headers.AppendHeader("content-length", |
| 110 base::IntToString(body.length())); | 102 base::IntToString(body.length())); |
| 111 | 103 |
| 112 // Check if response already exists and matches. | 104 // Check if response already exists and matches. |
| 113 const QuicInMemoryCache::Response* cached_response = | 105 const QuicInMemoryCache::Response* cached_response = |
| 114 cache->GetResponse(request_headers); | 106 cache->GetResponse(request_headers); |
| 115 if (cached_response != NULL) { | 107 if (cached_response != NULL) { |
| 116 string cached_response_headers_str, response_headers_str; | 108 string cached_response_headers_str, response_headers_str; |
| 117 cached_response->headers().DumpToString(&cached_response_headers_str); | 109 cached_response->headers().DumpToString(&cached_response_headers_str); |
| 118 response_headers.DumpToString(&response_headers_str); | 110 response_headers.DumpToString(&response_headers_str); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 143 | 135 |
| 144 QuicConsumedData ConsumeAllData( | 136 QuicConsumedData ConsumeAllData( |
| 145 QuicStreamId id, | 137 QuicStreamId id, |
| 146 const IOVector& data, | 138 const IOVector& data, |
| 147 QuicStreamOffset offset, | 139 QuicStreamOffset offset, |
| 148 bool fin, | 140 bool fin, |
| 149 QuicAckNotifier::DelegateInterface* /*ack_notifier_delegate*/) { | 141 QuicAckNotifier::DelegateInterface* /*ack_notifier_delegate*/) { |
| 150 return QuicConsumedData(data.TotalBufferSize(), fin); | 142 return QuicConsumedData(data.TotalBufferSize(), fin); |
| 151 } | 143 } |
| 152 | 144 |
| 153 INSTANTIATE_TEST_CASE_P(Tests, QuicSpdyServerStreamTest, | 145 INSTANTIATE_TEST_CASE_P(Tests, |
| 146 QuicSpdyServerStreamTest, |
| 154 ::testing::ValuesIn(QuicSupportedVersions())); | 147 ::testing::ValuesIn(QuicSupportedVersions())); |
| 155 | 148 |
| 156 TEST_P(QuicSpdyServerStreamTest, TestFraming) { | 149 TEST_P(QuicSpdyServerStreamTest, TestFraming) { |
| 157 EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(AnyNumber()). | 150 EXPECT_CALL(session_, WritevData(_, _, _, _, _)) |
| 158 WillRepeatedly(Invoke(ConsumeAllData)); | 151 .Times(AnyNumber()) |
| 152 .WillRepeatedly(Invoke(ConsumeAllData)); |
| 159 | 153 |
| 160 EXPECT_EQ(headers_string_.size(), stream_->ProcessData( | 154 EXPECT_EQ( |
| 161 headers_string_.c_str(), headers_string_.size())); | 155 headers_string_.size(), |
| 156 stream_->ProcessData(headers_string_.c_str(), headers_string_.size())); |
| 162 EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size())); | 157 EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size())); |
| 163 EXPECT_EQ(11u, StreamHeaders().content_length()); | 158 EXPECT_EQ(11u, StreamHeaders().content_length()); |
| 164 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); | 159 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); |
| 165 EXPECT_EQ("POST", StreamHeaders().request_method()); | 160 EXPECT_EQ("POST", StreamHeaders().request_method()); |
| 166 EXPECT_EQ(body_, StreamBody()); | 161 EXPECT_EQ(body_, StreamBody()); |
| 167 } | 162 } |
| 168 | 163 |
| 169 TEST_P(QuicSpdyServerStreamTest, TestFramingOnePacket) { | 164 TEST_P(QuicSpdyServerStreamTest, TestFramingOnePacket) { |
| 170 EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(AnyNumber()). | 165 EXPECT_CALL(session_, WritevData(_, _, _, _, _)) |
| 171 WillRepeatedly(Invoke(ConsumeAllData)); | 166 .Times(AnyNumber()) |
| 167 .WillRepeatedly(Invoke(ConsumeAllData)); |
| 172 | 168 |
| 173 string message = headers_string_ + body_; | 169 string message = headers_string_ + body_; |
| 174 | 170 |
| 175 EXPECT_EQ(message.size(), stream_->ProcessData( | 171 EXPECT_EQ(message.size(), |
| 176 message.c_str(), message.size())); | 172 stream_->ProcessData(message.c_str(), message.size())); |
| 177 EXPECT_EQ(11u, StreamHeaders().content_length()); | 173 EXPECT_EQ(11u, StreamHeaders().content_length()); |
| 178 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); | 174 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); |
| 179 EXPECT_EQ("POST", StreamHeaders().request_method()); | 175 EXPECT_EQ("POST", StreamHeaders().request_method()); |
| 180 EXPECT_EQ(body_, StreamBody()); | 176 EXPECT_EQ(body_, StreamBody()); |
| 181 } | 177 } |
| 182 | 178 |
| 183 TEST_P(QuicSpdyServerStreamTest, TestFramingExtraData) { | 179 TEST_P(QuicSpdyServerStreamTest, TestFramingExtraData) { |
| 184 string large_body = "hello world!!!!!!"; | 180 string large_body = "hello world!!!!!!"; |
| 185 | 181 |
| 186 // We'll automatically write out an error (headers + body) | 182 // We'll automatically write out an error (headers + body) |
| 187 EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(AnyNumber()). | 183 EXPECT_CALL(session_, WritevData(_, _, _, _, _)) |
| 188 WillRepeatedly(Invoke(ConsumeAllData)); | 184 .Times(AnyNumber()) |
| 185 .WillRepeatedly(Invoke(ConsumeAllData)); |
| 189 | 186 |
| 190 EXPECT_EQ(headers_string_.size(), stream_->ProcessData( | 187 EXPECT_EQ( |
| 191 headers_string_.c_str(), headers_string_.size())); | 188 headers_string_.size(), |
| 189 stream_->ProcessData(headers_string_.c_str(), headers_string_.size())); |
| 192 // Content length is still 11. This will register as an error and we won't | 190 // Content length is still 11. This will register as an error and we won't |
| 193 // accept the bytes. | 191 // accept the bytes. |
| 194 stream_->ProcessData(large_body.c_str(), large_body.size()); | 192 stream_->ProcessData(large_body.c_str(), large_body.size()); |
| 195 EXPECT_EQ(11u, StreamHeaders().content_length()); | 193 EXPECT_EQ(11u, StreamHeaders().content_length()); |
| 196 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); | 194 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); |
| 197 EXPECT_EQ("POST", StreamHeaders().request_method()); | 195 EXPECT_EQ("POST", StreamHeaders().request_method()); |
| 198 } | 196 } |
| 199 | 197 |
| 200 TEST_P(QuicSpdyServerStreamTest, TestSendResponse) { | 198 TEST_P(QuicSpdyServerStreamTest, TestSendResponse) { |
| 201 BalsaHeaders* request_headers = stream_->mutable_headers(); | 199 BalsaHeaders* request_headers = stream_->mutable_headers(); |
| 202 request_headers->SetRequestFirstlineFromStringPieces( | 200 request_headers->SetRequestFirstlineFromStringPieces( |
| 203 "GET", | 201 "GET", "https://www.google.com/foo", "HTTP/1.1"); |
| 204 "https://www.google.com/foo", | |
| 205 "HTTP/1.1"); | |
| 206 | 202 |
| 207 response_headers_.SetResponseFirstlineFromStringPieces( | 203 response_headers_.SetResponseFirstlineFromStringPieces( |
| 208 "HTTP/1.1", "200", "OK"); | 204 "HTTP/1.1", "200", "OK"); |
| 209 response_headers_.ReplaceOrAppendHeader("content-length", "3"); | 205 response_headers_.ReplaceOrAppendHeader("content-length", "3"); |
| 210 | 206 |
| 211 InSequence s; | 207 InSequence s; |
| 212 EXPECT_CALL(session_, | 208 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, 0, false, NULL)); |
| 213 WritevData(kHeadersStreamId, _, 0, false, NULL)); | |
| 214 | 209 |
| 215 | 210 EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(1).WillOnce( |
| 216 EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(1). | 211 Return(QuicConsumedData(3, true))); |
| 217 WillOnce(Return(QuicConsumedData(3, true))); | |
| 218 | 212 |
| 219 QuicSpdyServerStreamPeer::SendResponse(stream_.get()); | 213 QuicSpdyServerStreamPeer::SendResponse(stream_.get()); |
| 220 EXPECT_TRUE(stream_->read_side_closed()); | 214 EXPECT_TRUE(stream_->read_side_closed()); |
| 221 EXPECT_TRUE(stream_->write_side_closed()); | 215 EXPECT_TRUE(stream_->write_side_closed()); |
| 222 } | 216 } |
| 223 | 217 |
| 224 TEST_P(QuicSpdyServerStreamTest, TestSendErrorResponse) { | 218 TEST_P(QuicSpdyServerStreamTest, TestSendErrorResponse) { |
| 225 response_headers_.SetResponseFirstlineFromStringPieces( | 219 response_headers_.SetResponseFirstlineFromStringPieces( |
| 226 "HTTP/1.1", "500", "Server Error"); | 220 "HTTP/1.1", "500", "Server Error"); |
| 227 response_headers_.ReplaceOrAppendHeader("content-length", "3"); | 221 response_headers_.ReplaceOrAppendHeader("content-length", "3"); |
| 228 | 222 |
| 229 InSequence s; | 223 InSequence s; |
| 230 EXPECT_CALL(session_, | 224 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, 0, false, NULL)); |
| 231 WritevData(kHeadersStreamId, _, 0, false, NULL)); | |
| 232 | 225 |
| 233 EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(1). | 226 EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(1).WillOnce( |
| 234 WillOnce(Return(QuicConsumedData(3, true))); | 227 Return(QuicConsumedData(3, true))); |
| 235 | 228 |
| 236 QuicSpdyServerStreamPeer::SendErrorResponse(stream_.get()); | 229 QuicSpdyServerStreamPeer::SendErrorResponse(stream_.get()); |
| 237 EXPECT_TRUE(stream_->read_side_closed()); | 230 EXPECT_TRUE(stream_->read_side_closed()); |
| 238 EXPECT_TRUE(stream_->write_side_closed()); | 231 EXPECT_TRUE(stream_->write_side_closed()); |
| 239 } | 232 } |
| 240 | 233 |
| 241 TEST_P(QuicSpdyServerStreamTest, InvalidHeadersWithFin) { | 234 TEST_P(QuicSpdyServerStreamTest, InvalidHeadersWithFin) { |
| 242 char arr[] = { | 235 char arr[] = { |
| 243 0x3a, 0x68, 0x6f, 0x73, // :hos | 236 0x3a, 0x68, 0x6f, 0x73, // :hos |
| 244 0x74, 0x00, 0x00, 0x00, // t... | 237 0x74, 0x00, 0x00, 0x00, // t... |
| 245 0x00, 0x00, 0x00, 0x00, // .... | 238 0x00, 0x00, 0x00, 0x00, // .... |
| 246 0x07, 0x3a, 0x6d, 0x65, // .:me | 239 0x07, 0x3a, 0x6d, 0x65, // .:me |
| 247 0x74, 0x68, 0x6f, 0x64, // thod | 240 0x74, 0x68, 0x6f, 0x64, // thod |
| 248 0x00, 0x00, 0x00, 0x03, // .... | 241 0x00, 0x00, 0x00, 0x03, // .... |
| 249 0x47, 0x45, 0x54, 0x00, // GET. | 242 0x47, 0x45, 0x54, 0x00, // GET. |
| 250 0x00, 0x00, 0x05, 0x3a, // ...: | 243 0x00, 0x00, 0x05, 0x3a, // ...: |
| 251 0x70, 0x61, 0x74, 0x68, // path | 244 0x70, 0x61, 0x74, 0x68, // path |
| 252 0x00, 0x00, 0x00, 0x04, // .... | 245 0x00, 0x00, 0x00, 0x04, // .... |
| 253 0x2f, 0x66, 0x6f, 0x6f, // /foo | 246 0x2f, 0x66, 0x6f, 0x6f, // /foo |
| 254 0x00, 0x00, 0x00, 0x07, // .... | 247 0x00, 0x00, 0x00, 0x07, // .... |
| 255 0x3a, 0x73, 0x63, 0x68, // :sch | 248 0x3a, 0x73, 0x63, 0x68, // :sch |
| 256 0x65, 0x6d, 0x65, 0x00, // eme. | 249 0x65, 0x6d, 0x65, 0x00, // eme. |
| 257 0x00, 0x00, 0x00, 0x00, // .... | 250 0x00, 0x00, 0x00, 0x00, // .... |
| 258 0x00, 0x00, 0x08, 0x3a, // ...: | 251 0x00, 0x00, 0x08, 0x3a, // ...: |
| 259 0x76, 0x65, 0x72, 0x73, // vers | 252 0x76, 0x65, 0x72, 0x73, // vers |
| 260 '\x96', 0x6f, 0x6e, 0x00, // <i(69)>on. | 253 '\x96', 0x6f, 0x6e, 0x00, // <i(69)>on. |
| 261 0x00, 0x00, 0x08, 0x48, // ...H | 254 0x00, 0x00, 0x08, 0x48, // ...H |
| 262 0x54, 0x54, 0x50, 0x2f, // TTP/ | 255 0x54, 0x54, 0x50, 0x2f, // TTP/ |
| 263 0x31, 0x2e, 0x31, // 1.1 | 256 0x31, 0x2e, 0x31, // 1.1 |
| 264 }; | 257 }; |
| 265 StringPiece data(arr, arraysize(arr)); | 258 StringPiece data(arr, arraysize(arr)); |
| 266 QuicStreamFrame frame(stream_->id(), true, 0, MakeIOVector(data)); | 259 QuicStreamFrame frame(stream_->id(), true, 0, MakeIOVector(data)); |
| 267 // Verify that we don't crash when we get a invalid headers in stream frame. | 260 // Verify that we don't crash when we get a invalid headers in stream frame. |
| 268 stream_->OnStreamFrame(frame); | 261 stream_->OnStreamFrame(frame); |
| 269 } | 262 } |
| 270 | 263 |
| 271 } // namespace | 264 } // namespace |
| 272 } // namespace test | 265 } // namespace test |
| 273 } // namespace tools | 266 } // namespace tools |
| 274 } // namespace net | 267 } // namespace net |
| OLD | NEW |