OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/spdy/spdy_write_queue.h" |
| 6 |
| 7 #include <cstddef> |
| 8 #include <cstring> |
| 9 #include <string> |
| 10 |
| 11 #include "base/basictypes.h" |
| 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "net/base/net_log.h" |
| 16 #include "net/base/request_priority.h" |
| 17 #include "net/spdy/spdy_stream.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" |
| 19 |
| 20 namespace net { |
| 21 |
| 22 namespace { |
| 23 |
| 24 class SpdyWriteQueueTest : public ::testing::Test {}; |
| 25 |
| 26 // Makes a SpdyFrameProducer producing a frame with the data in the |
| 27 // given string. |
| 28 scoped_ptr<SpdyFrameProducer> StringToProducer(const std::string& s) { |
| 29 scoped_ptr<char[]> data(new char[s.size()]); |
| 30 std::memcpy(data.get(), s.data(), s.size()); |
| 31 return scoped_ptr<SpdyFrameProducer>( |
| 32 new SimpleFrameProducer( |
| 33 scoped_ptr<SpdyFrame>( |
| 34 new SpdyFrame(data.release(), s.size(), true)))); |
| 35 } |
| 36 |
| 37 // Makes a SpdyFrameProducer producing a frame with the data in the |
| 38 // given int (converted to a string). |
| 39 scoped_ptr<SpdyFrameProducer> IntToProducer(int i) { |
| 40 return StringToProducer(base::IntToString(i)); |
| 41 } |
| 42 |
| 43 // Produces a frame with the given producer and returns a copy of its |
| 44 // data as a string. |
| 45 std::string ProducerToString(scoped_ptr<SpdyFrameProducer> producer) { |
| 46 scoped_ptr<SpdyFrame> frame = producer->ProduceFrame(); |
| 47 return std::string(frame->data(), frame->size()); |
| 48 } |
| 49 |
| 50 // Produces a frame with the given producer and returns a copy of its |
| 51 // data as an int (converted from a string). |
| 52 int ProducerToInt(scoped_ptr<SpdyFrameProducer> producer) { |
| 53 int i = 0; |
| 54 EXPECT_TRUE(base::StringToInt(ProducerToString(producer.Pass()), &i)); |
| 55 return i; |
| 56 } |
| 57 |
| 58 // Makes a SpdyStream with the given priority and a NULL SpdySession |
| 59 // -- be careful to not call any functions that expect the session to |
| 60 // be there. |
| 61 SpdyStream* MakeTestStream(RequestPriority priority) { |
| 62 return new SpdyStream(NULL, "", priority, 0, 0, false, BoundNetLog()); |
| 63 } |
| 64 |
| 65 // Add some frame producers of different priority. The producers |
| 66 // should be dequeued in priority order with their associated stream. |
| 67 TEST_F(SpdyWriteQueueTest, DequeuesByPriority) { |
| 68 SpdyWriteQueue write_queue; |
| 69 |
| 70 scoped_ptr<SpdyFrameProducer> producer_low = StringToProducer("LOW"); |
| 71 scoped_ptr<SpdyFrameProducer> producer_medium = StringToProducer("MEDIUM"); |
| 72 scoped_ptr<SpdyFrameProducer> producer_highest = StringToProducer("HIGHEST"); |
| 73 |
| 74 // A NULL stream should still work. |
| 75 scoped_refptr<SpdyStream> stream_low(NULL); |
| 76 scoped_refptr<SpdyStream> stream_medium(MakeTestStream(MEDIUM)); |
| 77 scoped_refptr<SpdyStream> stream_highest(MakeTestStream(HIGHEST)); |
| 78 |
| 79 write_queue.Enqueue(LOW, producer_low.Pass(), stream_low); |
| 80 write_queue.Enqueue(MEDIUM, producer_medium.Pass(), stream_medium); |
| 81 write_queue.Enqueue(HIGHEST, producer_highest.Pass(), stream_highest); |
| 82 |
| 83 scoped_ptr<SpdyFrameProducer> frame_producer; |
| 84 scoped_refptr<SpdyStream> stream; |
| 85 ASSERT_TRUE(write_queue.Dequeue(&frame_producer, &stream)); |
| 86 EXPECT_EQ("HIGHEST", ProducerToString(frame_producer.Pass())); |
| 87 EXPECT_EQ(stream_highest, stream); |
| 88 |
| 89 ASSERT_TRUE(write_queue.Dequeue(&frame_producer, &stream)); |
| 90 EXPECT_EQ("MEDIUM", ProducerToString(frame_producer.Pass())); |
| 91 EXPECT_EQ(stream_medium, stream); |
| 92 |
| 93 ASSERT_TRUE(write_queue.Dequeue(&frame_producer, &stream)); |
| 94 EXPECT_EQ("LOW", ProducerToString(frame_producer.Pass())); |
| 95 EXPECT_EQ(stream_low, stream); |
| 96 |
| 97 EXPECT_FALSE(write_queue.Dequeue(&frame_producer, &stream)); |
| 98 } |
| 99 |
| 100 // Add some frame producers with the same priority. The producers |
| 101 // should be dequeued in FIFO order with their associated stream. |
| 102 TEST_F(SpdyWriteQueueTest, DequeuesFIFO) { |
| 103 SpdyWriteQueue write_queue; |
| 104 |
| 105 scoped_ptr<SpdyFrameProducer> producer1 = IntToProducer(1); |
| 106 scoped_ptr<SpdyFrameProducer> producer2 = IntToProducer(2); |
| 107 scoped_ptr<SpdyFrameProducer> producer3 = IntToProducer(3); |
| 108 |
| 109 scoped_refptr<SpdyStream> stream1(MakeTestStream(DEFAULT_PRIORITY)); |
| 110 scoped_refptr<SpdyStream> stream2(MakeTestStream(DEFAULT_PRIORITY)); |
| 111 scoped_refptr<SpdyStream> stream3(MakeTestStream(DEFAULT_PRIORITY)); |
| 112 |
| 113 write_queue.Enqueue(DEFAULT_PRIORITY, producer1.Pass(), stream1); |
| 114 write_queue.Enqueue(DEFAULT_PRIORITY, producer2.Pass(), stream2); |
| 115 write_queue.Enqueue(DEFAULT_PRIORITY, producer3.Pass(), stream3); |
| 116 |
| 117 scoped_ptr<SpdyFrameProducer> frame_producer; |
| 118 scoped_refptr<SpdyStream> stream; |
| 119 ASSERT_TRUE(write_queue.Dequeue(&frame_producer, &stream)); |
| 120 EXPECT_EQ(1, ProducerToInt(frame_producer.Pass())); |
| 121 EXPECT_EQ(stream1, stream); |
| 122 |
| 123 ASSERT_TRUE(write_queue.Dequeue(&frame_producer, &stream)); |
| 124 EXPECT_EQ(2, ProducerToInt(frame_producer.Pass())); |
| 125 EXPECT_EQ(stream2, stream); |
| 126 |
| 127 ASSERT_TRUE(write_queue.Dequeue(&frame_producer, &stream)); |
| 128 EXPECT_EQ(3, ProducerToInt(frame_producer.Pass())); |
| 129 EXPECT_EQ(stream3, stream); |
| 130 |
| 131 EXPECT_FALSE(write_queue.Dequeue(&frame_producer, &stream)); |
| 132 } |
| 133 |
| 134 // Enqueue a bunch of writes and then call |
| 135 // RemovePendingWritesForStream() on one of the streams. No dequeued |
| 136 // write should be for that stream. |
| 137 TEST_F(SpdyWriteQueueTest, RemovePendingWritesForStream) { |
| 138 SpdyWriteQueue write_queue; |
| 139 |
| 140 scoped_refptr<SpdyStream> stream1(MakeTestStream(DEFAULT_PRIORITY)); |
| 141 scoped_refptr<SpdyStream> stream2(MakeTestStream(DEFAULT_PRIORITY)); |
| 142 |
| 143 for (int i = 0; i < 100; ++i) { |
| 144 scoped_refptr<SpdyStream> stream = ((i % 3) == 0) ? stream1 : stream2; |
| 145 write_queue.Enqueue(DEFAULT_PRIORITY, IntToProducer(i), stream); |
| 146 } |
| 147 |
| 148 write_queue.RemovePendingWritesForStream(stream2); |
| 149 |
| 150 for (int i = 0; i < 100; i += 3) { |
| 151 scoped_ptr<SpdyFrameProducer> frame_producer; |
| 152 scoped_refptr<SpdyStream> stream; |
| 153 ASSERT_TRUE(write_queue.Dequeue(&frame_producer, &stream)); |
| 154 EXPECT_EQ(i, ProducerToInt(frame_producer.Pass())); |
| 155 EXPECT_EQ(stream1, stream); |
| 156 } |
| 157 |
| 158 scoped_ptr<SpdyFrameProducer> frame_producer; |
| 159 scoped_refptr<SpdyStream> stream; |
| 160 EXPECT_FALSE(write_queue.Dequeue(&frame_producer, &stream)); |
| 161 } |
| 162 |
| 163 // Enqueue a bunch of writes and then call Clear(). The write queue |
| 164 // should clean up the memory properly, and Dequeue() should return |
| 165 // false. |
| 166 TEST_F(SpdyWriteQueueTest, Clear) { |
| 167 SpdyWriteQueue write_queue; |
| 168 |
| 169 for (int i = 0; i < 100; ++i) { |
| 170 write_queue.Enqueue(DEFAULT_PRIORITY, IntToProducer(i), NULL); |
| 171 } |
| 172 |
| 173 write_queue.Clear(); |
| 174 |
| 175 scoped_ptr<SpdyFrameProducer> frame_producer; |
| 176 scoped_refptr<SpdyStream> stream; |
| 177 EXPECT_FALSE(write_queue.Dequeue(&frame_producer, &stream)); |
| 178 } |
| 179 |
| 180 } |
| 181 |
| 182 } // namespace net |
OLD | NEW |