| 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 28 matching lines...) Expand all Loading... |
| 39 | 39 |
| 40 class QuicSpdyServerStreamPeer : public QuicSpdyServerStream { | 40 class QuicSpdyServerStreamPeer : public QuicSpdyServerStream { |
| 41 public: | 41 public: |
| 42 QuicSpdyServerStreamPeer(QuicStreamId stream_id, QuicSession* session) | 42 QuicSpdyServerStreamPeer(QuicStreamId stream_id, QuicSession* session) |
| 43 : QuicSpdyServerStream(stream_id, session) { | 43 : QuicSpdyServerStream(stream_id, session) { |
| 44 } | 44 } |
| 45 | 45 |
| 46 using QuicSpdyServerStream::SendResponse; | 46 using QuicSpdyServerStream::SendResponse; |
| 47 using QuicSpdyServerStream::SendErrorResponse; | 47 using QuicSpdyServerStream::SendErrorResponse; |
| 48 | 48 |
| 49 BalsaHeaders* mutable_headers() { | 49 SpdyHeaderBlock* mutable_headers() { |
| 50 return &headers_; | 50 return &request_headers_; |
| 51 } | 51 } |
| 52 | 52 |
| 53 static void SendResponse(QuicSpdyServerStream* stream) { | 53 static void SendResponse(QuicSpdyServerStream* stream) { |
| 54 stream->SendResponse(); | 54 stream->SendResponse(); |
| 55 } | 55 } |
| 56 | 56 |
| 57 static void SendErrorResponse(QuicSpdyServerStream* stream) { | 57 static void SendErrorResponse(QuicSpdyServerStream* stream) { |
| 58 stream->SendResponse(); | 58 stream->SendResponse(); |
| 59 } | 59 } |
| 60 | 60 |
| 61 static const string& body(QuicSpdyServerStream* stream) { | 61 static const string& body(QuicSpdyServerStream* stream) { |
| 62 return stream->body_; | 62 return stream->body_; |
| 63 } | 63 } |
| 64 | 64 |
| 65 static const BalsaHeaders& headers(QuicSpdyServerStream* stream) { | 65 static const SpdyHeaderBlock& headers(QuicSpdyServerStream* stream) { |
| 66 return stream->headers_; | 66 return stream->request_headers_; |
| 67 } | 67 } |
| 68 }; | 68 }; |
| 69 | 69 |
| 70 namespace { | 70 namespace { |
| 71 | 71 |
| 72 class QuicSpdyServerStreamTest : public ::testing::TestWithParam<QuicVersion> { | 72 class QuicSpdyServerStreamTest : public ::testing::TestWithParam<QuicVersion> { |
| 73 public: | 73 public: |
| 74 QuicSpdyServerStreamTest() | 74 QuicSpdyServerStreamTest() |
| 75 : connection_( | 75 : connection_( |
| 76 new StrictMock<MockConnection>(Perspective::IS_SERVER, | 76 new StrictMock<MockConnection>(Perspective::IS_SERVER, |
| 77 SupportedVersions(GetParam()))), | 77 SupportedVersions(GetParam()))), |
| 78 session_(connection_), | 78 session_(connection_), |
| 79 body_("hello world") { | 79 body_("hello world") { |
| 80 BalsaHeaders request_headers; | 80 SpdyHeaderBlock request_headers; |
| 81 request_headers.SetRequestFirstlineFromStringPieces( | 81 request_headers[":host"] = ""; |
| 82 "POST", "https://www.google.com/", "HTTP/1.1"); | 82 request_headers[":path"] = "/"; |
| 83 request_headers.ReplaceOrAppendHeader("content-length", "11"); | 83 request_headers[":method"] = "POST"; |
| 84 request_headers[":version"] = "HTTP/1.1"; |
| 85 request_headers["content-length"] = "11"; |
| 84 | 86 |
| 85 headers_string_ = SpdyUtils::SerializeRequestHeaders(request_headers); | 87 headers_string_ = SpdyUtils::SerializeUncompressedHeaders(request_headers); |
| 86 | 88 |
| 87 // New streams rely on having the peer's flow control receive window | 89 // New streams rely on having the peer's flow control receive window |
| 88 // negotiated in the config. | 90 // negotiated in the config. |
| 89 session_.config()->SetInitialStreamFlowControlWindowToSend( | 91 session_.config()->SetInitialStreamFlowControlWindowToSend( |
| 90 kInitialStreamFlowControlWindowForTest); | 92 kInitialStreamFlowControlWindowForTest); |
| 91 session_.config()->SetInitialSessionFlowControlWindowToSend( | 93 session_.config()->SetInitialSessionFlowControlWindowToSend( |
| 92 kInitialSessionFlowControlWindowForTest); | 94 kInitialSessionFlowControlWindowForTest); |
| 93 stream_.reset(new QuicSpdyServerStreamPeer(3, &session_)); | 95 stream_.reset(new QuicSpdyServerStreamPeer(3, &session_)); |
| 94 | 96 |
| 95 QuicInMemoryCachePeer::ResetForTests(); | 97 QuicInMemoryCachePeer::ResetForTests(); |
| 98 |
| 96 string host = ""; | 99 string host = ""; |
| 97 string path = "/foo"; | 100 string path = "/foo"; |
| 98 SpdyHeaderBlock response_headers; | 101 SpdyHeaderBlock response_headers; |
| 99 StringPiece body("Yum"); | 102 StringPiece body("Yum"); |
| 100 QuicInMemoryCache::GetInstance()->AddResponse(host, path, response_headers, | 103 QuicInMemoryCache::GetInstance()->AddResponse(host, path, response_headers, |
| 101 body); | 104 body); |
| 102 } | 105 } |
| 103 | 106 |
| 104 ~QuicSpdyServerStreamTest() override { | 107 ~QuicSpdyServerStreamTest() override { |
| 105 QuicInMemoryCachePeer::ResetForTests(); | 108 QuicInMemoryCachePeer::ResetForTests(); |
| 106 } | 109 } |
| 107 | 110 |
| 108 const string& StreamBody() { | 111 const string& StreamBody() { |
| 109 return QuicSpdyServerStreamPeer::body(stream_.get()); | 112 return QuicSpdyServerStreamPeer::body(stream_.get()); |
| 110 } | 113 } |
| 111 | 114 |
| 112 const BalsaHeaders& StreamHeaders() { | 115 const string& StreamHeadersValue(const string& key) { |
| 113 return QuicSpdyServerStreamPeer::headers(stream_.get()); | 116 return (*stream_->mutable_headers())[key]; |
| 114 } | 117 } |
| 115 | 118 |
| 116 BalsaHeaders response_headers_; | 119 SpdyHeaderBlock response_headers_; |
| 117 EpollServer eps_; | 120 EpollServer eps_; |
| 118 StrictMock<MockConnection>* connection_; | 121 StrictMock<MockConnection>* connection_; |
| 119 StrictMock<MockSession> session_; | 122 StrictMock<MockSession> session_; |
| 120 scoped_ptr<QuicSpdyServerStreamPeer> stream_; | 123 scoped_ptr<QuicSpdyServerStreamPeer> stream_; |
| 121 string headers_string_; | 124 string headers_string_; |
| 122 string body_; | 125 string body_; |
| 123 }; | 126 }; |
| 124 | 127 |
| 125 QuicConsumedData ConsumeAllData( | 128 QuicConsumedData ConsumeAllData( |
| 126 QuicStreamId id, | 129 QuicStreamId id, |
| 127 const IOVector& data, | 130 const IOVector& data, |
| 128 QuicStreamOffset offset, | 131 QuicStreamOffset offset, |
| 129 bool fin, | 132 bool fin, |
| 130 FecProtection /*fec_protection_*/, | 133 FecProtection /*fec_protection_*/, |
| 131 QuicAckNotifier::DelegateInterface* /*ack_notifier_delegate*/) { | 134 QuicAckNotifier::DelegateInterface* /*ack_notifier_delegate*/) { |
| 132 return QuicConsumedData(data.TotalBufferSize(), fin); | 135 return QuicConsumedData(data.TotalBufferSize(), fin); |
| 133 } | 136 } |
| 134 | 137 |
| 135 INSTANTIATE_TEST_CASE_P(Tests, QuicSpdyServerStreamTest, | 138 INSTANTIATE_TEST_CASE_P(Tests, QuicSpdyServerStreamTest, |
| 136 ::testing::ValuesIn(QuicSupportedVersions())); | 139 ::testing::ValuesIn(QuicSupportedVersions())); |
| 137 | 140 |
| 138 TEST_P(QuicSpdyServerStreamTest, TestFraming) { | 141 TEST_P(QuicSpdyServerStreamTest, TestFraming) { |
| 139 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). | 142 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). |
| 140 WillRepeatedly(Invoke(ConsumeAllData)); | 143 WillRepeatedly(Invoke(ConsumeAllData)); |
| 141 | 144 stream_->OnStreamHeaders(headers_string_); |
| 142 EXPECT_EQ(headers_string_.size(), stream_->ProcessData( | 145 stream_->OnStreamHeadersComplete(false, headers_string_.size()); |
| 143 headers_string_.c_str(), headers_string_.size())); | |
| 144 EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size())); | 146 EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size())); |
| 145 EXPECT_EQ(11u, StreamHeaders().content_length()); | 147 EXPECT_EQ("11", StreamHeadersValue("content-length")); |
| 146 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); | 148 EXPECT_EQ("/", StreamHeadersValue(":path")); |
| 147 EXPECT_EQ("POST", StreamHeaders().request_method()); | 149 EXPECT_EQ("POST", StreamHeadersValue(":method")); |
| 148 EXPECT_EQ(body_, StreamBody()); | 150 EXPECT_EQ(body_, StreamBody()); |
| 149 } | 151 } |
| 150 | 152 |
| 151 TEST_P(QuicSpdyServerStreamTest, TestFramingOnePacket) { | 153 TEST_P(QuicSpdyServerStreamTest, TestFramingOnePacket) { |
| 152 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). | 154 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). |
| 153 WillRepeatedly(Invoke(ConsumeAllData)); | 155 WillRepeatedly(Invoke(ConsumeAllData)); |
| 154 | 156 |
| 155 string message = headers_string_ + body_; | 157 stream_->OnStreamHeaders(headers_string_); |
| 156 | 158 stream_->OnStreamHeadersComplete(false, headers_string_.size()); |
| 157 EXPECT_EQ(message.size(), stream_->ProcessData( | 159 EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size())); |
| 158 message.c_str(), message.size())); | 160 EXPECT_EQ("11", StreamHeadersValue("content-length")); |
| 159 EXPECT_EQ(11u, StreamHeaders().content_length()); | 161 EXPECT_EQ("/", StreamHeadersValue(":path")); |
| 160 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); | 162 EXPECT_EQ("POST", StreamHeadersValue(":method")); |
| 161 EXPECT_EQ("POST", StreamHeaders().request_method()); | |
| 162 EXPECT_EQ(body_, StreamBody()); | 163 EXPECT_EQ(body_, StreamBody()); |
| 163 } | 164 } |
| 164 | 165 |
| 165 TEST_P(QuicSpdyServerStreamTest, TestFramingExtraData) { | 166 TEST_P(QuicSpdyServerStreamTest, TestFramingExtraData) { |
| 166 string large_body = "hello world!!!!!!"; | 167 string large_body = "hello world!!!!!!"; |
| 167 | 168 |
| 168 // We'll automatically write out an error (headers + body) | 169 // We'll automatically write out an error (headers + body) |
| 169 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). | 170 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). |
| 170 WillRepeatedly(Invoke(ConsumeAllData)); | 171 WillRepeatedly(Invoke(ConsumeAllData)); |
| 171 | 172 |
| 172 EXPECT_EQ(headers_string_.size(), stream_->ProcessData( | 173 stream_->OnStreamHeaders(headers_string_); |
| 173 headers_string_.c_str(), headers_string_.size())); | 174 stream_->OnStreamHeadersComplete(false, headers_string_.size()); |
| 175 EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size())); |
| 174 // Content length is still 11. This will register as an error and we won't | 176 // Content length is still 11. This will register as an error and we won't |
| 175 // accept the bytes. | 177 // accept the bytes. |
| 176 stream_->ProcessData(large_body.c_str(), large_body.size()); | 178 stream_->ProcessData(large_body.c_str(), large_body.size()); |
| 177 EXPECT_EQ(11u, StreamHeaders().content_length()); | 179 EXPECT_EQ("11", StreamHeadersValue("content-length")); |
| 178 EXPECT_EQ("https://www.google.com/", StreamHeaders().request_uri()); | 180 EXPECT_EQ("/", StreamHeadersValue(":path")); |
| 179 EXPECT_EQ("POST", StreamHeaders().request_method()); | 181 EXPECT_EQ("POST", StreamHeadersValue(":method")); |
| 180 } | 182 } |
| 181 | 183 |
| 182 TEST_P(QuicSpdyServerStreamTest, TestSendResponse) { | 184 TEST_P(QuicSpdyServerStreamTest, TestSendResponse) { |
| 183 BalsaHeaders* request_headers = stream_->mutable_headers(); | 185 SpdyHeaderBlock* request_headers = stream_->mutable_headers(); |
| 184 request_headers->SetRequestFirstlineFromStringPieces( | 186 (*request_headers)[":path"] = "/foo"; |
| 185 "GET", | 187 (*request_headers)[":host"] = ""; |
| 186 "https://www.google.com/foo", | 188 (*request_headers)[":version"] = "HTTP/1.1"; |
| 187 "HTTP/1.1"); | 189 (*request_headers)[":method"] = "GET"; |
| 188 | 190 |
| 189 response_headers_.SetResponseFirstlineFromStringPieces( | 191 response_headers_[":version"] = "HTTP/1.1"; |
| 190 "HTTP/1.1", "200", "OK"); | 192 response_headers_[":status"] = "200 OK"; |
| 191 response_headers_.ReplaceOrAppendHeader("content-length", "3"); | 193 response_headers_["content-length"] = "3"; |
| 192 | 194 |
| 193 InSequence s; | 195 InSequence s; |
| 194 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, 0, false, _, nullptr)); | 196 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, 0, false, _, nullptr)); |
| 195 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(1). | 197 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(1). |
| 196 WillOnce(Return(QuicConsumedData(3, true))); | 198 WillOnce(Return(QuicConsumedData(3, true))); |
| 197 | 199 |
| 198 QuicSpdyServerStreamPeer::SendResponse(stream_.get()); | 200 QuicSpdyServerStreamPeer::SendResponse(stream_.get()); |
| 199 EXPECT_TRUE(stream_->read_side_closed()); | 201 EXPECT_TRUE(stream_->read_side_closed()); |
| 200 EXPECT_TRUE(stream_->write_side_closed()); | 202 EXPECT_TRUE(stream_->write_side_closed()); |
| 201 } | 203 } |
| 202 | 204 |
| 203 TEST_P(QuicSpdyServerStreamTest, TestSendErrorResponse) { | 205 TEST_P(QuicSpdyServerStreamTest, TestSendErrorResponse) { |
| 204 response_headers_.SetResponseFirstlineFromStringPieces( | 206 response_headers_[":version"] = "HTTP/1.1"; |
| 205 "HTTP/1.1", "500", "Server Error"); | 207 response_headers_[":status"] = "500 Server Error"; |
| 206 response_headers_.ReplaceOrAppendHeader("content-length", "3"); | 208 response_headers_["content-length"] = "3"; |
| 207 | 209 |
| 208 InSequence s; | 210 InSequence s; |
| 209 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, 0, false, _, nullptr)); | 211 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, 0, false, _, nullptr)); |
| 210 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(1). | 212 EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(1). |
| 211 WillOnce(Return(QuicConsumedData(3, true))); | 213 WillOnce(Return(QuicConsumedData(3, true))); |
| 212 | 214 |
| 213 QuicSpdyServerStreamPeer::SendErrorResponse(stream_.get()); | 215 QuicSpdyServerStreamPeer::SendErrorResponse(stream_.get()); |
| 214 EXPECT_TRUE(stream_->read_side_closed()); | 216 EXPECT_TRUE(stream_->read_side_closed()); |
| 215 EXPECT_TRUE(stream_->write_side_closed()); | 217 EXPECT_TRUE(stream_->write_side_closed()); |
| 216 } | 218 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 242 StringPiece data(arr, arraysize(arr)); | 244 StringPiece data(arr, arraysize(arr)); |
| 243 QuicStreamFrame frame(stream_->id(), true, 0, MakeIOVector(data)); | 245 QuicStreamFrame frame(stream_->id(), true, 0, MakeIOVector(data)); |
| 244 // Verify that we don't crash when we get a invalid headers in stream frame. | 246 // Verify that we don't crash when we get a invalid headers in stream frame. |
| 245 stream_->OnStreamFrame(frame); | 247 stream_->OnStreamFrame(frame); |
| 246 } | 248 } |
| 247 | 249 |
| 248 } // namespace | 250 } // namespace |
| 249 } // namespace test | 251 } // namespace test |
| 250 } // namespace tools | 252 } // namespace tools |
| 251 } // namespace net | 253 } // namespace net |
| OLD | NEW |