| 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 |