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