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