OLD | NEW |
| (Empty) |
1 // Copyright 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/quic/iovector.h" | |
6 | |
7 #include <string.h> | |
8 | |
9 #include <memory> | |
10 #include <string> | |
11 | |
12 #include "net/test/gtest_util.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 | |
15 using std::string; | |
16 | |
17 namespace net { | |
18 namespace test { | |
19 namespace { | |
20 | |
21 const char* const test_data[] = { | |
22 "test string 1, a medium size one.", "test string2", | |
23 "test string 3, a looooooooooooong loooooooooooooooong string"}; | |
24 | |
25 TEST(IOVectorTest, CopyConstructor) { | |
26 IOVector iov1; | |
27 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
28 iov1.Append(const_cast<char*>(test_data[i]), strlen(test_data[i])); | |
29 } | |
30 IOVector iov2 = iov1; | |
31 EXPECT_EQ(iov2.Size(), iov1.Size()); | |
32 for (size_t i = 0; i < iov2.Size(); ++i) { | |
33 EXPECT_TRUE(iov2.iovec()[i].iov_base == iov1.iovec()[i].iov_base); | |
34 EXPECT_EQ(iov2.iovec()[i].iov_len, iov1.iovec()[i].iov_len); | |
35 } | |
36 EXPECT_EQ(iov2.TotalBufferSize(), iov1.TotalBufferSize()); | |
37 } | |
38 | |
39 TEST(IOVectorTest, AssignmentOperator) { | |
40 IOVector iov1; | |
41 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
42 iov1.Append(const_cast<char*>(test_data[i]), strlen(test_data[i])); | |
43 } | |
44 IOVector iov2; | |
45 iov2.Append(const_cast<char*>("ephemeral string"), 16); | |
46 // The following assignment results in a shallow copy; | |
47 // both IOVectors point to the same underlying data. | |
48 iov2 = iov1; | |
49 EXPECT_EQ(iov2.Size(), iov1.Size()); | |
50 for (size_t i = 0; i < iov2.Size(); ++i) { | |
51 EXPECT_TRUE(iov2.iovec()[i].iov_base == iov1.iovec()[i].iov_base); | |
52 EXPECT_EQ(iov2.iovec()[i].iov_len, iov1.iovec()[i].iov_len); | |
53 } | |
54 EXPECT_EQ(iov2.TotalBufferSize(), iov1.TotalBufferSize()); | |
55 } | |
56 | |
57 TEST(IOVectorTest, Append) { | |
58 IOVector iov; | |
59 int length = 0; | |
60 const struct iovec* iov2 = iov.iovec(); | |
61 | |
62 ASSERT_EQ(0u, iov.Size()); | |
63 ASSERT_TRUE(iov2 == nullptr); | |
64 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
65 const int str_len = strlen(test_data[i]); | |
66 const int append_len = str_len / 2; | |
67 // This should append a new block. | |
68 iov.Append(const_cast<char*>(test_data[i]), append_len); | |
69 length += append_len; | |
70 ASSERT_EQ(i + 1, static_cast<size_t>(iov.Size())); | |
71 ASSERT_TRUE(iov.LastBlockEnd() == test_data[i] + append_len); | |
72 // This should just lengthen the existing block. | |
73 iov.Append(const_cast<char*>(test_data[i] + append_len), | |
74 str_len - append_len); | |
75 length += (str_len - append_len); | |
76 ASSERT_EQ(i + 1, static_cast<size_t>(iov.Size())); | |
77 ASSERT_TRUE(iov.LastBlockEnd() == test_data[i] + str_len); | |
78 } | |
79 | |
80 iov2 = iov.iovec(); | |
81 ASSERT_TRUE(iov2 != nullptr); | |
82 for (size_t i = 0; i < iov.Size(); ++i) { | |
83 ASSERT_TRUE(test_data[i] == iov2[i].iov_base); | |
84 ASSERT_EQ(strlen(test_data[i]), iov2[i].iov_len); | |
85 } | |
86 } | |
87 | |
88 TEST(IOVectorTest, AppendIovec) { | |
89 IOVector iov; | |
90 const struct iovec test_iov[] = {{const_cast<char*>("foo"), 3}, | |
91 {const_cast<char*>("bar"), 3}, | |
92 {const_cast<char*>("buzzzz"), 6}}; | |
93 iov.AppendIovec(test_iov, arraysize(test_iov)); | |
94 for (size_t i = 0; i < arraysize(test_iov); ++i) { | |
95 EXPECT_EQ(test_iov[i].iov_base, iov.iovec()[i].iov_base); | |
96 EXPECT_EQ(test_iov[i].iov_len, iov.iovec()[i].iov_len); | |
97 } | |
98 | |
99 // Test AppendIovecAtMostBytes. | |
100 iov.Clear(); | |
101 // Stop in the middle of a block. | |
102 EXPECT_EQ(5u, iov.AppendIovecAtMostBytes(test_iov, arraysize(test_iov), 5)); | |
103 EXPECT_EQ(5u, iov.TotalBufferSize()); | |
104 iov.Append(static_cast<char*>(test_iov[1].iov_base) + 2, 1); | |
105 // Make sure the boundary case, where max_bytes == size of block also works. | |
106 EXPECT_EQ(6u, iov.AppendIovecAtMostBytes(&test_iov[2], 1, 6)); | |
107 ASSERT_LE(arraysize(test_iov), static_cast<size_t>(iov.Size())); | |
108 for (size_t i = 0; i < arraysize(test_iov); ++i) { | |
109 EXPECT_EQ(test_iov[i].iov_base, iov.iovec()[i].iov_base); | |
110 EXPECT_EQ(test_iov[i].iov_len, iov.iovec()[i].iov_len); | |
111 } | |
112 } | |
113 | |
114 TEST(IOVectorTest, ConsumeHalfBlocks) { | |
115 IOVector iov; | |
116 int length = 0; | |
117 | |
118 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
119 const int str_len = strlen(test_data[i]); | |
120 iov.Append(const_cast<char*>(test_data[i]), str_len); | |
121 length += str_len; | |
122 } | |
123 const char* endp = iov.LastBlockEnd(); | |
124 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
125 const struct iovec* iov2 = iov.iovec(); | |
126 const size_t str_len = strlen(test_data[i]); | |
127 size_t tmp = str_len / 2; | |
128 | |
129 ASSERT_TRUE(iov2 != nullptr); | |
130 ASSERT_TRUE(iov2[0].iov_base == test_data[i]); | |
131 ASSERT_EQ(str_len, iov2[0].iov_len); | |
132 | |
133 // Consume half of the first block. | |
134 size_t consumed = iov.Consume(tmp); | |
135 ASSERT_EQ(tmp, consumed); | |
136 ASSERT_EQ(arraysize(test_data) - i, static_cast<size_t>(iov.Size())); | |
137 iov2 = iov.iovec(); | |
138 ASSERT_TRUE(iov2 != nullptr); | |
139 ASSERT_TRUE(iov2[0].iov_base == test_data[i] + tmp); | |
140 ASSERT_EQ(iov2[0].iov_len, str_len - tmp); | |
141 | |
142 // Consume the rest of the first block. | |
143 consumed = iov.Consume(str_len - tmp); | |
144 ASSERT_EQ(str_len - tmp, consumed); | |
145 ASSERT_EQ(arraysize(test_data) - i - 1, static_cast<size_t>(iov.Size())); | |
146 iov2 = iov.iovec(); | |
147 if (iov.Size() > 0) { | |
148 ASSERT_TRUE(iov2 != nullptr); | |
149 ASSERT_TRUE(iov.LastBlockEnd() == endp); | |
150 } else { | |
151 ASSERT_TRUE(iov2 == nullptr); | |
152 ASSERT_TRUE(iov.LastBlockEnd() == nullptr); | |
153 } | |
154 } | |
155 } | |
156 | |
157 TEST(IOVectorTest, ConsumeTwoAndHalfBlocks) { | |
158 IOVector iov; | |
159 int length = 0; | |
160 | |
161 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
162 const int str_len = strlen(test_data[i]); | |
163 iov.Append(const_cast<char*>(test_data[i]), str_len); | |
164 length += str_len; | |
165 } | |
166 const size_t last_len = strlen(test_data[arraysize(test_data) - 1]); | |
167 const size_t half_len = last_len / 2; | |
168 | |
169 const char* endp = iov.LastBlockEnd(); | |
170 size_t consumed = iov.Consume(length - half_len); | |
171 ASSERT_EQ(length - half_len, consumed); | |
172 const struct iovec* iov2 = iov.iovec(); | |
173 ASSERT_TRUE(iov2 != nullptr); | |
174 ASSERT_EQ(1u, iov.Size()); | |
175 ASSERT_TRUE(iov2[0].iov_base == | |
176 test_data[arraysize(test_data) - 1] + last_len - half_len); | |
177 ASSERT_EQ(half_len, iov2[0].iov_len); | |
178 ASSERT_TRUE(iov.LastBlockEnd() == endp); | |
179 | |
180 consumed = iov.Consume(half_len); | |
181 ASSERT_EQ(half_len, consumed); | |
182 iov2 = iov.iovec(); | |
183 ASSERT_EQ(0u, iov.Size()); | |
184 ASSERT_TRUE(iov2 == nullptr); | |
185 ASSERT_TRUE(iov.LastBlockEnd() == nullptr); | |
186 } | |
187 | |
188 TEST(IOVectorTest, ConsumeTooMuch) { | |
189 IOVector iov; | |
190 int length = 0; | |
191 | |
192 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
193 const int str_len = strlen(test_data[i]); | |
194 iov.Append(const_cast<char*>(test_data[i]), str_len); | |
195 length += str_len; | |
196 } | |
197 | |
198 int consumed = 0; | |
199 EXPECT_DFATAL({ consumed = iov.Consume(length + 1); }, | |
200 "Attempting to consume 1 non-existent bytes."); | |
201 ASSERT_EQ(length, consumed); | |
202 const struct iovec* iov2 = iov.iovec(); | |
203 ASSERT_EQ(0u, iov.Size()); | |
204 ASSERT_TRUE(iov2 == nullptr); | |
205 ASSERT_TRUE(iov.LastBlockEnd() == nullptr); | |
206 } | |
207 | |
208 TEST(IOVectorTest, ConsumeAndCopyHalfBlocks) { | |
209 IOVector iov; | |
210 int length = 0; | |
211 | |
212 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
213 const int str_len = strlen(test_data[i]); | |
214 iov.Append(const_cast<char*>(test_data[i]), str_len); | |
215 length += str_len; | |
216 } | |
217 const char* endp = iov.LastBlockEnd(); | |
218 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
219 const struct iovec* iov2 = iov.iovec(); | |
220 const size_t str_len = strlen(test_data[i]); | |
221 size_t tmp = str_len / 2; | |
222 | |
223 ASSERT_TRUE(iov2 != nullptr); | |
224 ASSERT_TRUE(iov2[0].iov_base == test_data[i]); | |
225 ASSERT_EQ(str_len, iov2[0].iov_len); | |
226 | |
227 // Consume half of the first block. | |
228 std::unique_ptr<char[]> buffer(new char[str_len]); | |
229 size_t consumed = iov.ConsumeAndCopy(tmp, buffer.get()); | |
230 EXPECT_EQ(0, memcmp(test_data[i], buffer.get(), tmp)); | |
231 ASSERT_EQ(tmp, consumed); | |
232 ASSERT_EQ(arraysize(test_data) - i, static_cast<size_t>(iov.Size())); | |
233 iov2 = iov.iovec(); | |
234 ASSERT_TRUE(iov2 != nullptr); | |
235 ASSERT_TRUE(iov2[0].iov_base == test_data[i] + tmp); | |
236 ASSERT_EQ(iov2[0].iov_len, str_len - tmp); | |
237 | |
238 // Consume the rest of the first block. | |
239 consumed = iov.ConsumeAndCopy(str_len - tmp, buffer.get()); | |
240 ASSERT_EQ(str_len - tmp, consumed); | |
241 ASSERT_EQ(arraysize(test_data) - i - 1, static_cast<size_t>(iov.Size())); | |
242 iov2 = iov.iovec(); | |
243 if (iov.Size() > 0) { | |
244 ASSERT_TRUE(iov2 != nullptr); | |
245 ASSERT_TRUE(iov.LastBlockEnd() == endp); | |
246 } else { | |
247 ASSERT_TRUE(iov2 == nullptr); | |
248 ASSERT_TRUE(iov.LastBlockEnd() == nullptr); | |
249 } | |
250 } | |
251 } | |
252 | |
253 TEST(IOVectorTest, ConsumeAndCopyTwoAndHalfBlocks) { | |
254 IOVector iov; | |
255 size_t length = 0; | |
256 | |
257 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
258 const int str_len = strlen(test_data[i]); | |
259 iov.Append(const_cast<char*>(test_data[i]), str_len); | |
260 length += str_len; | |
261 } | |
262 const size_t last_len = strlen(test_data[arraysize(test_data) - 1]); | |
263 const size_t half_len = last_len / 2; | |
264 | |
265 const char* endp = iov.LastBlockEnd(); | |
266 std::unique_ptr<char[]> buffer(new char[length]); | |
267 size_t consumed = iov.ConsumeAndCopy(length - half_len, buffer.get()); | |
268 ASSERT_EQ(length - half_len, consumed); | |
269 const struct iovec* iov2 = iov.iovec(); | |
270 ASSERT_TRUE(iov2 != nullptr); | |
271 ASSERT_EQ(1u, iov.Size()); | |
272 ASSERT_TRUE(iov2[0].iov_base == | |
273 test_data[arraysize(test_data) - 1] + last_len - half_len); | |
274 ASSERT_EQ(half_len, iov2[0].iov_len); | |
275 ASSERT_TRUE(iov.LastBlockEnd() == endp); | |
276 | |
277 consumed = iov.Consume(half_len); | |
278 ASSERT_EQ(half_len, consumed); | |
279 iov2 = iov.iovec(); | |
280 ASSERT_EQ(0u, iov.Size()); | |
281 ASSERT_TRUE(iov2 == nullptr); | |
282 ASSERT_TRUE(iov.LastBlockEnd() == nullptr); | |
283 } | |
284 | |
285 TEST(IOVectorTest, ConsumeAndCopyTooMuch) { | |
286 IOVector iov; | |
287 int length = 0; | |
288 | |
289 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
290 const int str_len = strlen(test_data[i]); | |
291 iov.Append(const_cast<char*>(test_data[i]), str_len); | |
292 length += str_len; | |
293 } | |
294 | |
295 int consumed = 0; | |
296 std::unique_ptr<char[]> buffer(new char[length + 1]); | |
297 EXPECT_DFATAL({ consumed = iov.ConsumeAndCopy(length + 1, buffer.get()); }, | |
298 "Attempting to consume 1 non-existent bytes."); | |
299 ASSERT_EQ(length, consumed); | |
300 const struct iovec* iov2 = iov.iovec(); | |
301 ASSERT_EQ(0u, iov.Size()); | |
302 ASSERT_TRUE(iov2 == nullptr); | |
303 ASSERT_TRUE(iov.LastBlockEnd() == nullptr); | |
304 } | |
305 | |
306 TEST(IOVectorTest, Clear) { | |
307 IOVector iov; | |
308 int length = 0; | |
309 | |
310 for (size_t i = 0; i < arraysize(test_data); ++i) { | |
311 const int str_len = strlen(test_data[i]); | |
312 iov.Append(const_cast<char*>(test_data[i]), str_len); | |
313 length += str_len; | |
314 } | |
315 const struct iovec* iov2 = iov.iovec(); | |
316 ASSERT_TRUE(iov2 != nullptr); | |
317 ASSERT_EQ(arraysize(test_data), static_cast<size_t>(iov.Size())); | |
318 | |
319 iov.Clear(); | |
320 iov2 = iov.iovec(); | |
321 ASSERT_EQ(0u, iov.Size()); | |
322 ASSERT_TRUE(iov2 == nullptr); | |
323 } | |
324 | |
325 TEST(IOVectorTest, Capacity) { | |
326 IOVector iov; | |
327 // Note: IOVector merges adjacent Appends() into a single iov. | |
328 // Therefore, if we expect final size of iov to be 3, we must insure | |
329 // that the items we are appending are not adjacent. To achieve that | |
330 // we use use an array (a[1] provides a buffer between a[0] and b[0], | |
331 // and makes them non-adjacent). | |
332 char a[2], b[2], c[2]; | |
333 iov.Append(&a[0], 1); | |
334 iov.Append(&b[0], 1); | |
335 iov.Append(&c[0], 1); | |
336 ASSERT_EQ(3u, iov.Size()); | |
337 size_t capacity = iov.Capacity(); | |
338 EXPECT_LE(iov.Size(), capacity); | |
339 iov.Consume(2); | |
340 // The capacity should not have changed. | |
341 EXPECT_EQ(capacity, iov.Capacity()); | |
342 } | |
343 | |
344 TEST(IOVectorTest, Swap) { | |
345 IOVector iov1, iov2; | |
346 // See IOVector merge comment above. | |
347 char a[2], b[2], c[2], d[2], e[2]; | |
348 iov1.Append(&a[0], 1); | |
349 iov1.Append(&b[0], 1); | |
350 | |
351 iov2.Append(&c[0], 1); | |
352 iov2.Append(&d[0], 1); | |
353 iov2.Append(&e[0], 1); | |
354 iov1.Swap(&iov2); | |
355 | |
356 ASSERT_EQ(3u, iov1.Size()); | |
357 EXPECT_EQ(&c[0], iov1.iovec()[0].iov_base); | |
358 EXPECT_EQ(1u, iov1.iovec()[0].iov_len); | |
359 EXPECT_EQ(&d[0], iov1.iovec()[1].iov_base); | |
360 EXPECT_EQ(1u, iov1.iovec()[1].iov_len); | |
361 EXPECT_EQ(&e[0], iov1.iovec()[2].iov_base); | |
362 EXPECT_EQ(1u, iov1.iovec()[2].iov_len); | |
363 | |
364 ASSERT_EQ(2u, iov2.Size()); | |
365 EXPECT_EQ(&a[0], iov2.iovec()[0].iov_base); | |
366 EXPECT_EQ(1u, iov2.iovec()[0].iov_len); | |
367 EXPECT_EQ(&b[0], iov2.iovec()[1].iov_base); | |
368 EXPECT_EQ(1u, iov2.iovec()[1].iov_len); | |
369 } | |
370 | |
371 } // namespace | |
372 } // namespace test | |
373 } // namespace net | |
OLD | NEW |