Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(142)

Side by Side Diff: net/spdy/spdy_write_queue_unittest.cc

Issue 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_write_queue.cc ('k') | net/spdy/write_scheduler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 <memory>
10 #include <utility>
11
12 #include "base/logging.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "net/base/request_priority.h"
16 #include "net/log/net_log_with_source.h"
17 #include "net/spdy/platform/api/spdy_string.h"
18 #include "net/spdy/spdy_buffer_producer.h"
19 #include "net/spdy/spdy_stream.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "url/gurl.h"
22
23 namespace net {
24
25 namespace {
26
27 const char kOriginal[] = "original";
28 const char kRequeued[] = "requeued";
29
30 class SpdyWriteQueueTest : public ::testing::Test {};
31
32 // Makes a SpdyFrameProducer producing a frame with the data in the
33 // given string.
34 std::unique_ptr<SpdyBufferProducer> StringToProducer(const SpdyString& s) {
35 std::unique_ptr<char[]> data(new char[s.size()]);
36 std::memcpy(data.get(), s.data(), s.size());
37 return std::unique_ptr<SpdyBufferProducer>(
38 new SimpleBufferProducer(std::unique_ptr<SpdyBuffer>(
39 new SpdyBuffer(std::unique_ptr<SpdySerializedFrame>(
40 new SpdySerializedFrame(data.release(), s.size(), true))))));
41 }
42
43 // Makes a SpdyBufferProducer producing a frame with the data in the
44 // given int (converted to a string).
45 std::unique_ptr<SpdyBufferProducer> IntToProducer(int i) {
46 return StringToProducer(base::IntToString(i));
47 }
48
49 // Producer whose produced buffer will enqueue yet another buffer into the
50 // SpdyWriteQueue upon destruction.
51 class RequeingBufferProducer : public SpdyBufferProducer {
52 public:
53 explicit RequeingBufferProducer(SpdyWriteQueue* queue) {
54 buffer_.reset(new SpdyBuffer(kOriginal, arraysize(kOriginal)));
55 buffer_->AddConsumeCallback(
56 base::Bind(RequeingBufferProducer::ConsumeCallback, queue));
57 }
58
59 std::unique_ptr<SpdyBuffer> ProduceBuffer() override {
60 return std::move(buffer_);
61 }
62
63 size_t EstimateMemoryUsage() const override {
64 NOTREACHED();
65 return 0;
66 }
67
68 static void ConsumeCallback(SpdyWriteQueue* queue,
69 size_t size,
70 SpdyBuffer::ConsumeSource source) {
71 std::unique_ptr<SpdyBufferProducer> producer(
72 new SimpleBufferProducer(std::unique_ptr<SpdyBuffer>(
73 new SpdyBuffer(kRequeued, arraysize(kRequeued)))));
74
75 queue->Enqueue(MEDIUM, SpdyFrameType::RST_STREAM, std::move(producer),
76 base::WeakPtr<SpdyStream>());
77 }
78
79 private:
80 std::unique_ptr<SpdyBuffer> buffer_;
81 };
82
83 // Produces a frame with the given producer and returns a copy of its
84 // data as a string.
85 SpdyString ProducerToString(std::unique_ptr<SpdyBufferProducer> producer) {
86 std::unique_ptr<SpdyBuffer> buffer = producer->ProduceBuffer();
87 return SpdyString(buffer->GetRemainingData(), buffer->GetRemainingSize());
88 }
89
90 // Produces a frame with the given producer and returns a copy of its
91 // data as an int (converted from a string).
92 int ProducerToInt(std::unique_ptr<SpdyBufferProducer> producer) {
93 int i = 0;
94 EXPECT_TRUE(base::StringToInt(ProducerToString(std::move(producer)), &i));
95 return i;
96 }
97
98 // Makes a SpdyStream with the given priority and a NULL SpdySession
99 // -- be careful to not call any functions that expect the session to
100 // be there.
101 SpdyStream* MakeTestStream(RequestPriority priority) {
102 return new SpdyStream(SPDY_BIDIRECTIONAL_STREAM, base::WeakPtr<SpdySession>(),
103 GURL(), priority, 0, 0, NetLogWithSource());
104 }
105
106 // Add some frame producers of different priority. The producers
107 // should be dequeued in priority order with their associated stream.
108 TEST_F(SpdyWriteQueueTest, DequeuesByPriority) {
109 SpdyWriteQueue write_queue;
110
111 std::unique_ptr<SpdyBufferProducer> producer_low = StringToProducer("LOW");
112 std::unique_ptr<SpdyBufferProducer> producer_medium =
113 StringToProducer("MEDIUM");
114 std::unique_ptr<SpdyBufferProducer> producer_highest =
115 StringToProducer("HIGHEST");
116
117 std::unique_ptr<SpdyStream> stream_medium(MakeTestStream(MEDIUM));
118 std::unique_ptr<SpdyStream> stream_highest(MakeTestStream(HIGHEST));
119
120 // A NULL stream should still work.
121 write_queue.Enqueue(LOW, SpdyFrameType::HEADERS, std::move(producer_low),
122 base::WeakPtr<SpdyStream>());
123 write_queue.Enqueue(MEDIUM, SpdyFrameType::HEADERS,
124 std::move(producer_medium), stream_medium->GetWeakPtr());
125 write_queue.Enqueue(HIGHEST, SpdyFrameType::RST_STREAM,
126 std::move(producer_highest),
127 stream_highest->GetWeakPtr());
128
129 SpdyFrameType frame_type = SpdyFrameType::DATA;
130 std::unique_ptr<SpdyBufferProducer> frame_producer;
131 base::WeakPtr<SpdyStream> stream;
132 ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
133 EXPECT_EQ(SpdyFrameType::RST_STREAM, frame_type);
134 EXPECT_EQ("HIGHEST", ProducerToString(std::move(frame_producer)));
135 EXPECT_EQ(stream_highest.get(), stream.get());
136
137 ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
138 EXPECT_EQ(SpdyFrameType::HEADERS, frame_type);
139 EXPECT_EQ("MEDIUM", ProducerToString(std::move(frame_producer)));
140 EXPECT_EQ(stream_medium.get(), stream.get());
141
142 ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
143 EXPECT_EQ(SpdyFrameType::HEADERS, frame_type);
144 EXPECT_EQ("LOW", ProducerToString(std::move(frame_producer)));
145 EXPECT_EQ(nullptr, stream.get());
146
147 EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
148 }
149
150 // Add some frame producers with the same priority. The producers
151 // should be dequeued in FIFO order with their associated stream.
152 TEST_F(SpdyWriteQueueTest, DequeuesFIFO) {
153 SpdyWriteQueue write_queue;
154
155 std::unique_ptr<SpdyBufferProducer> producer1 = IntToProducer(1);
156 std::unique_ptr<SpdyBufferProducer> producer2 = IntToProducer(2);
157 std::unique_ptr<SpdyBufferProducer> producer3 = IntToProducer(3);
158
159 std::unique_ptr<SpdyStream> stream1(MakeTestStream(DEFAULT_PRIORITY));
160 std::unique_ptr<SpdyStream> stream2(MakeTestStream(DEFAULT_PRIORITY));
161 std::unique_ptr<SpdyStream> stream3(MakeTestStream(DEFAULT_PRIORITY));
162
163 write_queue.Enqueue(DEFAULT_PRIORITY, SpdyFrameType::HEADERS,
164 std::move(producer1), stream1->GetWeakPtr());
165 write_queue.Enqueue(DEFAULT_PRIORITY, SpdyFrameType::HEADERS,
166 std::move(producer2), stream2->GetWeakPtr());
167 write_queue.Enqueue(DEFAULT_PRIORITY, SpdyFrameType::RST_STREAM,
168 std::move(producer3), stream3->GetWeakPtr());
169
170 SpdyFrameType frame_type = SpdyFrameType::DATA;
171 std::unique_ptr<SpdyBufferProducer> frame_producer;
172 base::WeakPtr<SpdyStream> stream;
173 ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
174 EXPECT_EQ(SpdyFrameType::HEADERS, frame_type);
175 EXPECT_EQ(1, ProducerToInt(std::move(frame_producer)));
176 EXPECT_EQ(stream1.get(), stream.get());
177
178 ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
179 EXPECT_EQ(SpdyFrameType::HEADERS, frame_type);
180 EXPECT_EQ(2, ProducerToInt(std::move(frame_producer)));
181 EXPECT_EQ(stream2.get(), stream.get());
182
183 ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
184 EXPECT_EQ(SpdyFrameType::RST_STREAM, frame_type);
185 EXPECT_EQ(3, ProducerToInt(std::move(frame_producer)));
186 EXPECT_EQ(stream3.get(), stream.get());
187
188 EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
189 }
190
191 // Enqueue a bunch of writes and then call
192 // RemovePendingWritesForStream() on one of the streams. No dequeued
193 // write should be for that stream.
194 TEST_F(SpdyWriteQueueTest, RemovePendingWritesForStream) {
195 SpdyWriteQueue write_queue;
196
197 std::unique_ptr<SpdyStream> stream1(MakeTestStream(DEFAULT_PRIORITY));
198 std::unique_ptr<SpdyStream> stream2(MakeTestStream(DEFAULT_PRIORITY));
199
200 for (int i = 0; i < 100; ++i) {
201 base::WeakPtr<SpdyStream> stream =
202 (((i % 3) == 0) ? stream1 : stream2)->GetWeakPtr();
203 write_queue.Enqueue(DEFAULT_PRIORITY, SpdyFrameType::HEADERS,
204 IntToProducer(i), stream);
205 }
206
207 write_queue.RemovePendingWritesForStream(stream2->GetWeakPtr());
208
209 for (int i = 0; i < 100; i += 3) {
210 SpdyFrameType frame_type = SpdyFrameType::DATA;
211 std::unique_ptr<SpdyBufferProducer> frame_producer;
212 base::WeakPtr<SpdyStream> stream;
213 ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
214 EXPECT_EQ(SpdyFrameType::HEADERS, frame_type);
215 EXPECT_EQ(i, ProducerToInt(std::move(frame_producer)));
216 EXPECT_EQ(stream1.get(), stream.get());
217 }
218
219 SpdyFrameType frame_type = SpdyFrameType::DATA;
220 std::unique_ptr<SpdyBufferProducer> frame_producer;
221 base::WeakPtr<SpdyStream> stream;
222 EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
223 }
224
225 // Enqueue a bunch of writes and then call
226 // RemovePendingWritesForStreamsAfter(). No dequeued write should be for
227 // those streams without a stream id, or with a stream_id after that
228 // argument.
229 TEST_F(SpdyWriteQueueTest, RemovePendingWritesForStreamsAfter) {
230 SpdyWriteQueue write_queue;
231
232 std::unique_ptr<SpdyStream> stream1(MakeTestStream(DEFAULT_PRIORITY));
233 stream1->set_stream_id(1);
234 std::unique_ptr<SpdyStream> stream2(MakeTestStream(DEFAULT_PRIORITY));
235 stream2->set_stream_id(3);
236 std::unique_ptr<SpdyStream> stream3(MakeTestStream(DEFAULT_PRIORITY));
237 stream3->set_stream_id(5);
238 // No stream id assigned.
239 std::unique_ptr<SpdyStream> stream4(MakeTestStream(DEFAULT_PRIORITY));
240 base::WeakPtr<SpdyStream> streams[] = {
241 stream1->GetWeakPtr(), stream2->GetWeakPtr(),
242 stream3->GetWeakPtr(), stream4->GetWeakPtr()
243 };
244
245 for (int i = 0; i < 100; ++i) {
246 write_queue.Enqueue(DEFAULT_PRIORITY, SpdyFrameType::HEADERS,
247 IntToProducer(i), streams[i % arraysize(streams)]);
248 }
249
250 write_queue.RemovePendingWritesForStreamsAfter(stream1->stream_id());
251
252 for (int i = 0; i < 100; i += arraysize(streams)) {
253 SpdyFrameType frame_type = SpdyFrameType::DATA;
254 std::unique_ptr<SpdyBufferProducer> frame_producer;
255 base::WeakPtr<SpdyStream> stream;
256 ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream))
257 << "Unable to Dequeue i: " << i;
258 EXPECT_EQ(SpdyFrameType::HEADERS, frame_type);
259 EXPECT_EQ(i, ProducerToInt(std::move(frame_producer)));
260 EXPECT_EQ(stream1.get(), stream.get());
261 }
262
263 SpdyFrameType frame_type = SpdyFrameType::DATA;
264 std::unique_ptr<SpdyBufferProducer> frame_producer;
265 base::WeakPtr<SpdyStream> stream;
266 EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
267 }
268
269 // Enqueue a bunch of writes and then call Clear(). The write queue
270 // should clean up the memory properly, and Dequeue() should return
271 // false.
272 TEST_F(SpdyWriteQueueTest, Clear) {
273 SpdyWriteQueue write_queue;
274
275 for (int i = 0; i < 100; ++i) {
276 write_queue.Enqueue(DEFAULT_PRIORITY, SpdyFrameType::HEADERS,
277 IntToProducer(i), base::WeakPtr<SpdyStream>());
278 }
279
280 write_queue.Clear();
281
282 SpdyFrameType frame_type = SpdyFrameType::DATA;
283 std::unique_ptr<SpdyBufferProducer> frame_producer;
284 base::WeakPtr<SpdyStream> stream;
285 EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
286 }
287
288 TEST_F(SpdyWriteQueueTest, RequeingProducerWithoutReentrance) {
289 SpdyWriteQueue queue;
290 queue.Enqueue(
291 DEFAULT_PRIORITY, SpdyFrameType::HEADERS,
292 std::unique_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)),
293 base::WeakPtr<SpdyStream>());
294 {
295 SpdyFrameType frame_type;
296 std::unique_ptr<SpdyBufferProducer> producer;
297 base::WeakPtr<SpdyStream> stream;
298
299 EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &stream));
300 EXPECT_TRUE(queue.IsEmpty());
301 EXPECT_EQ(SpdyString(kOriginal),
302 producer->ProduceBuffer()->GetRemainingData());
303 }
304 // |producer| was destroyed, and a buffer is re-queued.
305 EXPECT_FALSE(queue.IsEmpty());
306
307 SpdyFrameType frame_type;
308 std::unique_ptr<SpdyBufferProducer> producer;
309 base::WeakPtr<SpdyStream> stream;
310
311 EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &stream));
312 EXPECT_EQ(SpdyString(kRequeued),
313 producer->ProduceBuffer()->GetRemainingData());
314 }
315
316 TEST_F(SpdyWriteQueueTest, ReentranceOnClear) {
317 SpdyWriteQueue queue;
318 queue.Enqueue(
319 DEFAULT_PRIORITY, SpdyFrameType::HEADERS,
320 std::unique_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)),
321 base::WeakPtr<SpdyStream>());
322
323 queue.Clear();
324 EXPECT_FALSE(queue.IsEmpty());
325
326 SpdyFrameType frame_type;
327 std::unique_ptr<SpdyBufferProducer> producer;
328 base::WeakPtr<SpdyStream> stream;
329
330 EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &stream));
331 EXPECT_EQ(SpdyString(kRequeued),
332 producer->ProduceBuffer()->GetRemainingData());
333 }
334
335 TEST_F(SpdyWriteQueueTest, ReentranceOnRemovePendingWritesAfter) {
336 std::unique_ptr<SpdyStream> stream(MakeTestStream(DEFAULT_PRIORITY));
337 stream->set_stream_id(2);
338
339 SpdyWriteQueue queue;
340 queue.Enqueue(
341 DEFAULT_PRIORITY, SpdyFrameType::HEADERS,
342 std::unique_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)),
343 stream->GetWeakPtr());
344
345 queue.RemovePendingWritesForStreamsAfter(1);
346 EXPECT_FALSE(queue.IsEmpty());
347
348 SpdyFrameType frame_type;
349 std::unique_ptr<SpdyBufferProducer> producer;
350 base::WeakPtr<SpdyStream> weak_stream;
351
352 EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &weak_stream));
353 EXPECT_EQ(SpdyString(kRequeued),
354 producer->ProduceBuffer()->GetRemainingData());
355 }
356
357 TEST_F(SpdyWriteQueueTest, ReentranceOnRemovePendingWritesForStream) {
358 std::unique_ptr<SpdyStream> stream(MakeTestStream(DEFAULT_PRIORITY));
359 stream->set_stream_id(2);
360
361 SpdyWriteQueue queue;
362 queue.Enqueue(
363 DEFAULT_PRIORITY, SpdyFrameType::HEADERS,
364 std::unique_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)),
365 stream->GetWeakPtr());
366
367 queue.RemovePendingWritesForStream(stream->GetWeakPtr());
368 EXPECT_FALSE(queue.IsEmpty());
369
370 SpdyFrameType frame_type;
371 std::unique_ptr<SpdyBufferProducer> producer;
372 base::WeakPtr<SpdyStream> weak_stream;
373
374 EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &weak_stream));
375 EXPECT_EQ(SpdyString(kRequeued),
376 producer->ProduceBuffer()->GetRemainingData());
377 }
378
379 } // namespace
380
381 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_write_queue.cc ('k') | net/spdy/write_scheduler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698