• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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/server/http_connection.h"
11 
12 #include <string>
13 #include <string_view>
14 
15 #include "base/memory/ref_counted.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace net {
19 namespace {
20 
GetTestString(int size)21 std::string GetTestString(int size) {
22   std::string test_string;
23   for (int i = 0; i < size; ++i) {
24     test_string.push_back('A' + (i % 26));
25   }
26   return test_string;
27 }
28 
TEST(HttpConnectionTest,ReadIOBuffer_SetCapacity)29 TEST(HttpConnectionTest, ReadIOBuffer_SetCapacity) {
30   scoped_refptr<HttpConnection::ReadIOBuffer> buffer =
31       base::MakeRefCounted<HttpConnection::ReadIOBuffer>();
32   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize + 0,
33             buffer->GetCapacity());
34   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize + 0,
35             buffer->RemainingCapacity());
36   EXPECT_EQ(0, buffer->GetSize());
37 
38   const int kNewCapacity = HttpConnection::ReadIOBuffer::kInitialBufSize + 128;
39   buffer->SetCapacity(kNewCapacity);
40   EXPECT_EQ(kNewCapacity, buffer->GetCapacity());
41   EXPECT_EQ(kNewCapacity, buffer->RemainingCapacity());
42   EXPECT_EQ(0, buffer->GetSize());
43 }
44 
TEST(HttpConnectionTest,ReadIOBuffer_SetCapacity_WithData)45 TEST(HttpConnectionTest, ReadIOBuffer_SetCapacity_WithData) {
46   scoped_refptr<HttpConnection::ReadIOBuffer> buffer =
47       base::MakeRefCounted<HttpConnection::ReadIOBuffer>();
48   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize + 0,
49             buffer->GetCapacity());
50   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize + 0,
51             buffer->RemainingCapacity());
52 
53   // Write arbitrary data up to kInitialBufSize.
54   const std::string kReadData(
55       GetTestString(HttpConnection::ReadIOBuffer::kInitialBufSize));
56   memcpy(buffer->data(), kReadData.data(), kReadData.size());
57   buffer->DidRead(kReadData.size());
58   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize + 0,
59             buffer->GetCapacity());
60   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize -
61                 static_cast<int>(kReadData.size()),
62             buffer->RemainingCapacity());
63   EXPECT_EQ(static_cast<int>(kReadData.size()), buffer->GetSize());
64   EXPECT_EQ(kReadData,
65             std::string_view(buffer->StartOfBuffer(), buffer->GetSize()));
66 
67   // Check if read data in the buffer is same after SetCapacity().
68   const int kNewCapacity = HttpConnection::ReadIOBuffer::kInitialBufSize + 128;
69   buffer->SetCapacity(kNewCapacity);
70   EXPECT_EQ(kNewCapacity, buffer->GetCapacity());
71   EXPECT_EQ(kNewCapacity - static_cast<int>(kReadData.size()),
72             buffer->RemainingCapacity());
73   EXPECT_EQ(static_cast<int>(kReadData.size()), buffer->GetSize());
74   EXPECT_EQ(kReadData,
75             std::string_view(buffer->StartOfBuffer(), buffer->GetSize()));
76 }
77 
TEST(HttpConnectionTest,ReadIOBuffer_IncreaseCapacity)78 TEST(HttpConnectionTest, ReadIOBuffer_IncreaseCapacity) {
79   scoped_refptr<HttpConnection::ReadIOBuffer> buffer =
80       base::MakeRefCounted<HttpConnection::ReadIOBuffer>();
81   EXPECT_TRUE(buffer->IncreaseCapacity());
82   const int kExpectedInitialBufSize =
83       HttpConnection::ReadIOBuffer::kInitialBufSize *
84       HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor;
85   EXPECT_EQ(kExpectedInitialBufSize, buffer->GetCapacity());
86   EXPECT_EQ(kExpectedInitialBufSize, buffer->RemainingCapacity());
87   EXPECT_EQ(0, buffer->GetSize());
88 
89   // Increase capacity until it fails.
90   while (buffer->IncreaseCapacity());
91   EXPECT_FALSE(buffer->IncreaseCapacity());
92   EXPECT_EQ(HttpConnection::ReadIOBuffer::kDefaultMaxBufferSize + 0,
93             buffer->max_buffer_size());
94   EXPECT_EQ(HttpConnection::ReadIOBuffer::kDefaultMaxBufferSize + 0,
95             buffer->GetCapacity());
96 
97   // Enlarge capacity limit.
98   buffer->set_max_buffer_size(buffer->max_buffer_size() * 2);
99   EXPECT_TRUE(buffer->IncreaseCapacity());
100   EXPECT_EQ(HttpConnection::ReadIOBuffer::kDefaultMaxBufferSize *
101                 HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor,
102             buffer->GetCapacity());
103 
104   // Shrink capacity limit. It doesn't change capacity itself.
105   buffer->set_max_buffer_size(
106       HttpConnection::ReadIOBuffer::kDefaultMaxBufferSize / 2);
107   EXPECT_FALSE(buffer->IncreaseCapacity());
108   EXPECT_EQ(HttpConnection::ReadIOBuffer::kDefaultMaxBufferSize *
109                 HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor,
110             buffer->GetCapacity());
111 }
112 
TEST(HttpConnectionTest,ReadIOBuffer_IncreaseCapacity_WithData)113 TEST(HttpConnectionTest, ReadIOBuffer_IncreaseCapacity_WithData) {
114   scoped_refptr<HttpConnection::ReadIOBuffer> buffer =
115       base::MakeRefCounted<HttpConnection::ReadIOBuffer>();
116   EXPECT_TRUE(buffer->IncreaseCapacity());
117   const int kExpectedInitialBufSize =
118       HttpConnection::ReadIOBuffer::kInitialBufSize *
119       HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor;
120   EXPECT_EQ(kExpectedInitialBufSize, buffer->GetCapacity());
121   EXPECT_EQ(kExpectedInitialBufSize, buffer->RemainingCapacity());
122   EXPECT_EQ(0, buffer->GetSize());
123 
124   // Write arbitrary data up to kExpectedInitialBufSize.
125   std::string kReadData(GetTestString(kExpectedInitialBufSize));
126   memcpy(buffer->data(), kReadData.data(), kReadData.size());
127   buffer->DidRead(kReadData.size());
128   EXPECT_EQ(kExpectedInitialBufSize, buffer->GetCapacity());
129   EXPECT_EQ(kExpectedInitialBufSize - static_cast<int>(kReadData.size()),
130             buffer->RemainingCapacity());
131   EXPECT_EQ(static_cast<int>(kReadData.size()), buffer->GetSize());
132   EXPECT_EQ(kReadData,
133             std::string_view(buffer->StartOfBuffer(), buffer->GetSize()));
134 
135   // Increase capacity until it fails and check if read data in the buffer is
136   // same.
137   while (buffer->IncreaseCapacity());
138   EXPECT_FALSE(buffer->IncreaseCapacity());
139   EXPECT_EQ(HttpConnection::ReadIOBuffer::kDefaultMaxBufferSize + 0,
140             buffer->max_buffer_size());
141   EXPECT_EQ(HttpConnection::ReadIOBuffer::kDefaultMaxBufferSize + 0,
142             buffer->GetCapacity());
143   EXPECT_EQ(HttpConnection::ReadIOBuffer::kDefaultMaxBufferSize -
144                 static_cast<int>(kReadData.size()),
145             buffer->RemainingCapacity());
146   EXPECT_EQ(static_cast<int>(kReadData.size()), buffer->GetSize());
147   EXPECT_EQ(kReadData,
148             std::string_view(buffer->StartOfBuffer(), buffer->GetSize()));
149 }
150 
TEST(HttpConnectionTest,ReadIOBuffer_DidRead_DidConsume)151 TEST(HttpConnectionTest, ReadIOBuffer_DidRead_DidConsume) {
152   scoped_refptr<HttpConnection::ReadIOBuffer> buffer =
153       base::MakeRefCounted<HttpConnection::ReadIOBuffer>();
154   const char* start_of_buffer = buffer->StartOfBuffer();
155   EXPECT_EQ(start_of_buffer, buffer->data());
156 
157   // Read data.
158   const int kReadLength = 128;
159   const std::string kReadData(GetTestString(kReadLength));
160   memcpy(buffer->data(), kReadData.data(), kReadLength);
161   buffer->DidRead(kReadLength);
162   // No change in total capacity.
163   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize + 0,
164             buffer->GetCapacity());
165   // Change in unused capacity because of read data.
166   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize - kReadLength,
167             buffer->RemainingCapacity());
168   EXPECT_EQ(kReadLength, buffer->GetSize());
169   // No change in start pointers of read data.
170   EXPECT_EQ(start_of_buffer, buffer->StartOfBuffer());
171   // Change in start pointer of unused buffer.
172   EXPECT_EQ(start_of_buffer + kReadLength, buffer->data());
173   // Test read data.
174   EXPECT_EQ(kReadData, std::string(buffer->StartOfBuffer(), buffer->GetSize()));
175 
176   // Consume data partially.
177   const int kConsumedLength = 32;
178   ASSERT_LT(kConsumedLength, kReadLength);
179   buffer->DidConsume(kConsumedLength);
180   // Capacity reduced because read data was too small comparing to capacity.
181   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize /
182                 HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor,
183             buffer->GetCapacity());
184   // Change in unused capacity because of read data.
185   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize /
186                 HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor -
187                 kReadLength + kConsumedLength,
188             buffer->RemainingCapacity());
189   // Change in read size.
190   EXPECT_EQ(kReadLength - kConsumedLength, buffer->GetSize());
191   // Start data could be changed even when capacity is reduced.
192   start_of_buffer = buffer->StartOfBuffer();
193   // Change in start pointer of unused buffer.
194   EXPECT_EQ(start_of_buffer + kReadLength - kConsumedLength, buffer->data());
195   // Change in read data.
196   EXPECT_EQ(kReadData.substr(kConsumedLength),
197             std::string(buffer->StartOfBuffer(), buffer->GetSize()));
198 
199   // Read more data.
200   const int kReadLength2 = 64;
201   buffer->DidRead(kReadLength2);
202   // No change in total capacity.
203   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize /
204                 HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor,
205             buffer->GetCapacity());
206   // Change in unused capacity because of read data.
207   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize /
208                 HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor -
209                 kReadLength + kConsumedLength - kReadLength2,
210             buffer->RemainingCapacity());
211   // Change in read size
212   EXPECT_EQ(kReadLength - kConsumedLength + kReadLength2, buffer->GetSize());
213   // No change in start pointer of read part.
214   EXPECT_EQ(start_of_buffer, buffer->StartOfBuffer());
215   // Change in start pointer of unused buffer.
216   EXPECT_EQ(start_of_buffer + kReadLength - kConsumedLength + kReadLength2,
217             buffer->data());
218 
219   // Consume data fully.
220   buffer->DidConsume(kReadLength - kConsumedLength + kReadLength2);
221   // Capacity reduced again because read data was too small.
222   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize /
223                 HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor /
224                 HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor,
225             buffer->GetCapacity());
226   EXPECT_EQ(HttpConnection::ReadIOBuffer::kInitialBufSize /
227                 HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor /
228                 HttpConnection::ReadIOBuffer::kCapacityIncreaseFactor,
229             buffer->RemainingCapacity());
230   // All reverts to initial because no data is left.
231   EXPECT_EQ(0, buffer->GetSize());
232   // Start data could be changed even when capacity is reduced.
233   start_of_buffer = buffer->StartOfBuffer();
234   EXPECT_EQ(start_of_buffer, buffer->data());
235 }
236 
TEST(HttpConnectionTest,QueuedWriteIOBuffer_Append_DidConsume)237 TEST(HttpConnectionTest, QueuedWriteIOBuffer_Append_DidConsume) {
238   scoped_refptr<HttpConnection::QueuedWriteIOBuffer> buffer =
239       base::MakeRefCounted<HttpConnection::QueuedWriteIOBuffer>();
240   EXPECT_TRUE(buffer->IsEmpty());
241   EXPECT_EQ(0, buffer->GetSizeToWrite());
242   EXPECT_EQ(0, buffer->total_size());
243 
244   const std::string kData("data to write");
245   EXPECT_TRUE(buffer->Append(kData));
246   EXPECT_FALSE(buffer->IsEmpty());
247   EXPECT_EQ(static_cast<int>(kData.size()), buffer->GetSizeToWrite());
248   EXPECT_EQ(static_cast<int>(kData.size()), buffer->total_size());
249   // First data to write is same to kData.
250   EXPECT_EQ(kData, std::string_view(buffer->data(), buffer->GetSizeToWrite()));
251 
252   const std::string kData2("more data to write");
253   EXPECT_TRUE(buffer->Append(kData2));
254   EXPECT_FALSE(buffer->IsEmpty());
255   // No change in size to write.
256   EXPECT_EQ(static_cast<int>(kData.size()), buffer->GetSizeToWrite());
257   // Change in total size.
258   EXPECT_EQ(static_cast<int>(kData.size() + kData2.size()),
259             buffer->total_size());
260   // First data to write has not been changed. Same to kData.
261   EXPECT_EQ(kData, std::string_view(buffer->data(), buffer->GetSizeToWrite()));
262 
263   // Consume data partially.
264   const int kConsumedLength = kData.length() - 1;
265   buffer->DidConsume(kConsumedLength);
266   EXPECT_FALSE(buffer->IsEmpty());
267   // Change in size to write.
268   EXPECT_EQ(static_cast<int>(kData.size()) - kConsumedLength,
269             buffer->GetSizeToWrite());
270   // Change in total size.
271   EXPECT_EQ(static_cast<int>(kData.size() + kData2.size()) - kConsumedLength,
272             buffer->total_size());
273   // First data to write has shrinked.
274   EXPECT_EQ(kData.substr(kConsumedLength),
275             std::string_view(buffer->data(), buffer->GetSizeToWrite()));
276 
277   // Consume first data fully.
278   buffer->DidConsume(kData.size() - kConsumedLength);
279   EXPECT_FALSE(buffer->IsEmpty());
280   // Now, size to write is size of data added second.
281   EXPECT_EQ(static_cast<int>(kData2.size()), buffer->GetSizeToWrite());
282   // Change in total size.
283   EXPECT_EQ(static_cast<int>(kData2.size()), buffer->total_size());
284   // First data to write has changed to kData2.
285   EXPECT_EQ(kData2, std::string_view(buffer->data(), buffer->GetSizeToWrite()));
286 
287   // Consume second data fully.
288   buffer->DidConsume(kData2.size());
289   EXPECT_TRUE(buffer->IsEmpty());
290   EXPECT_EQ(0, buffer->GetSizeToWrite());
291   EXPECT_EQ(0, buffer->total_size());
292 }
293 
TEST(HttpConnectionTest,QueuedWriteIOBuffer_TotalSizeLimit)294 TEST(HttpConnectionTest, QueuedWriteIOBuffer_TotalSizeLimit) {
295   scoped_refptr<HttpConnection::QueuedWriteIOBuffer> buffer =
296       base::MakeRefCounted<HttpConnection::QueuedWriteIOBuffer>();
297   EXPECT_EQ(HttpConnection::QueuedWriteIOBuffer::kDefaultMaxBufferSize + 0,
298             buffer->max_buffer_size());
299 
300   // Set total size limit very small.
301   buffer->set_max_buffer_size(10);
302 
303   const int kDataLength = 4;
304   const std::string kData(kDataLength, 'd');
305   EXPECT_TRUE(buffer->Append(kData));
306   EXPECT_EQ(kDataLength, buffer->total_size());
307   EXPECT_TRUE(buffer->Append(kData));
308   EXPECT_EQ(kDataLength * 2, buffer->total_size());
309 
310   // Cannot append more data because it exceeds the limit.
311   EXPECT_FALSE(buffer->Append(kData));
312   EXPECT_EQ(kDataLength * 2, buffer->total_size());
313 
314   // Consume data partially.
315   const int kConsumedLength = 2;
316   buffer->DidConsume(kConsumedLength);
317   EXPECT_EQ(kDataLength * 2 - kConsumedLength, buffer->total_size());
318 
319   // Can add more data.
320   EXPECT_TRUE(buffer->Append(kData));
321   EXPECT_EQ(kDataLength * 3 - kConsumedLength, buffer->total_size());
322 
323   // Cannot append more data because it exceeds the limit.
324   EXPECT_FALSE(buffer->Append(kData));
325   EXPECT_EQ(kDataLength * 3 - kConsumedLength, buffer->total_size());
326 
327   // Enlarge limit.
328   buffer->set_max_buffer_size(20);
329   // Can add more data.
330   EXPECT_TRUE(buffer->Append(kData));
331   EXPECT_EQ(kDataLength * 4 - kConsumedLength, buffer->total_size());
332 }
333 
TEST(HttpConnectionTest,QueuedWriteIOBuffer_DataPointerStability)334 TEST(HttpConnectionTest, QueuedWriteIOBuffer_DataPointerStability) {
335   // This is a regression test that makes sure that QueuedWriteIOBuffer deals
336   // with base::queue's semantics differences vs. std::queue right, and still
337   // makes sure our data() pointers are stable.
338   scoped_refptr<HttpConnection::QueuedWriteIOBuffer> buffer =
339       base::MakeRefCounted<HttpConnection::QueuedWriteIOBuffer>();
340 
341   // We append a short string to make it fit within any short string
342   // optimization, so that if the underlying queue moves the std::string,
343   // the data should change.
344   buffer->Append("abcdefgh");
345 
346   // Read part of it, to make sure this handles the case of data() pointing
347   // to something other than start of string right.
348   buffer->DidConsume(3);
349   const char* old_data = buffer->data();
350   EXPECT_EQ("defgh", std::string_view(buffer->data(), 5));
351 
352   // Now append a whole bunch of other things to make the underlying queue
353   // grow, and likely need to move stuff around in memory.
354   for (int i = 0; i < 256; ++i)
355     buffer->Append("some other string data");
356 
357   // data() should still be right.
358   EXPECT_EQ("defgh", std::string_view(buffer->data(), 5));
359 
360   // ... it should also be bitwise the same, since the IOBuffer can get passed
361   // to async calls and then have Append's come in.
362   EXPECT_TRUE(buffer->data() == old_data);
363 }
364 
365 }  // namespace
366 }  // namespace net
367