• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/spdy/spdy_write_queue.h"
11 
12 #include <cstddef>
13 #include <cstring>
14 #include <string>
15 #include <utility>
16 
17 #include "base/functional/bind.h"
18 #include "base/memory/ref_counted.h"
19 #include "base/notreached.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "net/base/request_priority.h"
22 #include "net/log/net_log_with_source.h"
23 #include "net/spdy/spdy_buffer_producer.h"
24 #include "net/spdy/spdy_stream.h"
25 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "url/gurl.h"
28 
29 namespace net {
30 
31 namespace {
32 
33 const char kOriginal[] = "original";
34 const char kRequeued[] = "requeued";
35 
36 class SpdyWriteQueueTest : public ::testing::Test {};
37 
38 // Makes a SpdyFrameProducer producing a frame with the data in the
39 // given string.
StringToProducer(const std::string & s)40 std::unique_ptr<SpdyBufferProducer> StringToProducer(const std::string& s) {
41   auto data = std::make_unique<char[]>(s.size());
42   std::memcpy(data.get(), s.data(), s.size());
43   auto frame =
44       std::make_unique<spdy::SpdySerializedFrame>(std::move(data), s.size());
45   auto buffer = std::make_unique<SpdyBuffer>(std::move(frame));
46   return std::make_unique<SimpleBufferProducer>(std::move(buffer));
47 }
48 
49 // Makes a SpdyBufferProducer producing a frame with the data in the
50 // given int (converted to a string).
IntToProducer(int i)51 std::unique_ptr<SpdyBufferProducer> IntToProducer(int i) {
52   return StringToProducer(base::NumberToString(i));
53 }
54 
55 // Producer whose produced buffer will enqueue yet another buffer into the
56 // SpdyWriteQueue upon destruction.
57 class RequeingBufferProducer : public SpdyBufferProducer {
58  public:
RequeingBufferProducer(SpdyWriteQueue * queue)59   explicit RequeingBufferProducer(SpdyWriteQueue* queue) {
60     buffer_ = std::make_unique<SpdyBuffer>(kOriginal, std::size(kOriginal));
61     buffer_->AddConsumeCallback(
62         base::BindRepeating(RequeingBufferProducer::ConsumeCallback, queue));
63   }
64 
ProduceBuffer()65   std::unique_ptr<SpdyBuffer> ProduceBuffer() override {
66     return std::move(buffer_);
67   }
68 
ConsumeCallback(SpdyWriteQueue * queue,size_t size,SpdyBuffer::ConsumeSource source)69   static void ConsumeCallback(SpdyWriteQueue* queue,
70                               size_t size,
71                               SpdyBuffer::ConsumeSource source) {
72     auto buffer = std::make_unique<SpdyBuffer>(kRequeued, std::size(kRequeued));
73     auto buffer_producer =
74         std::make_unique<SimpleBufferProducer>(std::move(buffer));
75 
76     queue->Enqueue(MEDIUM, spdy::SpdyFrameType::RST_STREAM,
77                    std::move(buffer_producer), base::WeakPtr<SpdyStream>(),
78                    TRAFFIC_ANNOTATION_FOR_TESTS);
79   }
80 
81  private:
82   std::unique_ptr<SpdyBuffer> buffer_;
83 };
84 
85 // Produces a frame with the given producer and returns a copy of its
86 // data as a string.
ProducerToString(std::unique_ptr<SpdyBufferProducer> producer)87 std::string ProducerToString(std::unique_ptr<SpdyBufferProducer> producer) {
88   std::unique_ptr<SpdyBuffer> buffer = producer->ProduceBuffer();
89   return std::string(buffer->GetRemainingData(), buffer->GetRemainingSize());
90 }
91 
92 // Produces a frame with the given producer and returns a copy of its
93 // data as an int (converted from a string).
ProducerToInt(std::unique_ptr<SpdyBufferProducer> producer)94 int ProducerToInt(std::unique_ptr<SpdyBufferProducer> producer) {
95   int i = 0;
96   EXPECT_TRUE(base::StringToInt(ProducerToString(std::move(producer)), &i));
97   return i;
98 }
99 
100 // Makes a SpdyStream with the given priority and a NULL SpdySession
101 // -- be careful to not call any functions that expect the session to
102 // be there.
MakeTestStream(RequestPriority priority)103 std::unique_ptr<SpdyStream> MakeTestStream(RequestPriority priority) {
104   return std::make_unique<SpdyStream>(
105       SPDY_BIDIRECTIONAL_STREAM, base::WeakPtr<SpdySession>(), GURL(), priority,
106       0, 0, NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS,
107       false /* detect_broken_connection */);
108 }
109 
110 // Add some frame producers of different priority. The producers
111 // should be dequeued in priority order with their associated stream.
TEST_F(SpdyWriteQueueTest,DequeuesByPriority)112 TEST_F(SpdyWriteQueueTest, DequeuesByPriority) {
113   SpdyWriteQueue write_queue;
114 
115   std::unique_ptr<SpdyBufferProducer> producer_low = StringToProducer("LOW");
116   std::unique_ptr<SpdyBufferProducer> producer_medium =
117       StringToProducer("MEDIUM");
118   std::unique_ptr<SpdyBufferProducer> producer_highest =
119       StringToProducer("HIGHEST");
120 
121   std::unique_ptr<SpdyStream> stream_medium = MakeTestStream(MEDIUM);
122   std::unique_ptr<SpdyStream> stream_highest = MakeTestStream(HIGHEST);
123 
124   // A NULL stream should still work.
125   write_queue.Enqueue(LOW, spdy::SpdyFrameType::HEADERS,
126                       std::move(producer_low), base::WeakPtr<SpdyStream>(),
127                       TRAFFIC_ANNOTATION_FOR_TESTS);
128   write_queue.Enqueue(MEDIUM, spdy::SpdyFrameType::HEADERS,
129                       std::move(producer_medium), stream_medium->GetWeakPtr(),
130                       TRAFFIC_ANNOTATION_FOR_TESTS);
131   write_queue.Enqueue(HIGHEST, spdy::SpdyFrameType::RST_STREAM,
132                       std::move(producer_highest), stream_highest->GetWeakPtr(),
133                       TRAFFIC_ANNOTATION_FOR_TESTS);
134 
135   spdy::SpdyFrameType frame_type = spdy::SpdyFrameType::DATA;
136   std::unique_ptr<SpdyBufferProducer> frame_producer;
137   base::WeakPtr<SpdyStream> stream;
138   MutableNetworkTrafficAnnotationTag traffic_annotation;
139   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
140                                   &traffic_annotation));
141   EXPECT_EQ(spdy::SpdyFrameType::RST_STREAM, frame_type);
142   EXPECT_EQ("HIGHEST", ProducerToString(std::move(frame_producer)));
143   EXPECT_EQ(stream_highest.get(), stream.get());
144 
145   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
146                                   &traffic_annotation));
147   EXPECT_EQ(spdy::SpdyFrameType::HEADERS, frame_type);
148   EXPECT_EQ("MEDIUM", ProducerToString(std::move(frame_producer)));
149   EXPECT_EQ(stream_medium.get(), stream.get());
150 
151   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
152                                   &traffic_annotation));
153   EXPECT_EQ(spdy::SpdyFrameType::HEADERS, frame_type);
154   EXPECT_EQ("LOW", ProducerToString(std::move(frame_producer)));
155   EXPECT_EQ(nullptr, stream.get());
156 
157   EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
158                                    &traffic_annotation));
159 }
160 
161 // Add some frame producers with the same priority. The producers
162 // should be dequeued in FIFO order with their associated stream.
TEST_F(SpdyWriteQueueTest,DequeuesFIFO)163 TEST_F(SpdyWriteQueueTest, DequeuesFIFO) {
164   SpdyWriteQueue write_queue;
165 
166   std::unique_ptr<SpdyBufferProducer> producer1 = IntToProducer(1);
167   std::unique_ptr<SpdyBufferProducer> producer2 = IntToProducer(2);
168   std::unique_ptr<SpdyBufferProducer> producer3 = IntToProducer(3);
169 
170   std::unique_ptr<SpdyStream> stream1 = MakeTestStream(DEFAULT_PRIORITY);
171   std::unique_ptr<SpdyStream> stream2 = MakeTestStream(DEFAULT_PRIORITY);
172   std::unique_ptr<SpdyStream> stream3 = MakeTestStream(DEFAULT_PRIORITY);
173 
174   write_queue.Enqueue(DEFAULT_PRIORITY, spdy::SpdyFrameType::HEADERS,
175                       std::move(producer1), stream1->GetWeakPtr(),
176                       TRAFFIC_ANNOTATION_FOR_TESTS);
177   write_queue.Enqueue(DEFAULT_PRIORITY, spdy::SpdyFrameType::HEADERS,
178                       std::move(producer2), stream2->GetWeakPtr(),
179                       TRAFFIC_ANNOTATION_FOR_TESTS);
180   write_queue.Enqueue(DEFAULT_PRIORITY, spdy::SpdyFrameType::RST_STREAM,
181                       std::move(producer3), stream3->GetWeakPtr(),
182                       TRAFFIC_ANNOTATION_FOR_TESTS);
183 
184   spdy::SpdyFrameType frame_type = spdy::SpdyFrameType::DATA;
185   std::unique_ptr<SpdyBufferProducer> frame_producer;
186   base::WeakPtr<SpdyStream> stream;
187   MutableNetworkTrafficAnnotationTag traffic_annotation;
188   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
189                                   &traffic_annotation));
190   EXPECT_EQ(spdy::SpdyFrameType::HEADERS, frame_type);
191   EXPECT_EQ(1, ProducerToInt(std::move(frame_producer)));
192   EXPECT_EQ(stream1.get(), stream.get());
193 
194   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
195                                   &traffic_annotation));
196   EXPECT_EQ(spdy::SpdyFrameType::HEADERS, frame_type);
197   EXPECT_EQ(2, ProducerToInt(std::move(frame_producer)));
198   EXPECT_EQ(stream2.get(), stream.get());
199 
200   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
201                                   &traffic_annotation));
202   EXPECT_EQ(spdy::SpdyFrameType::RST_STREAM, frame_type);
203   EXPECT_EQ(3, ProducerToInt(std::move(frame_producer)));
204   EXPECT_EQ(stream3.get(), stream.get());
205 
206   EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
207                                    &traffic_annotation));
208 }
209 
210 // Enqueue a bunch of writes and then call
211 // RemovePendingWritesForStream() on one of the streams. No dequeued
212 // write should be for that stream.
TEST_F(SpdyWriteQueueTest,RemovePendingWritesForStream)213 TEST_F(SpdyWriteQueueTest, RemovePendingWritesForStream) {
214   SpdyWriteQueue write_queue;
215 
216   std::unique_ptr<SpdyStream> stream1 = MakeTestStream(DEFAULT_PRIORITY);
217   std::unique_ptr<SpdyStream> stream2 = MakeTestStream(DEFAULT_PRIORITY);
218 
219   for (int i = 0; i < 100; ++i) {
220     base::WeakPtr<SpdyStream> stream =
221         (((i % 3) == 0) ? stream1 : stream2)->GetWeakPtr();
222     write_queue.Enqueue(DEFAULT_PRIORITY, spdy::SpdyFrameType::HEADERS,
223                         IntToProducer(i), stream, TRAFFIC_ANNOTATION_FOR_TESTS);
224   }
225 
226   write_queue.RemovePendingWritesForStream(stream2.get());
227 
228   for (int i = 0; i < 100; i += 3) {
229     spdy::SpdyFrameType frame_type = spdy::SpdyFrameType::DATA;
230     std::unique_ptr<SpdyBufferProducer> frame_producer;
231     base::WeakPtr<SpdyStream> stream;
232     MutableNetworkTrafficAnnotationTag traffic_annotation;
233     ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
234                                     &traffic_annotation));
235     EXPECT_EQ(spdy::SpdyFrameType::HEADERS, frame_type);
236     EXPECT_EQ(i, ProducerToInt(std::move(frame_producer)));
237     EXPECT_EQ(stream1.get(), stream.get());
238     EXPECT_EQ(MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
239               traffic_annotation);
240   }
241 
242   spdy::SpdyFrameType frame_type = spdy::SpdyFrameType::DATA;
243   std::unique_ptr<SpdyBufferProducer> frame_producer;
244   base::WeakPtr<SpdyStream> stream;
245   MutableNetworkTrafficAnnotationTag traffic_annotation;
246   EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
247                                    &traffic_annotation));
248 }
249 
250 // Enqueue a bunch of writes and then call
251 // RemovePendingWritesForStreamsAfter(). No dequeued write should be for
252 // those streams without a stream id, or with a stream_id after that
253 // argument.
TEST_F(SpdyWriteQueueTest,RemovePendingWritesForStreamsAfter)254 TEST_F(SpdyWriteQueueTest, RemovePendingWritesForStreamsAfter) {
255   SpdyWriteQueue write_queue;
256 
257   std::unique_ptr<SpdyStream> stream1 = MakeTestStream(DEFAULT_PRIORITY);
258   stream1->set_stream_id(1);
259   std::unique_ptr<SpdyStream> stream2 = MakeTestStream(DEFAULT_PRIORITY);
260   stream2->set_stream_id(3);
261   std::unique_ptr<SpdyStream> stream3 = MakeTestStream(DEFAULT_PRIORITY);
262   stream3->set_stream_id(5);
263   // No stream id assigned.
264   std::unique_ptr<SpdyStream> stream4 = MakeTestStream(DEFAULT_PRIORITY);
265   base::WeakPtr<SpdyStream> streams[] = {
266     stream1->GetWeakPtr(), stream2->GetWeakPtr(),
267     stream3->GetWeakPtr(), stream4->GetWeakPtr()
268   };
269 
270   for (int i = 0; i < 100; ++i) {
271     write_queue.Enqueue(DEFAULT_PRIORITY, spdy::SpdyFrameType::HEADERS,
272                         IntToProducer(i), streams[i % std::size(streams)],
273                         TRAFFIC_ANNOTATION_FOR_TESTS);
274   }
275 
276   write_queue.RemovePendingWritesForStreamsAfter(stream1->stream_id());
277 
278   for (int i = 0; i < 100; i += std::size(streams)) {
279     spdy::SpdyFrameType frame_type = spdy::SpdyFrameType::DATA;
280     std::unique_ptr<SpdyBufferProducer> frame_producer;
281     base::WeakPtr<SpdyStream> stream;
282     MutableNetworkTrafficAnnotationTag traffic_annotation;
283     ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
284                                     &traffic_annotation))
285         << "Unable to Dequeue i: " << i;
286     EXPECT_EQ(spdy::SpdyFrameType::HEADERS, frame_type);
287     EXPECT_EQ(i, ProducerToInt(std::move(frame_producer)));
288     EXPECT_EQ(stream1.get(), stream.get());
289     EXPECT_EQ(MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
290               traffic_annotation);
291   }
292 
293   spdy::SpdyFrameType frame_type = spdy::SpdyFrameType::DATA;
294   std::unique_ptr<SpdyBufferProducer> frame_producer;
295   base::WeakPtr<SpdyStream> stream;
296   MutableNetworkTrafficAnnotationTag traffic_annotation;
297   EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
298                                    &traffic_annotation));
299 }
300 
301 // Enqueue a bunch of writes and then call Clear(). The write queue
302 // should clean up the memory properly, and Dequeue() should return
303 // false.
TEST_F(SpdyWriteQueueTest,Clear)304 TEST_F(SpdyWriteQueueTest, Clear) {
305   SpdyWriteQueue write_queue;
306 
307   for (int i = 0; i < 100; ++i) {
308     write_queue.Enqueue(DEFAULT_PRIORITY, spdy::SpdyFrameType::HEADERS,
309                         IntToProducer(i), base::WeakPtr<SpdyStream>(),
310                         TRAFFIC_ANNOTATION_FOR_TESTS);
311   }
312 
313   write_queue.Clear();
314 
315   spdy::SpdyFrameType frame_type = spdy::SpdyFrameType::DATA;
316   std::unique_ptr<SpdyBufferProducer> frame_producer;
317   base::WeakPtr<SpdyStream> stream;
318   MutableNetworkTrafficAnnotationTag traffic_annotation;
319   EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
320                                    &traffic_annotation));
321 }
322 
TEST_F(SpdyWriteQueueTest,RequeingProducerWithoutReentrance)323 TEST_F(SpdyWriteQueueTest, RequeingProducerWithoutReentrance) {
324   SpdyWriteQueue queue;
325   queue.Enqueue(DEFAULT_PRIORITY, spdy::SpdyFrameType::HEADERS,
326                 std::make_unique<RequeingBufferProducer>(&queue),
327                 base::WeakPtr<SpdyStream>(), TRAFFIC_ANNOTATION_FOR_TESTS);
328   {
329     spdy::SpdyFrameType frame_type;
330     std::unique_ptr<SpdyBufferProducer> producer;
331     base::WeakPtr<SpdyStream> stream;
332     MutableNetworkTrafficAnnotationTag traffic_annotation;
333 
334     EXPECT_TRUE(
335         queue.Dequeue(&frame_type, &producer, &stream, &traffic_annotation));
336     EXPECT_TRUE(queue.IsEmpty());
337     EXPECT_EQ(std::string(kOriginal),
338               producer->ProduceBuffer()->GetRemainingData());
339   }
340   // |producer| was destroyed, and a buffer is re-queued.
341   EXPECT_FALSE(queue.IsEmpty());
342 
343   spdy::SpdyFrameType frame_type;
344   std::unique_ptr<SpdyBufferProducer> producer;
345   base::WeakPtr<SpdyStream> stream;
346   MutableNetworkTrafficAnnotationTag traffic_annotation;
347 
348   EXPECT_TRUE(
349       queue.Dequeue(&frame_type, &producer, &stream, &traffic_annotation));
350   EXPECT_EQ(std::string(kRequeued),
351             producer->ProduceBuffer()->GetRemainingData());
352 }
353 
TEST_F(SpdyWriteQueueTest,ReentranceOnClear)354 TEST_F(SpdyWriteQueueTest, ReentranceOnClear) {
355   SpdyWriteQueue queue;
356   queue.Enqueue(DEFAULT_PRIORITY, spdy::SpdyFrameType::HEADERS,
357                 std::make_unique<RequeingBufferProducer>(&queue),
358                 base::WeakPtr<SpdyStream>(), TRAFFIC_ANNOTATION_FOR_TESTS);
359 
360   queue.Clear();
361   EXPECT_FALSE(queue.IsEmpty());
362 
363   spdy::SpdyFrameType frame_type;
364   std::unique_ptr<SpdyBufferProducer> producer;
365   base::WeakPtr<SpdyStream> stream;
366   MutableNetworkTrafficAnnotationTag traffic_annotation;
367 
368   EXPECT_TRUE(
369       queue.Dequeue(&frame_type, &producer, &stream, &traffic_annotation));
370   EXPECT_EQ(std::string(kRequeued),
371             producer->ProduceBuffer()->GetRemainingData());
372 }
373 
TEST_F(SpdyWriteQueueTest,ReentranceOnRemovePendingWritesAfter)374 TEST_F(SpdyWriteQueueTest, ReentranceOnRemovePendingWritesAfter) {
375   std::unique_ptr<SpdyStream> stream = MakeTestStream(DEFAULT_PRIORITY);
376   stream->set_stream_id(2);
377 
378   SpdyWriteQueue queue;
379   queue.Enqueue(DEFAULT_PRIORITY, spdy::SpdyFrameType::HEADERS,
380                 std::make_unique<RequeingBufferProducer>(&queue),
381                 stream->GetWeakPtr(), TRAFFIC_ANNOTATION_FOR_TESTS);
382 
383   queue.RemovePendingWritesForStreamsAfter(1);
384   EXPECT_FALSE(queue.IsEmpty());
385 
386   spdy::SpdyFrameType frame_type;
387   std::unique_ptr<SpdyBufferProducer> producer;
388   base::WeakPtr<SpdyStream> weak_stream;
389   MutableNetworkTrafficAnnotationTag traffic_annotation;
390 
391   EXPECT_TRUE(
392       queue.Dequeue(&frame_type, &producer, &weak_stream, &traffic_annotation));
393   EXPECT_EQ(std::string(kRequeued),
394             producer->ProduceBuffer()->GetRemainingData());
395 }
396 
TEST_F(SpdyWriteQueueTest,ReentranceOnRemovePendingWritesForStream)397 TEST_F(SpdyWriteQueueTest, ReentranceOnRemovePendingWritesForStream) {
398   std::unique_ptr<SpdyStream> stream = MakeTestStream(DEFAULT_PRIORITY);
399   stream->set_stream_id(2);
400 
401   SpdyWriteQueue queue;
402   queue.Enqueue(DEFAULT_PRIORITY, spdy::SpdyFrameType::HEADERS,
403                 std::make_unique<RequeingBufferProducer>(&queue),
404                 stream->GetWeakPtr(), TRAFFIC_ANNOTATION_FOR_TESTS);
405 
406   queue.RemovePendingWritesForStream(stream.get());
407   EXPECT_FALSE(queue.IsEmpty());
408 
409   spdy::SpdyFrameType frame_type;
410   std::unique_ptr<SpdyBufferProducer> producer;
411   base::WeakPtr<SpdyStream> weak_stream;
412   MutableNetworkTrafficAnnotationTag traffic_annotation;
413 
414   EXPECT_TRUE(
415       queue.Dequeue(&frame_type, &producer, &weak_stream, &traffic_annotation));
416   EXPECT_EQ(std::string(kRequeued),
417             producer->ProduceBuffer()->GetRemainingData());
418 }
419 
TEST_F(SpdyWriteQueueTest,ChangePriority)420 TEST_F(SpdyWriteQueueTest, ChangePriority) {
421   SpdyWriteQueue write_queue;
422 
423   std::unique_ptr<SpdyBufferProducer> producer1 = IntToProducer(1);
424   std::unique_ptr<SpdyBufferProducer> producer2 = IntToProducer(2);
425   std::unique_ptr<SpdyBufferProducer> producer3 = IntToProducer(3);
426 
427   std::unique_ptr<SpdyStream> stream1 = MakeTestStream(HIGHEST);
428   std::unique_ptr<SpdyStream> stream2 = MakeTestStream(MEDIUM);
429   std::unique_ptr<SpdyStream> stream3 = MakeTestStream(LOW);
430 
431   write_queue.Enqueue(HIGHEST, spdy::SpdyFrameType::HEADERS,
432                       std::move(producer1), stream1->GetWeakPtr(),
433                       TRAFFIC_ANNOTATION_FOR_TESTS);
434   write_queue.Enqueue(MEDIUM, spdy::SpdyFrameType::DATA, std::move(producer2),
435                       stream2->GetWeakPtr(), TRAFFIC_ANNOTATION_FOR_TESTS);
436   write_queue.Enqueue(LOW, spdy::SpdyFrameType::RST_STREAM,
437                       std::move(producer3), stream3->GetWeakPtr(),
438                       TRAFFIC_ANNOTATION_FOR_TESTS);
439 
440   write_queue.ChangePriorityOfWritesForStream(stream3.get(), LOW, HIGHEST);
441 
442   spdy::SpdyFrameType frame_type = spdy::SpdyFrameType::DATA;
443   std::unique_ptr<SpdyBufferProducer> frame_producer;
444   base::WeakPtr<SpdyStream> stream;
445   MutableNetworkTrafficAnnotationTag traffic_annotation;
446   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
447                                   &traffic_annotation));
448   EXPECT_EQ(spdy::SpdyFrameType::HEADERS, frame_type);
449   EXPECT_EQ(1, ProducerToInt(std::move(frame_producer)));
450   EXPECT_EQ(stream1.get(), stream.get());
451 
452   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
453                                   &traffic_annotation));
454   EXPECT_EQ(spdy::SpdyFrameType::RST_STREAM, frame_type);
455   EXPECT_EQ(3, ProducerToInt(std::move(frame_producer)));
456   EXPECT_EQ(stream3.get(), stream.get());
457 
458   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
459                                   &traffic_annotation));
460   EXPECT_EQ(spdy::SpdyFrameType::DATA, frame_type);
461   EXPECT_EQ(2, ProducerToInt(std::move(frame_producer)));
462   EXPECT_EQ(stream2.get(), stream.get());
463 
464   EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream,
465                                    &traffic_annotation));
466 }
467 
468 }  // namespace
469 
470 }  // namespace net
471