- add sources.
[platform/framework/web/crosswalk.git] / src / net / spdy / spdy_write_queue_unittest.cc
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_buffer_producer.h"
18 #include "net/spdy/spdy_stream.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "url/gurl.h"
21
22 namespace net {
23
24 namespace {
25
26 class SpdyWriteQueueTest : public ::testing::Test {};
27
28 // Makes a SpdyFrameProducer producing a frame with the data in the
29 // given string.
30 scoped_ptr<SpdyBufferProducer> StringToProducer(const std::string& s) {
31   scoped_ptr<char[]> data(new char[s.size()]);
32   std::memcpy(data.get(), s.data(), s.size());
33   return scoped_ptr<SpdyBufferProducer>(
34       new SimpleBufferProducer(
35           scoped_ptr<SpdyBuffer>(
36               new SpdyBuffer(
37                   scoped_ptr<SpdyFrame>(
38                       new SpdyFrame(data.release(), s.size(), true))))));
39 }
40
41 // Makes a SpdyBufferProducer producing a frame with the data in the
42 // given int (converted to a string).
43 scoped_ptr<SpdyBufferProducer> IntToProducer(int i) {
44   return StringToProducer(base::IntToString(i));
45 }
46
47 // Produces a frame with the given producer and returns a copy of its
48 // data as a string.
49 std::string ProducerToString(scoped_ptr<SpdyBufferProducer> producer) {
50   scoped_ptr<SpdyBuffer> buffer = producer->ProduceBuffer();
51   return std::string(buffer->GetRemainingData(), buffer->GetRemainingSize());
52 }
53
54 // Produces a frame with the given producer and returns a copy of its
55 // data as an int (converted from a string).
56 int ProducerToInt(scoped_ptr<SpdyBufferProducer> producer) {
57   int i = 0;
58   EXPECT_TRUE(base::StringToInt(ProducerToString(producer.Pass()), &i));
59   return i;
60 }
61
62 // Makes a SpdyStream with the given priority and a NULL SpdySession
63 // -- be careful to not call any functions that expect the session to
64 // be there.
65 SpdyStream* MakeTestStream(RequestPriority priority) {
66   return new SpdyStream(
67       SPDY_BIDIRECTIONAL_STREAM, base::WeakPtr<SpdySession>(),
68       GURL(), priority, 0, 0, BoundNetLog());
69 }
70
71 // Add some frame producers of different priority. The producers
72 // should be dequeued in priority order with their associated stream.
73 TEST_F(SpdyWriteQueueTest, DequeuesByPriority) {
74   SpdyWriteQueue write_queue;
75
76   scoped_ptr<SpdyBufferProducer> producer_low = StringToProducer("LOW");
77   scoped_ptr<SpdyBufferProducer> producer_medium = StringToProducer("MEDIUM");
78   scoped_ptr<SpdyBufferProducer> producer_highest = StringToProducer("HIGHEST");
79
80   scoped_ptr<SpdyStream> stream_medium(MakeTestStream(MEDIUM));
81   scoped_ptr<SpdyStream> stream_highest(MakeTestStream(HIGHEST));
82
83   // A NULL stream should still work.
84   write_queue.Enqueue(
85       LOW, SYN_STREAM, producer_low.Pass(), base::WeakPtr<SpdyStream>());
86   write_queue.Enqueue(
87       MEDIUM, SYN_REPLY, producer_medium.Pass(), stream_medium->GetWeakPtr());
88   write_queue.Enqueue(
89       HIGHEST, RST_STREAM, producer_highest.Pass(),
90       stream_highest->GetWeakPtr());
91
92   SpdyFrameType frame_type = DATA;
93   scoped_ptr<SpdyBufferProducer> frame_producer;
94   base::WeakPtr<SpdyStream> stream;
95   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
96   EXPECT_EQ(RST_STREAM, frame_type);
97   EXPECT_EQ("HIGHEST", ProducerToString(frame_producer.Pass()));
98   EXPECT_EQ(stream_highest, stream.get());
99
100   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
101   EXPECT_EQ(SYN_REPLY, frame_type);
102   EXPECT_EQ("MEDIUM", ProducerToString(frame_producer.Pass()));
103   EXPECT_EQ(stream_medium, stream.get());
104
105   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
106   EXPECT_EQ(SYN_STREAM, frame_type);
107   EXPECT_EQ("LOW", ProducerToString(frame_producer.Pass()));
108   EXPECT_EQ(NULL, stream.get());
109
110   EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
111 }
112
113 // Add some frame producers with the same priority. The producers
114 // should be dequeued in FIFO order with their associated stream.
115 TEST_F(SpdyWriteQueueTest, DequeuesFIFO) {
116   SpdyWriteQueue write_queue;
117
118   scoped_ptr<SpdyBufferProducer> producer1 = IntToProducer(1);
119   scoped_ptr<SpdyBufferProducer> producer2 = IntToProducer(2);
120   scoped_ptr<SpdyBufferProducer> producer3 = IntToProducer(3);
121
122   scoped_ptr<SpdyStream> stream1(MakeTestStream(DEFAULT_PRIORITY));
123   scoped_ptr<SpdyStream> stream2(MakeTestStream(DEFAULT_PRIORITY));
124   scoped_ptr<SpdyStream> stream3(MakeTestStream(DEFAULT_PRIORITY));
125
126   write_queue.Enqueue(DEFAULT_PRIORITY, SYN_STREAM, producer1.Pass(),
127                       stream1->GetWeakPtr());
128   write_queue.Enqueue(DEFAULT_PRIORITY, SYN_REPLY, producer2.Pass(),
129                       stream2->GetWeakPtr());
130   write_queue.Enqueue(DEFAULT_PRIORITY, RST_STREAM, producer3.Pass(),
131                       stream3->GetWeakPtr());
132
133   SpdyFrameType frame_type = DATA;
134   scoped_ptr<SpdyBufferProducer> frame_producer;
135   base::WeakPtr<SpdyStream> stream;
136   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
137   EXPECT_EQ(SYN_STREAM, frame_type);
138   EXPECT_EQ(1, ProducerToInt(frame_producer.Pass()));
139   EXPECT_EQ(stream1, stream.get());
140
141   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
142   EXPECT_EQ(SYN_REPLY, frame_type);
143   EXPECT_EQ(2, ProducerToInt(frame_producer.Pass()));
144   EXPECT_EQ(stream2, stream.get());
145
146   ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
147   EXPECT_EQ(RST_STREAM, frame_type);
148   EXPECT_EQ(3, ProducerToInt(frame_producer.Pass()));
149   EXPECT_EQ(stream3, stream.get());
150
151   EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
152 }
153
154 // Enqueue a bunch of writes and then call
155 // RemovePendingWritesForStream() on one of the streams. No dequeued
156 // write should be for that stream.
157 TEST_F(SpdyWriteQueueTest, RemovePendingWritesForStream) {
158   SpdyWriteQueue write_queue;
159
160   scoped_ptr<SpdyStream> stream1(MakeTestStream(DEFAULT_PRIORITY));
161   scoped_ptr<SpdyStream> stream2(MakeTestStream(DEFAULT_PRIORITY));
162
163   for (int i = 0; i < 100; ++i) {
164     base::WeakPtr<SpdyStream> stream =
165         (((i % 3) == 0) ? stream1 : stream2)->GetWeakPtr();
166     write_queue.Enqueue(DEFAULT_PRIORITY, SYN_STREAM, IntToProducer(i), stream);
167   }
168
169   write_queue.RemovePendingWritesForStream(stream2->GetWeakPtr());
170
171   for (int i = 0; i < 100; i += 3) {
172     SpdyFrameType frame_type = DATA;
173     scoped_ptr<SpdyBufferProducer> frame_producer;
174     base::WeakPtr<SpdyStream> stream;
175     ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
176     EXPECT_EQ(SYN_STREAM, frame_type);
177     EXPECT_EQ(i, ProducerToInt(frame_producer.Pass()));
178     EXPECT_EQ(stream1, stream.get());
179   }
180
181   SpdyFrameType frame_type = DATA;
182   scoped_ptr<SpdyBufferProducer> frame_producer;
183   base::WeakPtr<SpdyStream> stream;
184   EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
185 }
186
187 // Enqueue a bunch of writes and then call
188 // RemovePendingWritesForStreamsAfter(). No dequeued write should be for
189 // those streams without a stream id, or with a stream_id after that
190 // argument.
191 TEST_F(SpdyWriteQueueTest, RemovePendingWritesForStreamsAfter) {
192   SpdyWriteQueue write_queue;
193
194   scoped_ptr<SpdyStream> stream1(MakeTestStream(DEFAULT_PRIORITY));
195   stream1->set_stream_id(1);
196   scoped_ptr<SpdyStream> stream2(MakeTestStream(DEFAULT_PRIORITY));
197   stream2->set_stream_id(3);
198   scoped_ptr<SpdyStream> stream3(MakeTestStream(DEFAULT_PRIORITY));
199   stream3->set_stream_id(5);
200   // No stream id assigned.
201   scoped_ptr<SpdyStream> stream4(MakeTestStream(DEFAULT_PRIORITY));
202   base::WeakPtr<SpdyStream> streams[] = {
203     stream1->GetWeakPtr(), stream2->GetWeakPtr(),
204     stream3->GetWeakPtr(), stream4->GetWeakPtr()
205   };
206
207   for (int i = 0; i < 100; ++i) {
208     write_queue.Enqueue(DEFAULT_PRIORITY, SYN_STREAM, IntToProducer(i),
209                         streams[i % arraysize(streams)]);
210   }
211
212   write_queue.RemovePendingWritesForStreamsAfter(stream1->stream_id());
213
214   for (int i = 0; i < 100; i += arraysize(streams)) {
215     SpdyFrameType frame_type = DATA;
216     scoped_ptr<SpdyBufferProducer> frame_producer;
217     base::WeakPtr<SpdyStream> stream;
218     ASSERT_TRUE(write_queue.Dequeue(&frame_type, &frame_producer, &stream))
219         << "Unable to Dequeue i: " << i;
220     EXPECT_EQ(SYN_STREAM, frame_type);
221     EXPECT_EQ(i, ProducerToInt(frame_producer.Pass()));
222     EXPECT_EQ(stream1, stream.get());
223   }
224
225   SpdyFrameType frame_type = DATA;
226   scoped_ptr<SpdyBufferProducer> frame_producer;
227   base::WeakPtr<SpdyStream> stream;
228   EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
229 }
230
231 // Enqueue a bunch of writes and then call Clear(). The write queue
232 // should clean up the memory properly, and Dequeue() should return
233 // false.
234 TEST_F(SpdyWriteQueueTest, Clear) {
235   SpdyWriteQueue write_queue;
236
237   for (int i = 0; i < 100; ++i) {
238     write_queue.Enqueue(DEFAULT_PRIORITY, SYN_STREAM, IntToProducer(i),
239                         base::WeakPtr<SpdyStream>());
240   }
241
242   write_queue.Clear();
243
244   SpdyFrameType frame_type = DATA;
245   scoped_ptr<SpdyBufferProducer> frame_producer;
246   base::WeakPtr<SpdyStream> stream;
247   EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
248 }
249
250 }  // namespace
251
252 }  // namespace net