| 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/spdy/spdy_write_queue.h" | 5 #include "net/spdy/spdy_write_queue.h" |
| 6 | 6 |
| 7 #include <cstddef> | 7 #include <cstddef> |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| 11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "net/base/net_log.h" | 15 #include "net/base/net_log.h" |
| 16 #include "net/base/request_priority.h" | 16 #include "net/base/request_priority.h" |
| 17 #include "net/spdy/spdy_buffer_producer.h" | 17 #include "net/spdy/spdy_buffer_producer.h" |
| 18 #include "net/spdy/spdy_stream.h" | 18 #include "net/spdy/spdy_stream.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
| 20 #include "url/gurl.h" | 20 #include "url/gurl.h" |
| 21 | 21 |
| 22 namespace net { | 22 namespace net { |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 using std::string; |
| 27 |
| 28 const char kOriginal[] = "original"; |
| 29 const char kRequeued[] = "requeued"; |
| 30 |
| 26 class SpdyWriteQueueTest : public ::testing::Test {}; | 31 class SpdyWriteQueueTest : public ::testing::Test {}; |
| 27 | 32 |
| 28 // Makes a SpdyFrameProducer producing a frame with the data in the | 33 // Makes a SpdyFrameProducer producing a frame with the data in the |
| 29 // given string. | 34 // given string. |
| 30 scoped_ptr<SpdyBufferProducer> StringToProducer(const std::string& s) { | 35 scoped_ptr<SpdyBufferProducer> StringToProducer(const std::string& s) { |
| 31 scoped_ptr<char[]> data(new char[s.size()]); | 36 scoped_ptr<char[]> data(new char[s.size()]); |
| 32 std::memcpy(data.get(), s.data(), s.size()); | 37 std::memcpy(data.get(), s.data(), s.size()); |
| 33 return scoped_ptr<SpdyBufferProducer>( | 38 return scoped_ptr<SpdyBufferProducer>( |
| 34 new SimpleBufferProducer( | 39 new SimpleBufferProducer( |
| 35 scoped_ptr<SpdyBuffer>( | 40 scoped_ptr<SpdyBuffer>( |
| 36 new SpdyBuffer( | 41 new SpdyBuffer( |
| 37 scoped_ptr<SpdyFrame>( | 42 scoped_ptr<SpdyFrame>( |
| 38 new SpdyFrame(data.release(), s.size(), true)))))); | 43 new SpdyFrame(data.release(), s.size(), true)))))); |
| 39 } | 44 } |
| 40 | 45 |
| 41 // Makes a SpdyBufferProducer producing a frame with the data in the | 46 // Makes a SpdyBufferProducer producing a frame with the data in the |
| 42 // given int (converted to a string). | 47 // given int (converted to a string). |
| 43 scoped_ptr<SpdyBufferProducer> IntToProducer(int i) { | 48 scoped_ptr<SpdyBufferProducer> IntToProducer(int i) { |
| 44 return StringToProducer(base::IntToString(i)); | 49 return StringToProducer(base::IntToString(i)); |
| 45 } | 50 } |
| 46 | 51 |
| 52 // Producer whose produced buffer will enqueue yet another buffer into the |
| 53 // SpdyWriteQueue upon destruction. |
| 54 class RequeingBufferProducer : public SpdyBufferProducer { |
| 55 public: |
| 56 RequeingBufferProducer(SpdyWriteQueue* queue) { |
| 57 buffer_.reset(new SpdyBuffer(kOriginal, arraysize(kOriginal))); |
| 58 buffer_->AddConsumeCallback( |
| 59 base::Bind(RequeingBufferProducer::ConsumeCallback, queue)); |
| 60 } |
| 61 |
| 62 virtual scoped_ptr<SpdyBuffer> ProduceBuffer() OVERRIDE { |
| 63 return buffer_.Pass(); |
| 64 } |
| 65 |
| 66 static void ConsumeCallback(SpdyWriteQueue* queue, |
| 67 size_t size, |
| 68 SpdyBuffer::ConsumeSource source) { |
| 69 scoped_ptr<SpdyBufferProducer> producer( |
| 70 new SimpleBufferProducer(scoped_ptr<SpdyBuffer>( |
| 71 new SpdyBuffer(kRequeued, arraysize(kRequeued))))); |
| 72 |
| 73 queue->Enqueue( |
| 74 MEDIUM, RST_STREAM, producer.Pass(), base::WeakPtr<SpdyStream>()); |
| 75 } |
| 76 |
| 77 private: |
| 78 scoped_ptr<SpdyBuffer> buffer_; |
| 79 }; |
| 80 |
| 47 // Produces a frame with the given producer and returns a copy of its | 81 // Produces a frame with the given producer and returns a copy of its |
| 48 // data as a string. | 82 // data as a string. |
| 49 std::string ProducerToString(scoped_ptr<SpdyBufferProducer> producer) { | 83 std::string ProducerToString(scoped_ptr<SpdyBufferProducer> producer) { |
| 50 scoped_ptr<SpdyBuffer> buffer = producer->ProduceBuffer(); | 84 scoped_ptr<SpdyBuffer> buffer = producer->ProduceBuffer(); |
| 51 return std::string(buffer->GetRemainingData(), buffer->GetRemainingSize()); | 85 return std::string(buffer->GetRemainingData(), buffer->GetRemainingSize()); |
| 52 } | 86 } |
| 53 | 87 |
| 54 // Produces a frame with the given producer and returns a copy of its | 88 // Produces a frame with the given producer and returns a copy of its |
| 55 // data as an int (converted from a string). | 89 // data as an int (converted from a string). |
| 56 int ProducerToInt(scoped_ptr<SpdyBufferProducer> producer) { | 90 int ProducerToInt(scoped_ptr<SpdyBufferProducer> producer) { |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 } | 274 } |
| 241 | 275 |
| 242 write_queue.Clear(); | 276 write_queue.Clear(); |
| 243 | 277 |
| 244 SpdyFrameType frame_type = DATA; | 278 SpdyFrameType frame_type = DATA; |
| 245 scoped_ptr<SpdyBufferProducer> frame_producer; | 279 scoped_ptr<SpdyBufferProducer> frame_producer; |
| 246 base::WeakPtr<SpdyStream> stream; | 280 base::WeakPtr<SpdyStream> stream; |
| 247 EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream)); | 281 EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream)); |
| 248 } | 282 } |
| 249 | 283 |
| 284 TEST_F(SpdyWriteQueueTest, RequeingProducerWithoutReentrance) { |
| 285 SpdyWriteQueue queue; |
| 286 queue.Enqueue( |
| 287 DEFAULT_PRIORITY, |
| 288 SYN_STREAM, |
| 289 scoped_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)), |
| 290 base::WeakPtr<SpdyStream>()); |
| 291 { |
| 292 SpdyFrameType frame_type; |
| 293 scoped_ptr<SpdyBufferProducer> producer; |
| 294 base::WeakPtr<SpdyStream> stream; |
| 295 |
| 296 EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &stream)); |
| 297 EXPECT_TRUE(queue.IsEmpty()); |
| 298 EXPECT_EQ(string(kOriginal), producer->ProduceBuffer()->GetRemainingData()); |
| 299 } |
| 300 // |producer| was destroyed, and a buffer is re-queued. |
| 301 EXPECT_FALSE(queue.IsEmpty()); |
| 302 |
| 303 SpdyFrameType frame_type; |
| 304 scoped_ptr<SpdyBufferProducer> producer; |
| 305 base::WeakPtr<SpdyStream> stream; |
| 306 |
| 307 EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &stream)); |
| 308 EXPECT_EQ(string(kRequeued), producer->ProduceBuffer()->GetRemainingData()); |
| 309 } |
| 310 |
| 311 TEST_F(SpdyWriteQueueTest, ReentranceOnClear) { |
| 312 SpdyWriteQueue queue; |
| 313 queue.Enqueue( |
| 314 DEFAULT_PRIORITY, |
| 315 SYN_STREAM, |
| 316 scoped_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)), |
| 317 base::WeakPtr<SpdyStream>()); |
| 318 |
| 319 queue.Clear(); |
| 320 EXPECT_FALSE(queue.IsEmpty()); |
| 321 |
| 322 SpdyFrameType frame_type; |
| 323 scoped_ptr<SpdyBufferProducer> producer; |
| 324 base::WeakPtr<SpdyStream> stream; |
| 325 |
| 326 EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &stream)); |
| 327 EXPECT_EQ(string(kRequeued), producer->ProduceBuffer()->GetRemainingData()); |
| 328 } |
| 329 |
| 330 TEST_F(SpdyWriteQueueTest, ReentranceOnRemovePendingWritesAfter) { |
| 331 scoped_ptr<SpdyStream> stream(MakeTestStream(DEFAULT_PRIORITY)); |
| 332 stream->set_stream_id(2); |
| 333 |
| 334 SpdyWriteQueue queue; |
| 335 queue.Enqueue( |
| 336 DEFAULT_PRIORITY, |
| 337 SYN_STREAM, |
| 338 scoped_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)), |
| 339 stream->GetWeakPtr()); |
| 340 |
| 341 queue.RemovePendingWritesForStreamsAfter(1); |
| 342 EXPECT_FALSE(queue.IsEmpty()); |
| 343 |
| 344 SpdyFrameType frame_type; |
| 345 scoped_ptr<SpdyBufferProducer> producer; |
| 346 base::WeakPtr<SpdyStream> weak_stream; |
| 347 |
| 348 EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &weak_stream)); |
| 349 EXPECT_EQ(string(kRequeued), producer->ProduceBuffer()->GetRemainingData()); |
| 350 } |
| 351 |
| 352 TEST_F(SpdyWriteQueueTest, ReentranceOnRemovePendingWritesForStream) { |
| 353 scoped_ptr<SpdyStream> stream(MakeTestStream(DEFAULT_PRIORITY)); |
| 354 stream->set_stream_id(2); |
| 355 |
| 356 SpdyWriteQueue queue; |
| 357 queue.Enqueue( |
| 358 DEFAULT_PRIORITY, |
| 359 SYN_STREAM, |
| 360 scoped_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)), |
| 361 stream->GetWeakPtr()); |
| 362 |
| 363 queue.RemovePendingWritesForStream(stream->GetWeakPtr()); |
| 364 EXPECT_FALSE(queue.IsEmpty()); |
| 365 |
| 366 SpdyFrameType frame_type; |
| 367 scoped_ptr<SpdyBufferProducer> producer; |
| 368 base::WeakPtr<SpdyStream> weak_stream; |
| 369 |
| 370 EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &weak_stream)); |
| 371 EXPECT_EQ(string(kRequeued), producer->ProduceBuffer()->GetRemainingData()); |
| 372 } |
| 373 |
| 250 } // namespace | 374 } // namespace |
| 251 | 375 |
| 252 } // namespace net | 376 } // namespace net |
| OLD | NEW |