1 // Copyright 2022 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 "quiche/balsa/simple_buffer.h"
6
7 #include <string>
8
9 #include "absl/strings/string_view.h"
10 #include "quiche/common/platform/api/quiche_expect_bug.h"
11 #include "quiche/common/platform/api/quiche_test.h"
12
13 namespace quiche {
14
15 namespace test {
16
17 namespace {
18
19 constexpr int kMinimumSimpleBufferSize = 10;
20
21 // Buffer full of 40 char strings.
22 const char ibuf[] = {
23 "123456789!@#$%^&*()abcdefghijklmnopqrstu"
24 "123456789!@#$%^&*()abcdefghijklmnopqrstu"
25 "123456789!@#$%^&*()abcdefghijklmnopqrstu"
26 "123456789!@#$%^&*()abcdefghijklmnopqrstu"
27 "123456789!@#$%^&*()abcdefghijklmnopqrstu"};
28
29 } // namespace
30
31 class SimpleBufferTest : public QuicheTest {
32 public:
storage(SimpleBuffer & buffer)33 static char* storage(SimpleBuffer& buffer) { return buffer.storage_; }
write_idx(SimpleBuffer & buffer)34 static int write_idx(SimpleBuffer& buffer) { return buffer.write_idx_; }
read_idx(SimpleBuffer & buffer)35 static int read_idx(SimpleBuffer& buffer) { return buffer.read_idx_; }
storage_size(SimpleBuffer & buffer)36 static int storage_size(SimpleBuffer& buffer) { return buffer.storage_size_; }
37 };
38
39 namespace {
40
TEST_F(SimpleBufferTest,CreationWithSize)41 TEST_F(SimpleBufferTest, CreationWithSize) {
42 SimpleBuffer buffer1(5);
43 EXPECT_EQ(kMinimumSimpleBufferSize, storage_size(buffer1));
44
45 SimpleBuffer buffer2(25);
46 EXPECT_EQ(25, storage_size(buffer2));
47 }
48
49 // Make sure that a zero-sized initial buffer does not throw things off.
TEST_F(SimpleBufferTest,CreationWithZeroSize)50 TEST_F(SimpleBufferTest, CreationWithZeroSize) {
51 SimpleBuffer buffer(0);
52 EXPECT_EQ(0, storage_size(buffer));
53 EXPECT_EQ(4, buffer.Write(ibuf, 4));
54 EXPECT_EQ(4, write_idx(buffer));
55 EXPECT_EQ(kMinimumSimpleBufferSize, storage_size(buffer));
56 EXPECT_EQ(4, buffer.ReadableBytes());
57 }
58
TEST_F(SimpleBufferTest,ReadZeroBytes)59 TEST_F(SimpleBufferTest, ReadZeroBytes) {
60 SimpleBuffer buffer;
61
62 EXPECT_EQ(0, buffer.Read(nullptr, 0));
63 }
64
TEST_F(SimpleBufferTest,WriteZeroFromNullptr)65 TEST_F(SimpleBufferTest, WriteZeroFromNullptr) {
66 SimpleBuffer buffer;
67
68 EXPECT_EQ(0, buffer.Write(nullptr, 0));
69 }
70
TEST(SimpleBufferExpectBug,ReserveNegativeSize)71 TEST(SimpleBufferExpectBug, ReserveNegativeSize) {
72 SimpleBuffer buffer;
73
74 EXPECT_QUICHE_BUG(buffer.Reserve(-1), "size must not be negative");
75 }
76
TEST(SimpleBufferExpectBug,ReadNegativeSize)77 TEST(SimpleBufferExpectBug, ReadNegativeSize) {
78 SimpleBuffer buffer;
79
80 EXPECT_QUICHE_BUG(buffer.Read(nullptr, -1), "size must not be negative");
81 }
82
TEST(SimpleBufferExpectBug,WriteNegativeSize)83 TEST(SimpleBufferExpectBug, WriteNegativeSize) {
84 SimpleBuffer buffer;
85
86 EXPECT_QUICHE_BUG(buffer.Write(nullptr, -1), "size must not be negative");
87 }
88
TEST_F(SimpleBufferTest,Basics)89 TEST_F(SimpleBufferTest, Basics) {
90 SimpleBuffer buffer;
91
92 EXPECT_TRUE(buffer.Empty());
93 EXPECT_EQ("", buffer.GetReadableRegion());
94 EXPECT_EQ(0, storage_size(buffer));
95 EXPECT_EQ(0, read_idx(buffer));
96 EXPECT_EQ(0, write_idx(buffer));
97
98 char* readable_ptr = nullptr;
99 int readable_size = 0;
100 buffer.GetReadablePtr(&readable_ptr, &readable_size);
101 char* writeable_ptr = nullptr;
102 int writable_size = 0;
103 buffer.GetWritablePtr(&writeable_ptr, &writable_size);
104
105 EXPECT_EQ(storage(buffer), readable_ptr);
106 EXPECT_EQ(0, readable_size);
107 EXPECT_EQ(storage(buffer), writeable_ptr);
108 EXPECT_EQ(0, writable_size);
109 EXPECT_EQ(0, buffer.ReadableBytes());
110
111 const SimpleBuffer buffer2;
112 EXPECT_EQ(0, buffer2.ReadableBytes());
113 }
114
TEST_F(SimpleBufferTest,BasicWR)115 TEST_F(SimpleBufferTest, BasicWR) {
116 SimpleBuffer buffer;
117
118 EXPECT_EQ(4, buffer.Write(ibuf, 4));
119 EXPECT_EQ(0, read_idx(buffer));
120 EXPECT_EQ(4, write_idx(buffer));
121 EXPECT_EQ(kMinimumSimpleBufferSize, storage_size(buffer));
122 EXPECT_EQ(4, buffer.ReadableBytes());
123 EXPECT_EQ("1234", buffer.GetReadableRegion());
124 int bytes_written = 4;
125 EXPECT_TRUE(!buffer.Empty());
126
127 char* readable_ptr = nullptr;
128 int readable_size = 0;
129 buffer.GetReadablePtr(&readable_ptr, &readable_size);
130 char* writeable_ptr = nullptr;
131 int writable_size = 0;
132 buffer.GetWritablePtr(&writeable_ptr, &writable_size);
133
134 EXPECT_EQ(storage(buffer), readable_ptr);
135 EXPECT_EQ(4, readable_size);
136 EXPECT_EQ(storage(buffer) + 4, writeable_ptr);
137 EXPECT_EQ(6, writable_size);
138
139 char obuf[ABSL_ARRAYSIZE(ibuf)];
140 int bytes_read = 0;
141 EXPECT_EQ(4, buffer.Read(obuf + bytes_read, 40));
142 EXPECT_EQ(0, read_idx(buffer));
143 EXPECT_EQ(0, write_idx(buffer));
144 EXPECT_EQ(kMinimumSimpleBufferSize, storage_size(buffer));
145 EXPECT_EQ(0, buffer.ReadableBytes());
146 EXPECT_EQ("", buffer.GetReadableRegion());
147 bytes_read += 4;
148 EXPECT_TRUE(buffer.Empty());
149 buffer.GetReadablePtr(&readable_ptr, &readable_size);
150 buffer.GetWritablePtr(&writeable_ptr, &writable_size);
151 EXPECT_EQ(storage(buffer), readable_ptr);
152 EXPECT_EQ(0, readable_size);
153 EXPECT_EQ(storage(buffer), writeable_ptr);
154 EXPECT_EQ(kMinimumSimpleBufferSize, writable_size);
155
156 EXPECT_EQ(bytes_written, bytes_read);
157 for (int i = 0; i < bytes_read; ++i) {
158 EXPECT_EQ(obuf[i], ibuf[i]);
159 }
160
161 // More R/W tests.
162 EXPECT_EQ(10, buffer.Write(ibuf + bytes_written, 10));
163 EXPECT_EQ(0, read_idx(buffer));
164 EXPECT_EQ(10, write_idx(buffer));
165 EXPECT_EQ(10, storage_size(buffer));
166 EXPECT_EQ(10, buffer.ReadableBytes());
167 bytes_written += 10;
168
169 EXPECT_TRUE(!buffer.Empty());
170
171 EXPECT_EQ(6, buffer.Read(obuf + bytes_read, 6));
172 EXPECT_EQ(6, read_idx(buffer));
173 EXPECT_EQ(10, write_idx(buffer));
174 EXPECT_EQ(10, storage_size(buffer));
175 EXPECT_EQ(4, buffer.ReadableBytes());
176 bytes_read += 6;
177
178 EXPECT_TRUE(!buffer.Empty());
179
180 EXPECT_EQ(4, buffer.Read(obuf + bytes_read, 7));
181 EXPECT_EQ(0, read_idx(buffer));
182 EXPECT_EQ(0, write_idx(buffer));
183 EXPECT_EQ(10, storage_size(buffer));
184 EXPECT_EQ(0, buffer.ReadableBytes());
185 bytes_read += 4;
186
187 EXPECT_TRUE(buffer.Empty());
188
189 EXPECT_EQ(bytes_written, bytes_read);
190 for (int i = 0; i < bytes_read; ++i) {
191 EXPECT_EQ(obuf[i], ibuf[i]);
192 }
193 }
194
TEST_F(SimpleBufferTest,Reserve)195 TEST_F(SimpleBufferTest, Reserve) {
196 SimpleBuffer buffer;
197 EXPECT_EQ(0, storage_size(buffer));
198
199 buffer.WriteString("foo");
200 EXPECT_EQ(kMinimumSimpleBufferSize, storage_size(buffer));
201
202 // Reserve by expanding the buffer.
203 buffer.Reserve(kMinimumSimpleBufferSize + 1);
204 EXPECT_EQ(2 * kMinimumSimpleBufferSize, storage_size(buffer));
205
206 buffer.Clear();
207 buffer.AdvanceWritablePtr(kMinimumSimpleBufferSize);
208 buffer.AdvanceReadablePtr(kMinimumSimpleBufferSize - 2);
209 EXPECT_EQ(kMinimumSimpleBufferSize, write_idx(buffer));
210 EXPECT_EQ(2 * kMinimumSimpleBufferSize, storage_size(buffer));
211
212 // Reserve by moving data around. `storage_size` does not change.
213 buffer.Reserve(kMinimumSimpleBufferSize + 1);
214 EXPECT_EQ(2, write_idx(buffer));
215 EXPECT_EQ(2 * kMinimumSimpleBufferSize, storage_size(buffer));
216 }
217
TEST_F(SimpleBufferTest,Extend)218 TEST_F(SimpleBufferTest, Extend) {
219 SimpleBuffer buffer;
220
221 // Test a write which should not extend the buffer.
222 EXPECT_EQ(7, buffer.Write(ibuf, 7));
223 EXPECT_EQ(0, read_idx(buffer));
224 EXPECT_EQ(7, write_idx(buffer));
225 EXPECT_EQ(kMinimumSimpleBufferSize, storage_size(buffer));
226 EXPECT_EQ(7, buffer.ReadableBytes());
227 EXPECT_EQ(0, read_idx(buffer));
228 EXPECT_EQ(7, write_idx(buffer));
229 EXPECT_EQ(kMinimumSimpleBufferSize, storage_size(buffer));
230 EXPECT_EQ(7, buffer.ReadableBytes());
231 int bytes_written = 7;
232
233 // Test a write which should extend the buffer.
234 EXPECT_EQ(4, buffer.Write(ibuf + bytes_written, 4));
235 EXPECT_EQ(0, read_idx(buffer));
236 EXPECT_EQ(11, write_idx(buffer));
237 EXPECT_EQ(20, storage_size(buffer));
238 EXPECT_EQ(11, buffer.ReadableBytes());
239 bytes_written += 4;
240
241 char obuf[ABSL_ARRAYSIZE(ibuf)];
242 EXPECT_EQ(11, buffer.Read(obuf, 11));
243 EXPECT_EQ(0, read_idx(buffer));
244 EXPECT_EQ(0, write_idx(buffer));
245 EXPECT_EQ(20, storage_size(buffer));
246 EXPECT_EQ(0, read_idx(buffer));
247 EXPECT_EQ(0, write_idx(buffer));
248 EXPECT_EQ(0, buffer.ReadableBytes());
249
250 const int bytes_read = 11;
251 EXPECT_EQ(bytes_written, bytes_read);
252 for (int i = 0; i < bytes_read; ++i) {
253 EXPECT_EQ(obuf[i], ibuf[i]);
254 }
255 }
256
TEST_F(SimpleBufferTest,Clear)257 TEST_F(SimpleBufferTest, Clear) {
258 SimpleBuffer buffer;
259
260 buffer.Clear();
261
262 EXPECT_EQ(0, read_idx(buffer));
263 EXPECT_EQ(0, write_idx(buffer));
264 EXPECT_EQ(0, storage_size(buffer));
265 EXPECT_EQ(0, buffer.ReadableBytes());
266
267 buffer.WriteString("foo");
268 buffer.Clear();
269
270 EXPECT_EQ(0, read_idx(buffer));
271 EXPECT_EQ(0, write_idx(buffer));
272 EXPECT_EQ(kMinimumSimpleBufferSize, storage_size(buffer));
273 EXPECT_EQ(0, buffer.ReadableBytes());
274 }
275
TEST_F(SimpleBufferTest,LongWrite)276 TEST_F(SimpleBufferTest, LongWrite) {
277 SimpleBuffer buffer;
278
279 std::string s1 = "HTTP/1.1 500 Service Unavailable";
280 buffer.Write(s1.data(), s1.size());
281 buffer.Write("\r\n", 2);
282 std::string key = "Connection";
283 std::string value = "close";
284 buffer.Write(key.data(), key.size());
285 buffer.Write(": ", 2);
286 buffer.Write(value.data(), value.size());
287 buffer.Write("\r\n", 2);
288 buffer.Write("\r\n", 2);
289 std::string message =
290 "<html><head>\n"
291 "<meta http-equiv=\"content-type\""
292 " content=\"text/html;charset=us-ascii\">\n"
293 "<style><!--\n"
294 "body {font-family: arial,sans-serif}\n"
295 "div.nav {margin-top: 1ex}\n"
296 "div.nav A {font-size: 10pt; font-family: arial,sans-serif}\n"
297 "span.nav {font-size: 10pt; font-family: arial,sans-serif;"
298 " font-weight: bold}\n"
299 "div.nav A,span.big {font-size: 12pt; color: #0000cc}\n"
300 "div.nav A {font-size: 10pt; color: black}\n"
301 "A.l:link {color: #6f6f6f}\n"
302 "A.u:link {color: green}\n"
303 "//--></style>\n"
304 "</head>\n"
305 "<body text=#000000 bgcolor=#ffffff>\n"
306 "<table border=0 cellpadding=2 cellspacing=0 width=100%>"
307 "<tr><td rowspan=3 width=1% nowrap>\n"
308 "<b>"
309 "<font face=times color=#0039b6 size=10>G</font>"
310 "<font face=times color=#c41200 size=10>o</font>"
311 "<font face=times color=#f3c518 size=10>o</font>"
312 "<font face=times color=#0039b6 size=10>g</font>"
313 "<font face=times color=#30a72f size=10>l</font>"
314 "<font face=times color=#c41200 size=10>e</font>"
315 " </b>\n"
316 "<td> </td></tr>\n"
317 "<tr><td bgcolor=#3366cc><font face=arial,sans-serif color=#ffffff>"
318 " <b>Error</b></td></tr>\n"
319 "<tr><td> </td></tr></table>\n"
320 "<blockquote>\n"
321 "<H1> Internal Server Error</H1>\n"
322 " This server was unable to complete the request\n"
323 "<p></blockquote>\n"
324 "<table width=100% cellpadding=0 cellspacing=0>"
325 "<tr><td bgcolor=#3366cc><img alt=\"\" width=1 height=4></td></tr>"
326 "</table>"
327 "</body></html>\n";
328 buffer.Write(message.data(), message.size());
329 const std::string correct_result =
330 "HTTP/1.1 500 Service Unavailable\r\n"
331 "Connection: close\r\n"
332 "\r\n"
333 "<html><head>\n"
334 "<meta http-equiv=\"content-type\""
335 " content=\"text/html;charset=us-ascii\">\n"
336 "<style><!--\n"
337 "body {font-family: arial,sans-serif}\n"
338 "div.nav {margin-top: 1ex}\n"
339 "div.nav A {font-size: 10pt; font-family: arial,sans-serif}\n"
340 "span.nav {font-size: 10pt; font-family: arial,sans-serif;"
341 " font-weight: bold}\n"
342 "div.nav A,span.big {font-size: 12pt; color: #0000cc}\n"
343 "div.nav A {font-size: 10pt; color: black}\n"
344 "A.l:link {color: #6f6f6f}\n"
345 "A.u:link {color: green}\n"
346 "//--></style>\n"
347 "</head>\n"
348 "<body text=#000000 bgcolor=#ffffff>\n"
349 "<table border=0 cellpadding=2 cellspacing=0 width=100%>"
350 "<tr><td rowspan=3 width=1% nowrap>\n"
351 "<b>"
352 "<font face=times color=#0039b6 size=10>G</font>"
353 "<font face=times color=#c41200 size=10>o</font>"
354 "<font face=times color=#f3c518 size=10>o</font>"
355 "<font face=times color=#0039b6 size=10>g</font>"
356 "<font face=times color=#30a72f size=10>l</font>"
357 "<font face=times color=#c41200 size=10>e</font>"
358 " </b>\n"
359 "<td> </td></tr>\n"
360 "<tr><td bgcolor=#3366cc><font face=arial,sans-serif color=#ffffff>"
361 " <b>Error</b></td></tr>\n"
362 "<tr><td> </td></tr></table>\n"
363 "<blockquote>\n"
364 "<H1> Internal Server Error</H1>\n"
365 " This server was unable to complete the request\n"
366 "<p></blockquote>\n"
367 "<table width=100% cellpadding=0 cellspacing=0>"
368 "<tr><td bgcolor=#3366cc><img alt=\"\" width=1 height=4></td></tr>"
369 "</table>"
370 "</body></html>\n";
371 EXPECT_EQ(correct_result, buffer.GetReadableRegion());
372 }
373
TEST_F(SimpleBufferTest,ReleaseAsSlice)374 TEST_F(SimpleBufferTest, ReleaseAsSlice) {
375 SimpleBuffer buffer;
376
377 buffer.WriteString("abc");
378 SimpleBuffer::ReleasedBuffer released = buffer.Release();
379 EXPECT_EQ("abc", absl::string_view(released.buffer.get(), released.size));
380
381 char* readable_ptr = nullptr;
382 int readable_size = 0;
383 buffer.GetReadablePtr(&readable_ptr, &readable_size);
384 EXPECT_EQ(nullptr, readable_ptr);
385 EXPECT_EQ(0, readable_size);
386
387 buffer.WriteString("def");
388 released = buffer.Release();
389 buffer.GetReadablePtr(&readable_ptr, &readable_size);
390 EXPECT_EQ(nullptr, readable_ptr);
391 EXPECT_EQ(0, readable_size);
392 EXPECT_EQ("def", absl::string_view(released.buffer.get(), released.size));
393 }
394
TEST_F(SimpleBufferTest,EmptyBufferReleaseAsSlice)395 TEST_F(SimpleBufferTest, EmptyBufferReleaseAsSlice) {
396 SimpleBuffer buffer;
397 char* readable_ptr = nullptr;
398 int readable_size = 0;
399
400 SimpleBuffer::ReleasedBuffer released = buffer.Release();
401 buffer.GetReadablePtr(&readable_ptr, &readable_size);
402 EXPECT_EQ(nullptr, readable_ptr);
403 EXPECT_EQ(0, readable_size);
404 EXPECT_TRUE(released.buffer == nullptr);
405 EXPECT_EQ(released.size, 0u);
406 }
407
408 } // namespace
409
410 } // namespace test
411
412 } // namespace quiche
413