| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/quic/reliable_quic_stream.h" | 5 #include "net/quic/reliable_quic_stream.h" |
| 6 | 6 |
| 7 #include "net/quic/quic_connection.h" | 7 #include "net/quic/quic_connection.h" |
| 8 #include "net/quic/quic_spdy_compressor.h" | 8 #include "net/quic/quic_spdy_compressor.h" |
| 9 #include "net/quic/quic_spdy_decompressor.h" | 9 #include "net/quic/quic_spdy_decompressor.h" |
| 10 #include "net/quic/quic_utils.h" | 10 #include "net/quic/quic_utils.h" |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 WriteBlockedList<QuicStreamId>* write_blocked_list_; | 119 WriteBlockedList<QuicStreamId>* write_blocked_list_; |
| 120 }; | 120 }; |
| 121 | 121 |
| 122 TEST_F(ReliableQuicStreamTest, WriteAllData) { | 122 TEST_F(ReliableQuicStreamTest, WriteAllData) { |
| 123 Initialize(kShouldProcessData); | 123 Initialize(kShouldProcessData); |
| 124 | 124 |
| 125 connection_->options()->max_packet_length = | 125 connection_->options()->max_packet_length = |
| 126 1 + QuicPacketCreator::StreamFramePacketOverhead( | 126 1 + QuicPacketCreator::StreamFramePacketOverhead( |
| 127 connection_->version(), PACKET_8BYTE_GUID, !kIncludeVersion, | 127 connection_->version(), PACKET_8BYTE_GUID, !kIncludeVersion, |
| 128 PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); | 128 PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); |
| 129 // TODO(rch): figure out how to get StrEq working here. | 129 EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce( |
| 130 //EXPECT_CALL(*session_, WriteData(kStreamId, StrEq(kData1), _, _)).WillOnce( | |
| 131 EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce( | |
| 132 Return(QuicConsumedData(kDataLen, true))); | 130 Return(QuicConsumedData(kDataLen, true))); |
| 133 EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed); | 131 EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed); |
| 134 EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams()); | 132 EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams()); |
| 135 } | 133 } |
| 136 | 134 |
| 137 // TODO(rtenneti): Death tests crash on OS_ANDROID. | 135 // TODO(rtenneti): Death tests crash on OS_ANDROID. |
| 138 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) && !defined(OS_ANDROID) | 136 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) && !defined(OS_ANDROID) |
| 139 TEST_F(ReliableQuicStreamTest, NoBlockingIfNoDataOrFin) { | 137 TEST_F(ReliableQuicStreamTest, NoBlockingIfNoDataOrFin) { |
| 140 Initialize(kShouldProcessData); | 138 Initialize(kShouldProcessData); |
| 141 | 139 |
| 142 // Write no data and no fin. If we consume nothing we should not be write | 140 // Write no data and no fin. If we consume nothing we should not be write |
| 143 // blocked. | 141 // blocked. |
| 144 EXPECT_DEBUG_DEATH({ | 142 EXPECT_DEBUG_DEATH({ |
| 145 EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce( | 143 EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce( |
| 146 Return(QuicConsumedData(0, false))); | 144 Return(QuicConsumedData(0, false))); |
| 147 stream_->WriteData(StringPiece(), false); | 145 stream_->WriteData(StringPiece(), false); |
| 148 EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams()); | 146 EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams()); |
| 149 }, ""); | 147 }, ""); |
| 150 } | 148 } |
| 151 #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) && !defined(OS_ANDROID) | 149 #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) && !defined(OS_ANDROID) |
| 152 | 150 |
| 153 TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) { | 151 TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) { |
| 154 Initialize(kShouldProcessData); | 152 Initialize(kShouldProcessData); |
| 155 | 153 |
| 156 // Write some data and no fin. If we consume some but not all of the data, | 154 // Write some data and no fin. If we consume some but not all of the data, |
| 157 // we should be write blocked a not all the data was consumed. | 155 // we should be write blocked a not all the data was consumed. |
| 158 EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce( | 156 EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce( |
| 159 Return(QuicConsumedData(1, false))); | 157 Return(QuicConsumedData(1, false))); |
| 160 stream_->WriteData(StringPiece(kData1, 2), false); | 158 stream_->WriteData(StringPiece(kData1, 2), false); |
| 161 ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams()); | 159 ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams()); |
| 162 } | 160 } |
| 163 | 161 |
| 164 | 162 |
| 165 TEST_F(ReliableQuicStreamTest, BlockIfFinNotConsumedWithData) { | 163 TEST_F(ReliableQuicStreamTest, BlockIfFinNotConsumedWithData) { |
| 166 Initialize(kShouldProcessData); | 164 Initialize(kShouldProcessData); |
| 167 | 165 |
| 168 // Write some data and no fin. If we consume all the data but not the fin, | 166 // Write some data and no fin. If we consume all the data but not the fin, |
| 169 // we should be write blocked because the fin was not consumed. | 167 // we should be write blocked because the fin was not consumed. |
| 170 // (This should never actually happen as the fin should be sent out with the | 168 // (This should never actually happen as the fin should be sent out with the |
| 171 // last data) | 169 // last data) |
| 172 EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce( | 170 EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce( |
| 173 Return(QuicConsumedData(2, false))); | 171 Return(QuicConsumedData(2, false))); |
| 174 stream_->WriteData(StringPiece(kData1, 2), true); | 172 stream_->WriteData(StringPiece(kData1, 2), true); |
| 175 ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams()); | 173 ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams()); |
| 176 } | 174 } |
| 177 | 175 |
| 178 TEST_F(ReliableQuicStreamTest, BlockIfSoloFinNotConsumed) { | 176 TEST_F(ReliableQuicStreamTest, BlockIfSoloFinNotConsumed) { |
| 179 Initialize(kShouldProcessData); | 177 Initialize(kShouldProcessData); |
| 180 | 178 |
| 181 // Write no data and a fin. If we consume nothing we should be write blocked, | 179 // Write no data and a fin. If we consume nothing we should be write blocked, |
| 182 // as the fin was not consumed. | 180 // as the fin was not consumed. |
| 183 EXPECT_CALL(*session_, WriteData(kStreamId, _, _, _)).WillOnce( | 181 EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce( |
| 184 Return(QuicConsumedData(0, false))); | 182 Return(QuicConsumedData(0, false))); |
| 185 stream_->WriteData(StringPiece(), true); | 183 stream_->WriteData(StringPiece(), true); |
| 186 ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams()); | 184 ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams()); |
| 187 } | 185 } |
| 188 | 186 |
| 189 TEST_F(ReliableQuicStreamTest, WriteData) { | 187 TEST_F(ReliableQuicStreamTest, WriteData) { |
| 190 Initialize(kShouldProcessData); | 188 Initialize(kShouldProcessData); |
| 191 | 189 |
| 192 EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams()); | 190 EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams()); |
| 193 connection_->options()->max_packet_length = | 191 connection_->options()->max_packet_length = |
| 194 1 + QuicPacketCreator::StreamFramePacketOverhead( | 192 1 + QuicPacketCreator::StreamFramePacketOverhead( |
| 195 connection_->version(), PACKET_8BYTE_GUID, !kIncludeVersion, | 193 connection_->version(), PACKET_8BYTE_GUID, !kIncludeVersion, |
| 196 PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); | 194 PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP); |
| 197 // TODO(rch): figure out how to get StrEq working here. | 195 EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)).WillOnce( |
| 198 //EXPECT_CALL(*session_, WriteData(_, StrEq(kData1), _, _)).WillOnce( | |
| 199 EXPECT_CALL(*session_, WriteData(_, _, _, _)).WillOnce( | |
| 200 Return(QuicConsumedData(kDataLen - 1, false))); | 196 Return(QuicConsumedData(kDataLen - 1, false))); |
| 201 // The return will be kDataLen, because the last byte gets buffered. | 197 // The return will be kDataLen, because the last byte gets buffered. |
| 202 EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed); | 198 EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed); |
| 203 EXPECT_TRUE(write_blocked_list_->HasWriteBlockedStreams()); | 199 EXPECT_TRUE(write_blocked_list_->HasWriteBlockedStreams()); |
| 204 | 200 |
| 205 // Queue a bytes_consumed write. | 201 // Queue a bytes_consumed write. |
| 206 EXPECT_EQ(kDataLen, stream_->WriteData(kData2, false).bytes_consumed); | 202 EXPECT_EQ(kDataLen, stream_->WriteData(kData2, false).bytes_consumed); |
| 207 | 203 |
| 208 // Make sure we get the tail of the first write followed by the bytes_consumed | 204 // Make sure we get the tail of the first write followed by the bytes_consumed |
| 209 InSequence s; | 205 InSequence s; |
| 210 //EXPECT_CALL(*session_, WriteData(_, StrEq(&kData1[kDataLen - 1]), _, _)). | 206 EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)). |
| 211 EXPECT_CALL(*session_, WriteData(_, _, _, _)). | |
| 212 WillOnce(Return(QuicConsumedData(1, false))); | 207 WillOnce(Return(QuicConsumedData(1, false))); |
| 213 //EXPECT_CALL(*session_, WriteData(_, StrEq(kData2), _, _)). | 208 EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)). |
| 214 EXPECT_CALL(*session_, WriteData(_, _, _, _)). | |
| 215 WillOnce(Return(QuicConsumedData(kDataLen - 2, false))); | 209 WillOnce(Return(QuicConsumedData(kDataLen - 2, false))); |
| 216 stream_->OnCanWrite(); | 210 stream_->OnCanWrite(); |
| 217 | 211 |
| 218 // And finally the end of the bytes_consumed | 212 // And finally the end of the bytes_consumed. |
| 219 //EXPECT_CALL(*session_, WriteData(_, StrEq(&kData2[kDataLen - 2]), _, _)). | 213 EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)). |
| 220 EXPECT_CALL(*session_, WriteData(_, _, _, _)). | |
| 221 WillOnce(Return(QuicConsumedData(2, true))); | 214 WillOnce(Return(QuicConsumedData(2, true))); |
| 222 stream_->OnCanWrite(); | 215 stream_->OnCanWrite(); |
| 223 } | 216 } |
| 224 | 217 |
| 225 TEST_F(ReliableQuicStreamTest, ConnectionCloseAfterStreamClose) { | 218 TEST_F(ReliableQuicStreamTest, ConnectionCloseAfterStreamClose) { |
| 226 Initialize(kShouldProcessData); | 219 Initialize(kShouldProcessData); |
| 227 | 220 |
| 228 stream_->CloseReadSide(); | 221 stream_->CloseReadSide(); |
| 229 stream_->CloseWriteSide(); | 222 stream_->CloseWriteSide(); |
| 230 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); | 223 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); |
| 231 EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error()); | 224 EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error()); |
| 232 stream_->ConnectionClose(QUIC_INTERNAL_ERROR, false); | 225 stream_->ConnectionClose(QUIC_INTERNAL_ERROR, false); |
| 233 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); | 226 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); |
| 234 EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error()); | 227 EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error()); |
| 235 } | 228 } |
| 236 | 229 |
| 237 TEST_F(ReliableQuicStreamTest, ProcessHeaders) { | 230 TEST_F(ReliableQuicStreamTest, ProcessHeaders) { |
| 238 Initialize(kShouldProcessData); | 231 Initialize(kShouldProcessData); |
| 239 | 232 |
| 240 string compressed_headers = | 233 string compressed_headers = |
| 241 compressor_->CompressHeadersWithPriority(0, headers_); | 234 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 242 QuicStreamFrame frame(kStreamId, false, 0, compressed_headers); | 235 QuicStreamFrame frame(kStreamId, false, 0, compressed_headers); |
| 243 | 236 |
| 244 stream_->OnStreamFrame(frame); | 237 stream_->OnStreamFrame(frame); |
| 245 EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_), stream_->data()); | 238 EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_), stream_->data()); |
| 246 EXPECT_EQ(0u, stream_->priority()); | 239 EXPECT_EQ(static_cast<QuicPriority>(kHighestPriority), |
| 240 stream_->EffectivePriority()); |
| 247 } | 241 } |
| 248 | 242 |
| 249 TEST_F(ReliableQuicStreamTest, ProcessHeadersWithInvalidHeaderId) { | 243 TEST_F(ReliableQuicStreamTest, ProcessHeadersWithInvalidHeaderId) { |
| 250 Initialize(kShouldProcessData); | 244 Initialize(kShouldProcessData); |
| 251 | 245 |
| 252 string compressed_headers = | 246 string compressed_headers = |
| 253 compressor_->CompressHeadersWithPriority(0, headers_); | 247 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 254 compressed_headers.replace(4, 1, 1, '\xFF'); // Illegal header id. | 248 compressed_headers.replace(4, 1, 1, '\xFF'); // Illegal header id. |
| 255 QuicStreamFrame frame(kStreamId, false, 0, compressed_headers); | 249 QuicStreamFrame frame(kStreamId, false, 0, compressed_headers); |
| 256 | 250 |
| 257 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID)); | 251 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID)); |
| 258 stream_->OnStreamFrame(frame); | 252 stream_->OnStreamFrame(frame); |
| 259 } | 253 } |
| 260 | 254 |
| 261 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBody) { | 255 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBody) { |
| 262 Initialize(kShouldProcessData); | 256 Initialize(kShouldProcessData); |
| 263 | 257 |
| 264 string compressed_headers = | 258 string compressed_headers = |
| 265 compressor_->CompressHeadersWithPriority(0, headers_); | 259 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 266 string body = "this is the body"; | 260 string body = "this is the body"; |
| 267 string data = compressed_headers + body; | 261 string data = compressed_headers + body; |
| 268 QuicStreamFrame frame(kStreamId, false, 0, data); | 262 QuicStreamFrame frame(kStreamId, false, 0, data); |
| 269 | 263 |
| 270 stream_->OnStreamFrame(frame); | 264 stream_->OnStreamFrame(frame); |
| 271 EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body, | 265 EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body, |
| 272 stream_->data()); | 266 stream_->data()); |
| 273 } | 267 } |
| 274 | 268 |
| 275 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyFragments) { | 269 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyFragments) { |
| 276 Initialize(kShouldProcessData); | 270 Initialize(kShouldProcessData); |
| 277 | 271 |
| 278 string compressed_headers = | 272 string compressed_headers = |
| 279 compressor_->CompressHeadersWithPriority(7, headers_); | 273 compressor_->CompressHeadersWithPriority(kLowestPriority, headers_); |
| 280 string body = "this is the body"; | 274 string body = "this is the body"; |
| 281 string data = compressed_headers + body; | 275 string data = compressed_headers + body; |
| 282 | 276 |
| 283 for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) { | 277 for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) { |
| 284 Initialize(kShouldProcessData); | 278 Initialize(kShouldProcessData); |
| 285 for (size_t offset = 0; offset < data.size(); offset += fragment_size) { | 279 for (size_t offset = 0; offset < data.size(); offset += fragment_size) { |
| 286 size_t remaining_data = data.length() - offset; | 280 size_t remaining_data = data.length() - offset; |
| 287 StringPiece fragment(data.data() + offset, | 281 StringPiece fragment(data.data() + offset, |
| 288 min(fragment_size, remaining_data)); | 282 min(fragment_size, remaining_data)); |
| 289 QuicStreamFrame frame(kStreamId, false, offset, fragment); | 283 QuicStreamFrame frame(kStreamId, false, offset, fragment); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 301 QuicStreamFrame frame1(kStreamId, false, 0, fragment1); | 295 QuicStreamFrame frame1(kStreamId, false, 0, fragment1); |
| 302 stream_->OnStreamFrame(frame1); | 296 stream_->OnStreamFrame(frame1); |
| 303 | 297 |
| 304 StringPiece fragment2(data.data() + split_point, data.size() - split_point); | 298 StringPiece fragment2(data.data() + split_point, data.size() - split_point); |
| 305 QuicStreamFrame frame2(kStreamId, false, split_point, fragment2); | 299 QuicStreamFrame frame2(kStreamId, false, split_point, fragment2); |
| 306 stream_->OnStreamFrame(frame2); | 300 stream_->OnStreamFrame(frame2); |
| 307 | 301 |
| 308 ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body, | 302 ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body, |
| 309 stream_->data()) << "split_point: " << split_point; | 303 stream_->data()) << "split_point: " << split_point; |
| 310 } | 304 } |
| 311 EXPECT_EQ(7u, stream_->priority()); | 305 EXPECT_EQ(static_cast<QuicPriority>(kLowestPriority), |
| 306 stream_->EffectivePriority()); |
| 312 } | 307 } |
| 313 | 308 |
| 314 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyReadv) { | 309 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyReadv) { |
| 315 Initialize(!kShouldProcessData); | 310 Initialize(!kShouldProcessData); |
| 316 | 311 |
| 317 string compressed_headers = | 312 string compressed_headers = |
| 318 compressor_->CompressHeadersWithPriority(0, headers_); | 313 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 319 string body = "this is the body"; | 314 string body = "this is the body"; |
| 320 string data = compressed_headers + body; | 315 string data = compressed_headers + body; |
| 321 QuicStreamFrame frame(kStreamId, false, 0, data); | 316 QuicStreamFrame frame(kStreamId, false, 0, data); |
| 322 string uncompressed_headers = | 317 string uncompressed_headers = |
| 323 SpdyUtils::SerializeUncompressedHeaders(headers_); | 318 SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 324 string uncompressed_data = uncompressed_headers + body; | 319 string uncompressed_data = uncompressed_headers + body; |
| 325 | 320 |
| 326 stream_->OnStreamFrame(frame); | 321 stream_->OnStreamFrame(frame); |
| 327 EXPECT_EQ(uncompressed_headers, stream_->data()); | 322 EXPECT_EQ(uncompressed_headers, stream_->data()); |
| 328 | 323 |
| 329 char buffer[2048]; | 324 char buffer[2048]; |
| 330 ASSERT_LT(data.length(), arraysize(buffer)); | 325 ASSERT_LT(data.length(), arraysize(buffer)); |
| 331 struct iovec vec; | 326 struct iovec vec; |
| 332 vec.iov_base = buffer; | 327 vec.iov_base = buffer; |
| 333 vec.iov_len = arraysize(buffer); | 328 vec.iov_len = arraysize(buffer); |
| 334 | 329 |
| 335 size_t bytes_read = stream_->Readv(&vec, 1); | 330 size_t bytes_read = stream_->Readv(&vec, 1); |
| 336 EXPECT_EQ(uncompressed_headers.length(), bytes_read); | 331 EXPECT_EQ(uncompressed_headers.length(), bytes_read); |
| 337 EXPECT_EQ(uncompressed_headers, string(buffer, bytes_read)); | 332 EXPECT_EQ(uncompressed_headers, string(buffer, bytes_read)); |
| 338 | 333 |
| 339 bytes_read = stream_->Readv(&vec, 1); | 334 bytes_read = stream_->Readv(&vec, 1); |
| 340 EXPECT_EQ(body.length(), bytes_read); | 335 EXPECT_EQ(body.length(), bytes_read); |
| 341 EXPECT_EQ(body, string(buffer, bytes_read)); | 336 EXPECT_EQ(body, string(buffer, bytes_read)); |
| 342 } | 337 } |
| 343 | 338 |
| 344 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyIncrementalReadv) { | 339 TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyIncrementalReadv) { |
| 345 Initialize(!kShouldProcessData); | 340 Initialize(!kShouldProcessData); |
| 346 | 341 |
| 347 string compressed_headers = | 342 string compressed_headers = |
| 348 compressor_->CompressHeadersWithPriority(0, headers_); | 343 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 349 string body = "this is the body"; | 344 string body = "this is the body"; |
| 350 string data = compressed_headers + body; | 345 string data = compressed_headers + body; |
| 351 QuicStreamFrame frame(kStreamId, false, 0, data); | 346 QuicStreamFrame frame(kStreamId, false, 0, data); |
| 352 string uncompressed_headers = | 347 string uncompressed_headers = |
| 353 SpdyUtils::SerializeUncompressedHeaders(headers_); | 348 SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 354 string uncompressed_data = uncompressed_headers + body; | 349 string uncompressed_data = uncompressed_headers + body; |
| 355 | 350 |
| 356 stream_->OnStreamFrame(frame); | 351 stream_->OnStreamFrame(frame); |
| 357 EXPECT_EQ(uncompressed_headers, stream_->data()); | 352 EXPECT_EQ(uncompressed_headers, stream_->data()); |
| 358 | 353 |
| 359 char buffer[1]; | 354 char buffer[1]; |
| 360 struct iovec vec; | 355 struct iovec vec; |
| 361 vec.iov_base = buffer; | 356 vec.iov_base = buffer; |
| 362 vec.iov_len = arraysize(buffer); | 357 vec.iov_len = arraysize(buffer); |
| 363 for (size_t i = 0; i < uncompressed_data.length(); ++i) { | 358 for (size_t i = 0; i < uncompressed_data.length(); ++i) { |
| 364 size_t bytes_read = stream_->Readv(&vec, 1); | 359 size_t bytes_read = stream_->Readv(&vec, 1); |
| 365 ASSERT_EQ(1u, bytes_read); | 360 ASSERT_EQ(1u, bytes_read); |
| 366 EXPECT_EQ(uncompressed_data.data()[i], buffer[0]); | 361 EXPECT_EQ(uncompressed_data.data()[i], buffer[0]); |
| 367 } | 362 } |
| 368 } | 363 } |
| 369 | 364 |
| 370 TEST_F(ReliableQuicStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) { | 365 TEST_F(ReliableQuicStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) { |
| 371 Initialize(!kShouldProcessData); | 366 Initialize(!kShouldProcessData); |
| 372 | 367 |
| 373 string compressed_headers = | 368 string compressed_headers = |
| 374 compressor_->CompressHeadersWithPriority(0, headers_); | 369 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 375 string body = "this is the body"; | 370 string body = "this is the body"; |
| 376 string data = compressed_headers + body; | 371 string data = compressed_headers + body; |
| 377 QuicStreamFrame frame(kStreamId, false, 0, data); | 372 QuicStreamFrame frame(kStreamId, false, 0, data); |
| 378 string uncompressed_headers = | 373 string uncompressed_headers = |
| 379 SpdyUtils::SerializeUncompressedHeaders(headers_); | 374 SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 380 string uncompressed_data = uncompressed_headers + body; | 375 string uncompressed_data = uncompressed_headers + body; |
| 381 | 376 |
| 382 stream_->OnStreamFrame(frame); | 377 stream_->OnStreamFrame(frame); |
| 383 EXPECT_EQ(uncompressed_headers, stream_->data()); | 378 EXPECT_EQ(uncompressed_headers, stream_->data()); |
| 384 | 379 |
| 385 char buffer1[1]; | 380 char buffer1[1]; |
| 386 char buffer2[1]; | 381 char buffer2[1]; |
| 387 struct iovec vec[2]; | 382 struct iovec vec[2]; |
| 388 vec[0].iov_base = buffer1; | 383 vec[0].iov_base = buffer1; |
| 389 vec[0].iov_len = arraysize(buffer1); | 384 vec[0].iov_len = arraysize(buffer1); |
| 390 vec[1].iov_base = buffer2; | 385 vec[1].iov_base = buffer2; |
| 391 vec[1].iov_len = arraysize(buffer2); | 386 vec[1].iov_len = arraysize(buffer2); |
| 392 for (size_t i = 0; i < uncompressed_data.length(); i += 2) { | 387 for (size_t i = 0; i < uncompressed_data.length(); i += 2) { |
| 393 size_t bytes_read = stream_->Readv(vec, 2); | 388 size_t bytes_read = stream_->Readv(vec, 2); |
| 394 ASSERT_EQ(2u, bytes_read) << i; | 389 ASSERT_EQ(2u, bytes_read) << i; |
| 395 ASSERT_EQ(uncompressed_data.data()[i], buffer1[0]) << i; | 390 ASSERT_EQ(uncompressed_data.data()[i], buffer1[0]) << i; |
| 396 ASSERT_EQ(uncompressed_data.data()[i + 1], buffer2[0]) << i; | 391 ASSERT_EQ(uncompressed_data.data()[i + 1], buffer2[0]) << i; |
| 397 } | 392 } |
| 398 } | 393 } |
| 399 | 394 |
| 400 TEST_F(ReliableQuicStreamTest, ProcessCorruptHeadersEarly) { | 395 TEST_F(ReliableQuicStreamTest, ProcessCorruptHeadersEarly) { |
| 401 Initialize(kShouldProcessData); | 396 Initialize(kShouldProcessData); |
| 402 | 397 |
| 403 string compressed_headers1 = | 398 string compressed_headers1 = |
| 404 compressor_->CompressHeadersWithPriority(0, headers_); | 399 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 405 QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1); | 400 QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1); |
| 406 string decompressed_headers1 = | 401 string decompressed_headers1 = |
| 407 SpdyUtils::SerializeUncompressedHeaders(headers_); | 402 SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 408 | 403 |
| 409 headers_["content-type"] = "text/plain"; | 404 headers_["content-type"] = "text/plain"; |
| 410 string compressed_headers2 = | 405 string compressed_headers2 = |
| 411 compressor_->CompressHeadersWithPriority(0, headers_); | 406 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 412 // Corrupt the compressed data. | 407 // Corrupt the compressed data. |
| 413 compressed_headers2[compressed_headers2.length() - 1] ^= 0xA1; | 408 compressed_headers2[compressed_headers2.length() - 1] ^= 0xA1; |
| 414 QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2); | 409 QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2); |
| 415 string decompressed_headers2 = | 410 string decompressed_headers2 = |
| 416 SpdyUtils::SerializeUncompressedHeaders(headers_); | 411 SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 417 | 412 |
| 418 // Deliver frame2 to stream2 out of order. The decompressor is not | 413 // Deliver frame2 to stream2 out of order. The decompressor is not |
| 419 // available yet, so no data will be processed. The compressed data | 414 // available yet, so no data will be processed. The compressed data |
| 420 // will be buffered until OnDecompressorAvailable() is called | 415 // will be buffered until OnDecompressorAvailable() is called |
| 421 // to process it. | 416 // to process it. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 434 EXPECT_EQ(2u, session_->decompressor()->current_header_id()); | 429 EXPECT_EQ(2u, session_->decompressor()->current_header_id()); |
| 435 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE)); | 430 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE)); |
| 436 stream2_->OnDecompressorAvailable(); | 431 stream2_->OnDecompressorAvailable(); |
| 437 EXPECT_EQ("", stream2_->data()); | 432 EXPECT_EQ("", stream2_->data()); |
| 438 } | 433 } |
| 439 | 434 |
| 440 TEST_F(ReliableQuicStreamTest, ProcessPartialHeadersEarly) { | 435 TEST_F(ReliableQuicStreamTest, ProcessPartialHeadersEarly) { |
| 441 Initialize(kShouldProcessData); | 436 Initialize(kShouldProcessData); |
| 442 | 437 |
| 443 string compressed_headers1 = | 438 string compressed_headers1 = |
| 444 compressor_->CompressHeadersWithPriority(0, headers_); | 439 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 445 QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1); | 440 QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1); |
| 446 string decompressed_headers1 = | 441 string decompressed_headers1 = |
| 447 SpdyUtils::SerializeUncompressedHeaders(headers_); | 442 SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 448 | 443 |
| 449 headers_["content-type"] = "text/plain"; | 444 headers_["content-type"] = "text/plain"; |
| 450 string compressed_headers2 = | 445 string compressed_headers2 = |
| 451 compressor_->CompressHeadersWithPriority(0, headers_); | 446 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 452 string partial_compressed_headers = | 447 string partial_compressed_headers = |
| 453 compressed_headers2.substr(0, compressed_headers2.length() / 2); | 448 compressed_headers2.substr(0, compressed_headers2.length() / 2); |
| 454 QuicStreamFrame frame2(stream2_->id(), false, 0, partial_compressed_headers); | 449 QuicStreamFrame frame2(stream2_->id(), false, 0, partial_compressed_headers); |
| 455 string decompressed_headers2 = | 450 string decompressed_headers2 = |
| 456 SpdyUtils::SerializeUncompressedHeaders(headers_); | 451 SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 457 | 452 |
| 458 // Deliver frame2 to stream2 out of order. The decompressor is not | 453 // Deliver frame2 to stream2 out of order. The decompressor is not |
| 459 // available yet, so no data will be processed. The compressed data | 454 // available yet, so no data will be processed. The compressed data |
| 460 // will be buffered until OnDecompressorAvailable() is called | 455 // will be buffered until OnDecompressorAvailable() is called |
| 461 // to process it. | 456 // to process it. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 485 partial_compressed_headers.length(), | 480 partial_compressed_headers.length(), |
| 486 remaining_compressed_headers); | 481 remaining_compressed_headers); |
| 487 stream2_->OnStreamFrame(frame3); | 482 stream2_->OnStreamFrame(frame3); |
| 488 EXPECT_EQ(decompressed_headers2, stream2_->data()); | 483 EXPECT_EQ(decompressed_headers2, stream2_->data()); |
| 489 } | 484 } |
| 490 | 485 |
| 491 TEST_F(ReliableQuicStreamTest, ProcessHeadersEarly) { | 486 TEST_F(ReliableQuicStreamTest, ProcessHeadersEarly) { |
| 492 Initialize(kShouldProcessData); | 487 Initialize(kShouldProcessData); |
| 493 | 488 |
| 494 string compressed_headers1 = | 489 string compressed_headers1 = |
| 495 compressor_->CompressHeadersWithPriority(0, headers_); | 490 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 496 QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1); | 491 QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1); |
| 497 string decompressed_headers1 = | 492 string decompressed_headers1 = |
| 498 SpdyUtils::SerializeUncompressedHeaders(headers_); | 493 SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 499 | 494 |
| 500 headers_["content-type"] = "text/plain"; | 495 headers_["content-type"] = "text/plain"; |
| 501 string compressed_headers2 = | 496 string compressed_headers2 = |
| 502 compressor_->CompressHeadersWithPriority(0, headers_); | 497 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 503 QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2); | 498 QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2); |
| 504 string decompressed_headers2 = | 499 string decompressed_headers2 = |
| 505 SpdyUtils::SerializeUncompressedHeaders(headers_); | 500 SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 506 | 501 |
| 507 // Deliver frame2 to stream2 out of order. The decompressor is not | 502 // Deliver frame2 to stream2 out of order. The decompressor is not |
| 508 // available yet, so no data will be processed. The compressed data | 503 // available yet, so no data will be processed. The compressed data |
| 509 // will be buffered until OnDecompressorAvailable() is called | 504 // will be buffered until OnDecompressorAvailable() is called |
| 510 // to process it. | 505 // to process it. |
| 511 stream2_->OnStreamFrame(frame2); | 506 stream2_->OnStreamFrame(frame2); |
| 512 EXPECT_EQ("", stream2_->data()); | 507 EXPECT_EQ("", stream2_->data()); |
| 513 | 508 |
| 514 // Now deliver frame1 to stream1. The decompressor is available so | 509 // Now deliver frame1 to stream1. The decompressor is available so |
| 515 // the data will be processed, and the decompressor will become | 510 // the data will be processed, and the decompressor will become |
| 516 // available for stream2. | 511 // available for stream2. |
| 517 stream_->OnStreamFrame(frame1); | 512 stream_->OnStreamFrame(frame1); |
| 518 EXPECT_EQ(decompressed_headers1, stream_->data()); | 513 EXPECT_EQ(decompressed_headers1, stream_->data()); |
| 519 | 514 |
| 520 // Verify that the decompressor is available, and inform stream2 | 515 // Verify that the decompressor is available, and inform stream2 |
| 521 // that it can now decompress the buffered compressed data. | 516 // that it can now decompress the buffered compressed data. |
| 522 EXPECT_EQ(2u, session_->decompressor()->current_header_id()); | 517 EXPECT_EQ(2u, session_->decompressor()->current_header_id()); |
| 523 stream2_->OnDecompressorAvailable(); | 518 stream2_->OnDecompressorAvailable(); |
| 524 EXPECT_EQ(decompressed_headers2, stream2_->data()); | 519 EXPECT_EQ(decompressed_headers2, stream2_->data()); |
| 525 } | 520 } |
| 526 | 521 |
| 527 TEST_F(ReliableQuicStreamTest, ProcessHeadersDelay) { | 522 TEST_F(ReliableQuicStreamTest, ProcessHeadersDelay) { |
| 528 Initialize(!kShouldProcessData); | 523 Initialize(!kShouldProcessData); |
| 529 | 524 |
| 530 string compressed_headers = | 525 string compressed_headers = |
| 531 compressor_->CompressHeadersWithPriority(0, headers_); | 526 compressor_->CompressHeadersWithPriority(kHighestPriority, headers_); |
| 532 QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers); | 527 QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers); |
| 533 string decompressed_headers = | 528 string decompressed_headers = |
| 534 SpdyUtils::SerializeUncompressedHeaders(headers_); | 529 SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 535 | 530 |
| 536 // Send the headers to the stream and verify they were decompressed. | 531 // Send the headers to the stream and verify they were decompressed. |
| 537 stream_->OnStreamFrame(frame1); | 532 stream_->OnStreamFrame(frame1); |
| 538 EXPECT_EQ(2u, session_->decompressor()->current_header_id()); | 533 EXPECT_EQ(2u, session_->decompressor()->current_header_id()); |
| 539 | 534 |
| 540 // Verify that we are now able to handle the body data, | 535 // Verify that we are now able to handle the body data, |
| 541 // even though the stream has not processed the headers. | 536 // even though the stream has not processed the headers. |
| 542 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID)) | 537 EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID)) |
| 543 .Times(0); | 538 .Times(0); |
| 544 QuicStreamFrame frame2(stream_->id(), false, compressed_headers.length(), | 539 QuicStreamFrame frame2(stream_->id(), false, compressed_headers.length(), |
| 545 "body data"); | 540 "body data"); |
| 546 stream_->OnStreamFrame(frame2); | 541 stream_->OnStreamFrame(frame2); |
| 547 } | 542 } |
| 548 | 543 |
| 549 } // namespace | 544 } // namespace |
| 550 } // namespace test | 545 } // namespace test |
| 551 } // namespace net | 546 } // namespace net |
| OLD | NEW |