1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008, 2024 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "google/protobuf/repeated_ptr_field.h"
9
10 #include <algorithm>
11 #include <cstddef>
12 #include <cstdint>
13 #include <cstdlib>
14 #include <cstring>
15 #include <iterator>
16 #include <list>
17 #include <memory>
18 #include <string>
19 #include <type_traits>
20 #include <utility>
21 #include <vector>
22
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25 #include "absl/log/absl_check.h"
26 #include "absl/numeric/bits.h"
27 #include "absl/strings/str_cat.h"
28 #include "google/protobuf/arena_test_util.h"
29 #include "google/protobuf/internal_visibility_for_testing.h"
30 #include "google/protobuf/io/coded_stream.h"
31 #include "google/protobuf/unittest.pb.h"
32
33
34 // Must be included last.
35 #include "google/protobuf/port_def.inc"
36
37 namespace google {
38 namespace protobuf {
39 namespace {
40
41 using ::protobuf_unittest::TestAllTypes;
42 using ::protobuf_unittest::TestMessageWithManyRepeatedPtrFields;
43 using ::testing::A;
44 using ::testing::AllOf;
45 using ::testing::ElementsAre;
46 using ::testing::Ge;
47 using ::testing::Le;
48
TEST(RepeatedPtrOverPtrsIterator,Traits)49 TEST(RepeatedPtrOverPtrsIterator, Traits) {
50 using It = RepeatedPtrField<std::string>::pointer_iterator;
51 static_assert(std::is_same<It::value_type, std::string*>::value, "");
52 static_assert(std::is_same<It::reference, std::string*&>::value, "");
53 static_assert(std::is_same<It::pointer, std::string**>::value, "");
54 static_assert(std::is_same<It::difference_type, std::ptrdiff_t>::value, "");
55 static_assert(std::is_same<It::iterator_category,
56 std::random_access_iterator_tag>::value,
57 "");
58 #if __cplusplus >= 202002L
59 static_assert(
60 std::is_same<It::iterator_concept, std::contiguous_iterator_tag>::value,
61 "");
62 #else
63 static_assert(std::is_same<It::iterator_concept,
64 std::random_access_iterator_tag>::value,
65 "");
66 #endif
67 }
68
69 #ifdef __cpp_lib_to_address
TEST(RepeatedPtrOverPtrsIterator,ToAddress)70 TEST(RepeatedPtrOverPtrsIterator, ToAddress) {
71 // empty container
72 RepeatedPtrField<std::string> field;
73 EXPECT_THAT(std::to_address(field.pointer_begin()), A<std::string**>());
74 EXPECT_EQ(std::to_address(field.pointer_begin()),
75 std::to_address(field.pointer_end()));
76
77 // "null" iterator
78 using It = RepeatedPtrField<std::string>::pointer_iterator;
79 EXPECT_THAT(std::to_address(It()), A<std::string**>());
80 }
81 #endif
82
TEST(ConstRepeatedPtrOverPtrsIterator,Traits)83 TEST(ConstRepeatedPtrOverPtrsIterator, Traits) {
84 using It = RepeatedPtrField<std::string>::const_pointer_iterator;
85 static_assert(std::is_same<It::value_type, const std::string*>::value, "");
86 static_assert(std::is_same<It::reference, const std::string* const&>::value,
87 "");
88 static_assert(std::is_same<It::pointer, const std::string* const*>::value,
89 "");
90 static_assert(std::is_same<It::difference_type, std::ptrdiff_t>::value, "");
91 static_assert(std::is_same<It::iterator_category,
92 std::random_access_iterator_tag>::value,
93 "");
94 #if __cplusplus >= 202002L
95 static_assert(
96 std::is_same<It::iterator_concept, std::contiguous_iterator_tag>::value,
97 "");
98 #else
99 static_assert(std::is_same<It::iterator_concept,
100 std::random_access_iterator_tag>::value,
101 "");
102 #endif
103 }
104
TEST(RepeatedPtrField,MoveAdd)105 TEST(RepeatedPtrField, MoveAdd) {
106 RepeatedPtrField<TestAllTypes> field;
107 TestAllTypes test_all_types;
108 auto* optional_nested_message =
109 test_all_types.mutable_optional_nested_message();
110 optional_nested_message->set_bb(42);
111 field.Add(std::move(test_all_types));
112
113 EXPECT_EQ(optional_nested_message,
114 field.Mutable(0)->mutable_optional_nested_message());
115 }
116
TEST(RepeatedPtrField,ConstInit)117 TEST(RepeatedPtrField, ConstInit) {
118 PROTOBUF_CONSTINIT static RepeatedPtrField<std::string> field{}; // NOLINT
119 EXPECT_TRUE(field.empty());
120 }
121
TEST(RepeatedPtrField,ClearThenReserveMore)122 TEST(RepeatedPtrField, ClearThenReserveMore) {
123 // Test that Reserve properly destroys the old internal array when it's forced
124 // to allocate a new one, even when cleared-but-not-deleted objects are
125 // present. Use a 'string' and > 16 bytes length so that the elements are
126 // non-POD and allocate -- the leak checker will catch any skipped destructor
127 // calls here.
128 RepeatedPtrField<std::string> field;
129 for (int i = 0; i < 32; i++) {
130 *field.Add() = std::string("abcdefghijklmnopqrstuvwxyz0123456789");
131 }
132 EXPECT_EQ(32, field.size());
133 field.Clear();
134 EXPECT_EQ(0, field.size());
135 EXPECT_LE(32, field.Capacity());
136
137 field.Reserve(1024);
138 EXPECT_EQ(0, field.size());
139 EXPECT_LE(1024, field.Capacity());
140 // Finish test -- |field| should destroy the cleared-but-not-yet-destroyed
141 // strings.
142 }
143
144 // This helper overload set tests whether X::f can be called with a braced pair,
145 // X::f({a, b}) of std::string iterators (specifically, pointers: That call is
146 // ambiguous if and only if the call to ValidResolutionPointerRange is not.
147 template <typename X>
148 auto ValidResolutionPointerRange(const std::string* p)
149 -> decltype(X::f({p, p + 2}), std::true_type{});
150 template <typename X>
151 std::false_type ValidResolutionPointerRange(void*);
152
TEST(RepeatedPtrField,UnambiguousConstructor)153 TEST(RepeatedPtrField, UnambiguousConstructor) {
154 struct X {
155 static bool f(std::vector<std::string>) { return false; }
156 static bool f(google::protobuf::RepeatedPtrField<std::string>) { return true; }
157
158 static bool g(std::vector<int>) { return false; }
159 static bool g(google::protobuf::RepeatedPtrField<std::string>) { return true; }
160 };
161
162 // RepeatedPtrField has no initializer-list constructor, and a constructor
163 // from to const char* values is excluded by its constraints.
164 EXPECT_FALSE(X::f({"abc", "xyz"}));
165
166 // Construction from a pair of int* is also not ambiguous.
167 int a[5] = {};
168 EXPECT_FALSE(X::g({a, a + 5}));
169
170 // Construction from string iterators for the unique string overload "g"
171 // works.
172 // Disabling this for now, this is actually ambiguous with libstdc++.
173 // std::string b[2] = {"abc", "xyz"};
174 // EXPECT_TRUE(X::g({b, b + 2}));
175
176 // Construction from string iterators for "f" is ambiguous, since both
177 // containers are equally good.
178 //
179 // X::f({b, b + 2}); // error => ValidResolutionPointerRange is unambiguous.
180 EXPECT_FALSE(decltype(ValidResolutionPointerRange<X>(nullptr))::value);
181 }
182
TEST(RepeatedPtrField,Small)183 TEST(RepeatedPtrField, Small) {
184 RepeatedPtrField<std::string> field;
185
186 EXPECT_TRUE(field.empty());
187 EXPECT_EQ(field.size(), 0);
188
189 field.Add()->assign("foo");
190
191 EXPECT_FALSE(field.empty());
192 EXPECT_EQ(field.size(), 1);
193 EXPECT_EQ(field.Get(0), "foo");
194 EXPECT_EQ(field.at(0), "foo");
195
196 field.Add()->assign("bar");
197
198 EXPECT_FALSE(field.empty());
199 EXPECT_EQ(field.size(), 2);
200 EXPECT_EQ(field.Get(0), "foo");
201 EXPECT_EQ(field.at(0), "foo");
202 EXPECT_EQ(field.Get(1), "bar");
203 EXPECT_EQ(field.at(1), "bar");
204
205 field.Mutable(1)->assign("baz");
206
207 EXPECT_FALSE(field.empty());
208 EXPECT_EQ(field.size(), 2);
209 EXPECT_EQ(field.Get(0), "foo");
210 EXPECT_EQ(field.at(0), "foo");
211 EXPECT_EQ(field.Get(1), "baz");
212 EXPECT_EQ(field.at(1), "baz");
213
214 field.RemoveLast();
215
216 EXPECT_FALSE(field.empty());
217 EXPECT_EQ(field.size(), 1);
218 EXPECT_EQ(field.Get(0), "foo");
219 EXPECT_EQ(field.at(0), "foo");
220
221 field.Clear();
222
223 EXPECT_TRUE(field.empty());
224 EXPECT_EQ(field.size(), 0);
225 }
226
TEST(RepeatedPtrField,Large)227 TEST(RepeatedPtrField, Large) {
228 RepeatedPtrField<std::string> field;
229
230 for (int i = 0; i < 16; i++) {
231 *field.Add() += 'a' + i;
232 }
233
234 EXPECT_EQ(field.size(), 16);
235
236 for (int i = 0; i < 16; i++) {
237 EXPECT_EQ(field.Get(i).size(), 1);
238 EXPECT_EQ(field.Get(i)[0], 'a' + i);
239 }
240
241 int min_expected_usage = 16 * sizeof(std::string);
242 EXPECT_GE(field.SpaceUsedExcludingSelf(), min_expected_usage);
243 }
244
245 // TODO: Dedup with the same thing in repeated_field_unittest.cc.
246 template <typename Rep>
CheckAllocationSizes()247 void CheckAllocationSizes() {
248 using T = typename Rep::value_type;
249 // Use a large initial block to make the checks below easier to predict.
250 std::string buf(1 << 20, 0);
251 Arena arena(&buf[0], buf.size());
252 auto* rep = Arena::Create<Rep>(&arena);
253 size_t prev = arena.SpaceUsed();
254
255 for (int i = 0; i < 100; ++i) {
256 rep->Add(T{});
257 if (sizeof(void*) == 8) {
258 // For `RepeatedPtrField`, we also allocate the T on the arena.
259 // Subtract those from the count.
260 size_t new_used = arena.SpaceUsed() - (sizeof(T) * (i + 1));
261 size_t last_alloc = new_used - prev;
262 prev = new_used;
263
264 // When we actually allocated something, check the size.
265 if (last_alloc != 0) {
266 // Must be `>= 16`, as expected by the Arena.
267 ASSERT_GE(last_alloc, 16);
268 // Must be of a power of two.
269 size_t log2 = absl::bit_width(last_alloc) - 1;
270 ASSERT_EQ((1 << log2), last_alloc);
271 }
272
273 // The byte size must be a multiple of 8 when not SOO.
274 const int capacity_bytes = rep->Capacity() * sizeof(T);
275 if (capacity_bytes > internal::kSooCapacityBytes) {
276 ASSERT_EQ(capacity_bytes % 8, 0);
277 }
278 }
279 }
280 }
281
TEST(RepeatedPtrField,ArenaAllocationSizesMatchExpectedValues)282 TEST(RepeatedPtrField, ArenaAllocationSizesMatchExpectedValues) {
283 EXPECT_NO_FATAL_FAILURE(
284 CheckAllocationSizes<RepeatedPtrField<std::string>>());
285 }
286
TEST(RepeatedPtrField,NaturalGrowthOnArenasReuseBlocks)287 TEST(RepeatedPtrField, NaturalGrowthOnArenasReuseBlocks) {
288 using Rep = RepeatedPtrField<std::string>;
289 Arena arena;
290 std::vector<Rep*> values;
291
292 static constexpr int kNumFields = 100;
293 static constexpr int kNumElems = 1000;
294 for (int i = 0; i < kNumFields; ++i) {
295 values.push_back(Arena::Create<Rep>(&arena));
296 auto& field = *values.back();
297 for (int j = 0; j < kNumElems; ++j) {
298 field.Add("");
299 }
300 }
301
302 size_t expected =
303 values.size() * values[0]->Capacity() * sizeof(std::string*) +
304 sizeof(std::string) * kNumElems * kNumFields;
305 // Use a 2% slack for other overhead.
306 // If we were not reusing the blocks, the actual value would be ~2x the
307 // expected.
308 EXPECT_THAT(arena.SpaceUsed(), AllOf(Ge(expected), Le(1.02 * expected)));
309 }
310
TEST(RepeatedPtrField,AddAndAssignRanges)311 TEST(RepeatedPtrField, AddAndAssignRanges) {
312 RepeatedPtrField<std::string> field;
313
314 const char* vals[] = {"abc", "x", "yz", "xyzzy"};
315 field.Assign(std::begin(vals), std::end(vals));
316
317 ASSERT_EQ(field.size(), 4);
318 EXPECT_EQ(field.Get(0), "abc");
319 EXPECT_EQ(field.Get(1), "x");
320 EXPECT_EQ(field.Get(2), "yz");
321 EXPECT_EQ(field.Get(3), "xyzzy");
322
323 field.Add(std::begin(vals), std::end(vals));
324 ASSERT_EQ(field.size(), 8);
325 EXPECT_EQ(field.Get(0), "abc");
326 EXPECT_EQ(field.Get(1), "x");
327 EXPECT_EQ(field.Get(2), "yz");
328 EXPECT_EQ(field.Get(3), "xyzzy");
329 EXPECT_EQ(field.Get(4), "abc");
330 EXPECT_EQ(field.Get(5), "x");
331 EXPECT_EQ(field.Get(6), "yz");
332 EXPECT_EQ(field.Get(7), "xyzzy");
333 }
334
TEST(RepeatedPtrField,SwapSmallSmall)335 TEST(RepeatedPtrField, SwapSmallSmall) {
336 RepeatedPtrField<std::string> field1;
337 RepeatedPtrField<std::string> field2;
338
339 EXPECT_TRUE(field1.empty());
340 EXPECT_EQ(field1.size(), 0);
341 EXPECT_TRUE(field2.empty());
342 EXPECT_EQ(field2.size(), 0);
343
344 field1.Add()->assign("foo");
345 field1.Add()->assign("bar");
346
347 EXPECT_FALSE(field1.empty());
348 EXPECT_EQ(field1.size(), 2);
349 EXPECT_EQ(field1.Get(0), "foo");
350 EXPECT_EQ(field1.Get(1), "bar");
351
352 EXPECT_TRUE(field2.empty());
353 EXPECT_EQ(field2.size(), 0);
354
355 field1.Swap(&field2);
356
357 EXPECT_TRUE(field1.empty());
358 EXPECT_EQ(field1.size(), 0);
359
360 EXPECT_EQ(field2.size(), 2);
361 EXPECT_EQ(field2.Get(0), "foo");
362 EXPECT_EQ(field2.Get(1), "bar");
363 }
364
TEST(RepeatedPtrField,SwapLargeSmall)365 TEST(RepeatedPtrField, SwapLargeSmall) {
366 RepeatedPtrField<std::string> field1;
367 RepeatedPtrField<std::string> field2;
368
369 field2.Add()->assign("foo");
370 field2.Add()->assign("bar");
371 for (int i = 0; i < 16; i++) {
372 *field1.Add() += 'a' + i;
373 }
374 field1.Swap(&field2);
375
376 EXPECT_EQ(field1.size(), 2);
377 EXPECT_EQ(field1.Get(0), "foo");
378 EXPECT_EQ(field1.Get(1), "bar");
379 EXPECT_EQ(field2.size(), 16);
380 for (int i = 0; i < 16; i++) {
381 EXPECT_EQ(field2.Get(i).size(), 1);
382 EXPECT_EQ(field2.Get(i)[0], 'a' + i);
383 }
384 }
385
TEST(RepeatedPtrField,SwapLargeLarge)386 TEST(RepeatedPtrField, SwapLargeLarge) {
387 RepeatedPtrField<std::string> field1;
388 RepeatedPtrField<std::string> field2;
389
390 field1.Add()->assign("foo");
391 field1.Add()->assign("bar");
392 for (int i = 0; i < 16; i++) {
393 *field1.Add() += 'A' + i;
394 *field2.Add() += 'a' + i;
395 }
396 field2.Swap(&field1);
397
398 EXPECT_EQ(field1.size(), 16);
399 for (int i = 0; i < 16; i++) {
400 EXPECT_EQ(field1.Get(i).size(), 1);
401 EXPECT_EQ(field1.Get(i)[0], 'a' + i);
402 }
403 EXPECT_EQ(field2.size(), 18);
404 EXPECT_EQ(field2.Get(0), "foo");
405 EXPECT_EQ(field2.Get(1), "bar");
406 for (int i = 2; i < 18; i++) {
407 EXPECT_EQ(field2.Get(i).size(), 1);
408 EXPECT_EQ(field2.Get(i)[0], 'A' + i - 2);
409 }
410 }
411
ReservedSpace(RepeatedPtrField<std::string> * field)412 static int ReservedSpace(RepeatedPtrField<std::string>* field) {
413 const std::string* const* ptr = field->data();
414 do {
415 field->Add();
416 } while (field->data() == ptr);
417
418 return field->size() - 1;
419 }
420
TEST(RepeatedPtrField,ReserveMoreThanDouble)421 TEST(RepeatedPtrField, ReserveMoreThanDouble) {
422 RepeatedPtrField<std::string> field;
423 field.Reserve(20);
424
425 EXPECT_LE(20, ReservedSpace(&field));
426 }
427
TEST(RepeatedPtrField,ReserveLessThanDouble)428 TEST(RepeatedPtrField, ReserveLessThanDouble) {
429 RepeatedPtrField<std::string> field;
430 field.Reserve(20);
431
432 int capacity = field.Capacity();
433 // Grow by 1.5x
434 field.Reserve(capacity + (capacity >> 2));
435
436 EXPECT_LE(2 * capacity, ReservedSpace(&field));
437 }
438
TEST(RepeatedPtrField,ReserveLessThanExisting)439 TEST(RepeatedPtrField, ReserveLessThanExisting) {
440 RepeatedPtrField<std::string> field;
441 field.Reserve(20);
442 const std::string* const* previous_ptr = field.data();
443 field.Reserve(10);
444
445 EXPECT_EQ(previous_ptr, field.data());
446 EXPECT_LE(20, ReservedSpace(&field));
447 }
448
TEST(RepeatedPtrField,ReserveDoesntLoseAllocated)449 TEST(RepeatedPtrField, ReserveDoesntLoseAllocated) {
450 // Check that a bug is fixed: An earlier implementation of Reserve()
451 // failed to copy pointers to allocated-but-cleared objects, possibly
452 // leading to segfaults.
453 RepeatedPtrField<std::string> field;
454 std::string* first = field.Add();
455 field.RemoveLast();
456
457 field.Reserve(20);
458 EXPECT_EQ(first, field.Add());
459 }
460
461 // Clearing elements is tricky with RepeatedPtrFields since the memory for
462 // the elements is retained and reused.
TEST(RepeatedPtrField,ClearedElements)463 TEST(RepeatedPtrField, ClearedElements) {
464 PROTOBUF_IGNORE_DEPRECATION_START
465 RepeatedPtrField<std::string> field;
466
467 std::string* original = field.Add();
468 *original = "foo";
469
470 EXPECT_EQ(field.ClearedCount(), 0);
471
472 field.RemoveLast();
473 EXPECT_TRUE(original->empty());
474 EXPECT_EQ(field.ClearedCount(), 1);
475
476 EXPECT_EQ(field.Add(),
477 original); // Should return same string for reuse.
478 EXPECT_EQ(field.UnsafeArenaReleaseLast(), original); // We take ownership.
479 EXPECT_EQ(field.ClearedCount(), 0);
480
481 EXPECT_NE(field.Add(), original); // Should NOT return the same string.
482 EXPECT_EQ(field.ClearedCount(), 0);
483
484 field.UnsafeArenaAddAllocated(original); // Give ownership back.
485 EXPECT_EQ(field.ClearedCount(), 0);
486 EXPECT_EQ(field.Mutable(1), original);
487
488 field.Clear();
489 EXPECT_EQ(field.ClearedCount(), 2);
490 PROTOBUF_IGNORE_DEPRECATION_STOP
491 }
492
493 // Test all code paths in AddAllocated().
TEST(RepeatedPtrField,AddAllocated)494 TEST(RepeatedPtrField, AddAllocated) {
495 RepeatedPtrField<std::string> field;
496 while (field.size() < field.Capacity()) {
497 field.Add()->assign("filler");
498 }
499
500 const auto ensure_at_capacity = [&] {
501 while (field.size() < field.Capacity()) {
502 field.Add()->assign("filler");
503 }
504 };
505 const auto ensure_not_at_capacity = [&] { field.Reserve(field.size() + 1); };
506
507 ensure_at_capacity();
508 int index = field.size();
509
510 // First branch: Field is at capacity with no cleared objects.
511 ASSERT_EQ(field.size(), field.Capacity());
512 std::string* foo = new std::string("foo");
513 field.AddAllocated(foo);
514 EXPECT_EQ(index + 1, field.size());
515 EXPECT_EQ(0, field.ClearedCount());
516 EXPECT_EQ(foo, &field.Get(index));
517
518 // Last branch: Field is not at capacity and there are no cleared objects.
519 ensure_not_at_capacity();
520 std::string* bar = new std::string("bar");
521 field.AddAllocated(bar);
522 ++index;
523 EXPECT_EQ(index + 1, field.size());
524 EXPECT_EQ(0, field.ClearedCount());
525 EXPECT_EQ(bar, &field.Get(index));
526
527 // Third branch: Field is not at capacity and there are no cleared objects.
528 ensure_not_at_capacity();
529 field.RemoveLast();
530 std::string* baz = new std::string("baz");
531 field.AddAllocated(baz);
532 EXPECT_EQ(index + 1, field.size());
533 EXPECT_EQ(1, field.ClearedCount());
534 EXPECT_EQ(baz, &field.Get(index));
535
536 // Second branch: Field is at capacity but has some cleared objects.
537 ensure_at_capacity();
538 field.RemoveLast();
539 index = field.size();
540 std::string* moo = new std::string("moo");
541 field.AddAllocated(moo);
542 EXPECT_EQ(index + 1, field.size());
543 // We should have discarded the cleared object.
544 EXPECT_EQ(0, field.ClearedCount());
545 EXPECT_EQ(moo, &field.Get(index));
546 }
547
TEST(RepeatedPtrField,AddMethodsDontAcceptNull)548 TEST(RepeatedPtrField, AddMethodsDontAcceptNull) {
549 #if !defined(NDEBUG)
550 RepeatedPtrField<std::string> field;
551 EXPECT_DEATH(field.AddAllocated(nullptr), "nullptr");
552 EXPECT_DEATH(field.UnsafeArenaAddAllocated(nullptr), "nullptr");
553 #endif
554 }
555
TEST(RepeatedPtrField,AddAllocatedDifferentArena)556 TEST(RepeatedPtrField, AddAllocatedDifferentArena) {
557 RepeatedPtrField<TestAllTypes> field;
558 Arena arena;
559 auto* msg = Arena::Create<TestAllTypes>(&arena);
560 field.AddAllocated(msg);
561 }
562
TEST(RepeatedPtrField,MergeFrom)563 TEST(RepeatedPtrField, MergeFrom) {
564 RepeatedPtrField<std::string> source, destination;
565 source.Add()->assign("4");
566 source.Add()->assign("5");
567 destination.Add()->assign("1");
568 destination.Add()->assign("2");
569 destination.Add()->assign("3");
570
571 destination.MergeFrom(source);
572
573 ASSERT_EQ(5, destination.size());
574 EXPECT_EQ("1", destination.Get(0));
575 EXPECT_EQ("2", destination.Get(1));
576 EXPECT_EQ("3", destination.Get(2));
577 EXPECT_EQ("4", destination.Get(3));
578 EXPECT_EQ("5", destination.Get(4));
579 }
580
581
TEST(RepeatedPtrField,CopyFrom)582 TEST(RepeatedPtrField, CopyFrom) {
583 RepeatedPtrField<std::string> source, destination;
584 source.Add()->assign("4");
585 source.Add()->assign("5");
586 destination.Add()->assign("1");
587 destination.Add()->assign("2");
588 destination.Add()->assign("3");
589
590 destination.CopyFrom(source);
591
592 ASSERT_EQ(2, destination.size());
593 EXPECT_EQ("4", destination.Get(0));
594 EXPECT_EQ("5", destination.Get(1));
595 }
596
TEST(RepeatedPtrField,CopyFromSelf)597 TEST(RepeatedPtrField, CopyFromSelf) {
598 RepeatedPtrField<std::string> me;
599 me.Add()->assign("1");
600 me.CopyFrom(me);
601 ASSERT_EQ(1, me.size());
602 EXPECT_EQ("1", me.Get(0));
603 }
604
TEST(RepeatedPtrField,Erase)605 TEST(RepeatedPtrField, Erase) {
606 RepeatedPtrField<std::string> me;
607 RepeatedPtrField<std::string>::iterator it = me.erase(me.begin(), me.end());
608 EXPECT_TRUE(me.begin() == it);
609 EXPECT_EQ(0, me.size());
610
611 *me.Add() = "1";
612 *me.Add() = "2";
613 *me.Add() = "3";
614 it = me.erase(me.begin(), me.end());
615 EXPECT_TRUE(me.begin() == it);
616 EXPECT_EQ(0, me.size());
617
618 *me.Add() = "4";
619 *me.Add() = "5";
620 *me.Add() = "6";
621 it = me.erase(me.begin() + 2, me.end());
622 EXPECT_TRUE(me.begin() + 2 == it);
623 EXPECT_EQ(2, me.size());
624 EXPECT_EQ("4", me.Get(0));
625 EXPECT_EQ("5", me.Get(1));
626
627 *me.Add() = "6";
628 *me.Add() = "7";
629 *me.Add() = "8";
630 it = me.erase(me.begin() + 1, me.begin() + 3);
631 EXPECT_TRUE(me.begin() + 1 == it);
632 EXPECT_EQ(3, me.size());
633 EXPECT_EQ("4", me.Get(0));
634 EXPECT_EQ("7", me.Get(1));
635 EXPECT_EQ("8", me.Get(2));
636 }
637
TEST(RepeatedPtrField,CopyConstruct)638 TEST(RepeatedPtrField, CopyConstruct) {
639 auto token = internal::InternalVisibilityForTesting{};
640 RepeatedPtrField<std::string> source;
641 source.Add()->assign("1");
642 source.Add()->assign("2");
643
644 RepeatedPtrField<std::string> destination1(source);
645 ASSERT_EQ(2, destination1.size());
646 EXPECT_EQ("1", destination1.Get(0));
647 EXPECT_EQ("2", destination1.Get(1));
648
649 RepeatedPtrField<std::string> destination2(token, nullptr, source);
650 ASSERT_EQ(2, destination2.size());
651 EXPECT_EQ("1", destination2.Get(0));
652 EXPECT_EQ("2", destination2.Get(1));
653 }
654
TEST(RepeatedPtrField,CopyConstructWithArena)655 TEST(RepeatedPtrField, CopyConstructWithArena) {
656 auto token = internal::InternalVisibilityForTesting{};
657 RepeatedPtrField<std::string> source;
658 source.Add()->assign("1");
659 source.Add()->assign("2");
660
661 Arena arena;
662 RepeatedPtrField<std::string> destination(token, &arena, source);
663 ASSERT_EQ(2, destination.size());
664 EXPECT_EQ("1", destination.Get(0));
665 EXPECT_EQ("2", destination.Get(1));
666 }
667
TEST(RepeatedPtrField,IteratorConstruct_String)668 TEST(RepeatedPtrField, IteratorConstruct_String) {
669 std::vector<std::string> values;
670 values.push_back("1");
671 values.push_back("2");
672
673 RepeatedPtrField<std::string> field(values.begin(), values.end());
674 ASSERT_EQ(values.size(), field.size());
675 EXPECT_EQ(values[0], field.Get(0));
676 EXPECT_EQ(values[1], field.Get(1));
677
678 RepeatedPtrField<std::string> other(field.begin(), field.end());
679 ASSERT_EQ(values.size(), other.size());
680 EXPECT_EQ(values[0], other.Get(0));
681 EXPECT_EQ(values[1], other.Get(1));
682 }
683
TEST(RepeatedPtrField,IteratorConstruct_Proto)684 TEST(RepeatedPtrField, IteratorConstruct_Proto) {
685 typedef TestAllTypes::NestedMessage Nested;
686 std::vector<Nested> values;
687 values.push_back(Nested());
688 values.back().set_bb(1);
689 values.push_back(Nested());
690 values.back().set_bb(2);
691
692 RepeatedPtrField<Nested> field(values.begin(), values.end());
693 ASSERT_EQ(values.size(), field.size());
694 EXPECT_EQ(values[0].bb(), field.Get(0).bb());
695 EXPECT_EQ(values[1].bb(), field.Get(1).bb());
696
697 RepeatedPtrField<Nested> other(field.begin(), field.end());
698 ASSERT_EQ(values.size(), other.size());
699 EXPECT_EQ(values[0].bb(), other.Get(0).bb());
700 EXPECT_EQ(values[1].bb(), other.Get(1).bb());
701 }
702
TEST(RepeatedPtrField,SmallOptimization)703 TEST(RepeatedPtrField, SmallOptimization) {
704 // Properties checked here are not part of the contract of RepeatedPtrField,
705 // but we test them to verify that SSO is working as expected by the
706 // implementation.
707
708 // We use an arena to easily measure memory usage, but not needed.
709 Arena arena;
710 auto* array = Arena::Create<RepeatedPtrField<std::string>>(&arena);
711 EXPECT_EQ(array->Capacity(), 1);
712 EXPECT_EQ(array->SpaceUsedExcludingSelf(), 0);
713 std::string str;
714 auto usage_before = arena.SpaceUsed();
715 // We use UnsafeArenaAddAllocated just to grow the array without creating
716 // objects or causing extra cleanup costs in the arena to make the
717 // measurements simpler.
718 array->UnsafeArenaAddAllocated(&str);
719 // No backing array, just the string.
720 EXPECT_EQ(array->SpaceUsedExcludingSelf(), sizeof(str));
721 // We have not used any arena space.
722 EXPECT_EQ(usage_before, arena.SpaceUsed());
723 // Verify the string is where we think it is.
724 EXPECT_EQ(&*array->begin(), &str);
725 EXPECT_EQ(array->pointer_begin()[0], &str);
726 auto is_inlined = [array]() {
727 return std::less_equal<void*>{}(array, &*array->pointer_begin()) &&
728 std::less<void*>{}(&*array->pointer_begin(), array + 1);
729 };
730 // The T** in pointer_begin points into the sso in the object.
731 EXPECT_TRUE(is_inlined());
732
733 // Adding a second object stops sso.
734 std::string str2;
735 array->UnsafeArenaAddAllocated(&str2);
736 EXPECT_EQ(array->Capacity(), 3);
737 // Backing array and the strings.
738 EXPECT_EQ(array->SpaceUsedExcludingSelf(),
739 (1 + array->Capacity()) * sizeof(void*) + 2 * sizeof(str));
740 // We used some arena space now.
741 EXPECT_LT(usage_before, arena.SpaceUsed());
742 // And the pointer_begin is not in the sso anymore.
743 EXPECT_FALSE(is_inlined());
744 }
745
TEST(RepeatedPtrField,CopyAssign)746 TEST(RepeatedPtrField, CopyAssign) {
747 RepeatedPtrField<std::string> source, destination;
748 source.Add()->assign("4");
749 source.Add()->assign("5");
750 destination.Add()->assign("1");
751 destination.Add()->assign("2");
752 destination.Add()->assign("3");
753
754 destination = source;
755
756 ASSERT_EQ(2, destination.size());
757 EXPECT_EQ("4", destination.Get(0));
758 EXPECT_EQ("5", destination.Get(1));
759 }
760
TEST(RepeatedPtrField,SelfAssign)761 TEST(RepeatedPtrField, SelfAssign) {
762 // Verify that assignment to self does not destroy data.
763 RepeatedPtrField<std::string> source, *p;
764 p = &source;
765 source.Add()->assign("7");
766 source.Add()->assign("8");
767
768 *p = source;
769
770 ASSERT_EQ(2, source.size());
771 EXPECT_EQ("7", source.Get(0));
772 EXPECT_EQ("8", source.Get(1));
773 }
774
TEST(RepeatedPtrField,MoveConstruct)775 TEST(RepeatedPtrField, MoveConstruct) {
776 {
777 RepeatedPtrField<std::string> source;
778 *source.Add() = "1";
779 *source.Add() = "2";
780 const std::string* const* data = source.data();
781 RepeatedPtrField<std::string> destination = std::move(source);
782 EXPECT_EQ(data, destination.data());
783 EXPECT_THAT(destination, ElementsAre("1", "2"));
784 // This property isn't guaranteed but it's useful to have a test that would
785 // catch changes in this area.
786 EXPECT_TRUE(source.empty());
787 }
788 {
789 Arena arena;
790 RepeatedPtrField<std::string>* source =
791 Arena::Create<RepeatedPtrField<std::string>>(&arena);
792 *source->Add() = "1";
793 *source->Add() = "2";
794 RepeatedPtrField<std::string> destination = std::move(*source);
795 EXPECT_EQ(nullptr, destination.GetArena());
796 EXPECT_THAT(destination, ElementsAre("1", "2"));
797 // This property isn't guaranteed but it's useful to have a test that would
798 // catch changes in this area.
799 EXPECT_THAT(*source, ElementsAre("1", "2"));
800 }
801 }
802
TEST(RepeatedPtrField,MoveAssign)803 TEST(RepeatedPtrField, MoveAssign) {
804 {
805 RepeatedPtrField<std::string> source;
806 *source.Add() = "1";
807 *source.Add() = "2";
808 RepeatedPtrField<std::string> destination;
809 *destination.Add() = "3";
810 const std::string* const* source_data = source.data();
811 destination = std::move(source);
812 EXPECT_EQ(source_data, destination.data());
813 EXPECT_THAT(destination, ElementsAre("1", "2"));
814 EXPECT_THAT(source, ElementsAre("3"));
815 }
816 {
817 Arena arena;
818 RepeatedPtrField<std::string>* source =
819 Arena::Create<RepeatedPtrField<std::string>>(&arena);
820 *source->Add() = "1";
821 *source->Add() = "2";
822 RepeatedPtrField<std::string>* destination =
823 Arena::Create<RepeatedPtrField<std::string>>(&arena);
824 *destination->Add() = "3";
825 const std::string* const* source_data = source->data();
826 *destination = std::move(*source);
827 EXPECT_EQ(source_data, destination->data());
828 EXPECT_THAT(*destination, ElementsAre("1", "2"));
829 EXPECT_THAT(*source, ElementsAre("3"));
830 }
831 {
832 Arena source_arena;
833 RepeatedPtrField<std::string>* source =
834 Arena::Create<RepeatedPtrField<std::string>>(&source_arena);
835 *source->Add() = "1";
836 *source->Add() = "2";
837 Arena destination_arena;
838 RepeatedPtrField<std::string>* destination =
839 Arena::Create<RepeatedPtrField<std::string>>(&destination_arena);
840 *destination->Add() = "3";
841 *destination = std::move(*source);
842 EXPECT_THAT(*destination, ElementsAre("1", "2"));
843 // This property isn't guaranteed but it's useful to have a test that would
844 // catch changes in this area.
845 EXPECT_THAT(*source, ElementsAre("1", "2"));
846 }
847 {
848 Arena arena;
849 RepeatedPtrField<std::string>* source =
850 Arena::Create<RepeatedPtrField<std::string>>(&arena);
851 *source->Add() = "1";
852 *source->Add() = "2";
853 RepeatedPtrField<std::string> destination;
854 *destination.Add() = "3";
855 destination = std::move(*source);
856 EXPECT_THAT(destination, ElementsAre("1", "2"));
857 // This property isn't guaranteed but it's useful to have a test that would
858 // catch changes in this area.
859 EXPECT_THAT(*source, ElementsAre("1", "2"));
860 }
861 {
862 RepeatedPtrField<std::string> source;
863 *source.Add() = "1";
864 *source.Add() = "2";
865 Arena arena;
866 RepeatedPtrField<std::string>* destination =
867 Arena::Create<RepeatedPtrField<std::string>>(&arena);
868 *destination->Add() = "3";
869 *destination = std::move(source);
870 EXPECT_THAT(*destination, ElementsAre("1", "2"));
871 // This property isn't guaranteed but it's useful to have a test that would
872 // catch changes in this area.
873 EXPECT_THAT(source, ElementsAre("1", "2"));
874 }
875 {
876 RepeatedPtrField<std::string> field;
877 // An alias to defeat -Wself-move.
878 RepeatedPtrField<std::string>& alias = field;
879 *field.Add() = "1";
880 *field.Add() = "2";
881 const std::string* const* data = field.data();
882 field = std::move(alias);
883 EXPECT_EQ(data, field.data());
884 EXPECT_THAT(field, ElementsAre("1", "2"));
885 }
886 {
887 Arena arena;
888 RepeatedPtrField<std::string>* field =
889 Arena::Create<RepeatedPtrField<std::string>>(&arena);
890 *field->Add() = "1";
891 *field->Add() = "2";
892 const std::string* const* data = field->data();
893 *field = std::move(*field);
894 EXPECT_EQ(data, field->data());
895 EXPECT_THAT(*field, ElementsAre("1", "2"));
896 }
897 }
898
TEST(RepeatedPtrField,MutableDataIsMutable)899 TEST(RepeatedPtrField, MutableDataIsMutable) {
900 RepeatedPtrField<std::string> field;
901 *field.Add() = "1";
902 EXPECT_EQ("1", field.Get(0));
903 // The fact that this line compiles would be enough, but we'll check the
904 // value anyway.
905 std::string** data = field.mutable_data();
906 **data = "2";
907 EXPECT_EQ("2", field.Get(0));
908 }
909
TEST(RepeatedPtrField,SubscriptOperators)910 TEST(RepeatedPtrField, SubscriptOperators) {
911 RepeatedPtrField<std::string> field;
912 *field.Add() = "1";
913 EXPECT_EQ("1", field.Get(0));
914 EXPECT_EQ("1", field[0]);
915 EXPECT_EQ(field.Mutable(0), &field[0]);
916 const RepeatedPtrField<std::string>& const_field = field;
917 EXPECT_EQ(*field.data(), &const_field[0]);
918 }
919
TEST(RepeatedPtrField,ExtractSubrange)920 TEST(RepeatedPtrField, ExtractSubrange) {
921 // Exhaustively test every subrange in arrays of all sizes from 0 through 9
922 // with 0 through 3 cleared elements at the end.
923 for (int sz = 0; sz < 10; ++sz) {
924 for (int num = 0; num <= sz; ++num) {
925 for (int start = 0; start < sz - num; ++start) {
926 for (int extra = 0; extra < 4; ++extra) {
927 std::vector<std::string*> subject;
928
929 // Create an array with "sz" elements and "extra" cleared elements.
930 // Use an arena to avoid copies from debug-build stability checks.
931 Arena arena;
932 auto& field = *Arena::Create<RepeatedPtrField<std::string>>(&arena);
933 for (int i = 0; i < sz + extra; ++i) {
934 subject.push_back(new std::string());
935 field.AddAllocated(subject[i]);
936 }
937 EXPECT_EQ(field.size(), sz + extra);
938 for (int i = 0; i < extra; ++i) field.RemoveLast();
939 EXPECT_EQ(field.size(), sz);
940 EXPECT_EQ(field.ClearedCount(), extra);
941
942 // Create a catcher array and call ExtractSubrange.
943 std::string* catcher[10];
944 for (int i = 0; i < 10; ++i) catcher[i] = nullptr;
945 field.ExtractSubrange(start, num, catcher);
946
947 // Does the resulting array have the right size?
948 EXPECT_EQ(field.size(), sz - num);
949
950 // Were the removed elements extracted into the catcher array?
951 for (int i = 0; i < num; ++i)
952 EXPECT_EQ(*catcher[i], *subject[start + i]);
953 EXPECT_EQ(nullptr, catcher[num]);
954
955 // Does the resulting array contain the right values?
956 for (int i = 0; i < start; ++i)
957 EXPECT_EQ(field.Mutable(i), subject[i]);
958 for (int i = start; i < field.size(); ++i)
959 EXPECT_EQ(field.Mutable(i), subject[i + num]);
960
961 // Reinstate the cleared elements.
962 EXPECT_EQ(field.ClearedCount(), extra);
963 for (int i = 0; i < extra; ++i) field.Add();
964 EXPECT_EQ(field.ClearedCount(), 0);
965 EXPECT_EQ(field.size(), sz - num + extra);
966
967 // Make sure the extra elements are all there (in some order).
968 for (int i = sz; i < sz + extra; ++i) {
969 int count = 0;
970 for (int j = sz; j < sz + extra; ++j) {
971 if (field.Mutable(j - num) == subject[i]) count += 1;
972 }
973 EXPECT_EQ(count, 1);
974 }
975
976 // Release the caught elements.
977 for (int i = 0; i < num; ++i) delete catcher[i];
978 }
979 }
980 }
981 }
982 }
983
TEST(RepeatedPtrField,DeleteSubrange)984 TEST(RepeatedPtrField, DeleteSubrange) {
985 // DeleteSubrange is a trivial extension of ExtendSubrange.
986 }
987
TEST(RepeatedPtrField,Cleanups)988 TEST(RepeatedPtrField, Cleanups) {
989 Arena arena;
990 auto growth = internal::CleanupGrowth(
991 arena, [&] { Arena::Create<RepeatedPtrField<std::string>>(&arena); });
992 EXPECT_THAT(growth.cleanups, testing::IsEmpty());
993
994 growth = internal::CleanupGrowth(
995 arena, [&] { Arena::Create<RepeatedPtrField<TestAllTypes>>(&arena); });
996 EXPECT_THAT(growth.cleanups, testing::IsEmpty());
997 }
998
999
1000 // ===================================================================
1001
1002 class RepeatedPtrFieldIteratorTest : public testing::Test {
1003 protected:
SetUp()1004 void SetUp() override {
1005 proto_array_.Add()->assign("foo");
1006 proto_array_.Add()->assign("bar");
1007 proto_array_.Add()->assign("baz");
1008 }
1009
1010 RepeatedPtrField<std::string> proto_array_;
1011 };
1012
TEST_F(RepeatedPtrFieldIteratorTest,Convertible)1013 TEST_F(RepeatedPtrFieldIteratorTest, Convertible) {
1014 RepeatedPtrField<std::string>::iterator iter = proto_array_.begin();
1015 RepeatedPtrField<std::string>::const_iterator c_iter = iter;
1016 RepeatedPtrField<std::string>::value_type value = *c_iter;
1017 EXPECT_EQ("foo", value);
1018 }
1019
TEST_F(RepeatedPtrFieldIteratorTest,MutableIteration)1020 TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) {
1021 RepeatedPtrField<std::string>::iterator iter = proto_array_.begin();
1022 EXPECT_EQ("foo", *iter);
1023 ++iter;
1024 EXPECT_EQ("bar", *(iter++));
1025 EXPECT_EQ("baz", *iter);
1026 ++iter;
1027 EXPECT_TRUE(proto_array_.end() == iter);
1028 EXPECT_EQ("baz", *(--proto_array_.end()));
1029 }
1030
TEST_F(RepeatedPtrFieldIteratorTest,ConstIteration)1031 TEST_F(RepeatedPtrFieldIteratorTest, ConstIteration) {
1032 const RepeatedPtrField<std::string>& const_proto_array = proto_array_;
1033 RepeatedPtrField<std::string>::const_iterator iter =
1034 const_proto_array.begin();
1035 iter - const_proto_array.cbegin();
1036 EXPECT_EQ("foo", *iter);
1037 ++iter;
1038 EXPECT_EQ("bar", *(iter++));
1039 EXPECT_EQ("baz", *iter);
1040 ++iter;
1041 EXPECT_TRUE(const_proto_array.end() == iter);
1042 EXPECT_EQ("baz", *(--const_proto_array.end()));
1043 }
1044
TEST_F(RepeatedPtrFieldIteratorTest,MutableReverseIteration)1045 TEST_F(RepeatedPtrFieldIteratorTest, MutableReverseIteration) {
1046 RepeatedPtrField<std::string>::reverse_iterator iter = proto_array_.rbegin();
1047 EXPECT_EQ("baz", *iter);
1048 ++iter;
1049 EXPECT_EQ("bar", *(iter++));
1050 EXPECT_EQ("foo", *iter);
1051 ++iter;
1052 EXPECT_TRUE(proto_array_.rend() == iter);
1053 EXPECT_EQ("foo", *(--proto_array_.rend()));
1054 }
1055
TEST_F(RepeatedPtrFieldIteratorTest,ConstReverseIteration)1056 TEST_F(RepeatedPtrFieldIteratorTest, ConstReverseIteration) {
1057 const RepeatedPtrField<std::string>& const_proto_array = proto_array_;
1058 RepeatedPtrField<std::string>::const_reverse_iterator iter =
1059 const_proto_array.rbegin();
1060 EXPECT_EQ("baz", *iter);
1061 ++iter;
1062 EXPECT_EQ("bar", *(iter++));
1063 EXPECT_EQ("foo", *iter);
1064 ++iter;
1065 EXPECT_TRUE(const_proto_array.rend() == iter);
1066 EXPECT_EQ("foo", *(--const_proto_array.rend()));
1067 }
1068
TEST_F(RepeatedPtrFieldIteratorTest,RandomAccess)1069 TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) {
1070 RepeatedPtrField<std::string>::iterator iter = proto_array_.begin();
1071 RepeatedPtrField<std::string>::iterator iter2 = iter;
1072 ++iter2;
1073 ++iter2;
1074 EXPECT_TRUE(iter + 2 == iter2);
1075 EXPECT_TRUE(iter == iter2 - 2);
1076 EXPECT_EQ("baz", iter[2]);
1077 EXPECT_EQ("baz", *(iter + 2));
1078 EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
1079 }
1080
TEST_F(RepeatedPtrFieldIteratorTest,RandomAccessConst)1081 TEST_F(RepeatedPtrFieldIteratorTest, RandomAccessConst) {
1082 RepeatedPtrField<std::string>::const_iterator iter = proto_array_.cbegin();
1083 RepeatedPtrField<std::string>::const_iterator iter2 = iter;
1084 ++iter2;
1085 ++iter2;
1086 EXPECT_TRUE(iter + 2 == iter2);
1087 EXPECT_TRUE(iter == iter2 - 2);
1088 EXPECT_EQ("baz", iter[2]);
1089 EXPECT_EQ("baz", *(iter + 2));
1090 EXPECT_EQ(3, proto_array_.cend() - proto_array_.cbegin());
1091 }
1092
TEST_F(RepeatedPtrFieldIteratorTest,DifferenceConstConversion)1093 TEST_F(RepeatedPtrFieldIteratorTest, DifferenceConstConversion) {
1094 EXPECT_EQ(3, proto_array_.end() - proto_array_.cbegin());
1095 EXPECT_EQ(3, proto_array_.cend() - proto_array_.begin());
1096 }
1097
TEST_F(RepeatedPtrFieldIteratorTest,Comparable)1098 TEST_F(RepeatedPtrFieldIteratorTest, Comparable) {
1099 RepeatedPtrField<std::string>::const_iterator iter = proto_array_.begin();
1100 RepeatedPtrField<std::string>::const_iterator iter2 = iter + 1;
1101 EXPECT_TRUE(iter == iter);
1102 EXPECT_TRUE(iter != iter2);
1103 EXPECT_TRUE(iter < iter2);
1104 EXPECT_TRUE(iter <= iter2);
1105 EXPECT_TRUE(iter <= iter);
1106 EXPECT_TRUE(iter2 > iter);
1107 EXPECT_TRUE(iter2 >= iter);
1108 EXPECT_TRUE(iter >= iter);
1109 }
1110
TEST_F(RepeatedPtrFieldIteratorTest,ComparableConstConversion)1111 TEST_F(RepeatedPtrFieldIteratorTest, ComparableConstConversion) {
1112 RepeatedPtrField<std::string>::iterator iter = proto_array_.begin();
1113 RepeatedPtrField<std::string>::const_iterator iter2 = iter + 1;
1114 EXPECT_TRUE(iter == iter);
1115 EXPECT_TRUE(iter == proto_array_.cbegin());
1116 EXPECT_TRUE(proto_array_.cbegin() == iter);
1117 EXPECT_TRUE(iter != iter2);
1118 EXPECT_TRUE(iter2 != iter);
1119 EXPECT_TRUE(iter < iter2);
1120 EXPECT_TRUE(iter <= iter2);
1121 EXPECT_TRUE(iter <= iter);
1122 EXPECT_TRUE(iter2 > iter);
1123 EXPECT_TRUE(iter2 >= iter);
1124 EXPECT_TRUE(iter >= iter);
1125 }
1126
1127 // Uninitialized iterator does not point to any of the RepeatedPtrField.
TEST_F(RepeatedPtrFieldIteratorTest,UninitializedIterator)1128 TEST_F(RepeatedPtrFieldIteratorTest, UninitializedIterator) {
1129 RepeatedPtrField<std::string>::iterator iter;
1130 EXPECT_TRUE(iter != proto_array_.begin());
1131 EXPECT_TRUE(iter != proto_array_.begin() + 1);
1132 EXPECT_TRUE(iter != proto_array_.begin() + 2);
1133 EXPECT_TRUE(iter != proto_array_.begin() + 3);
1134 EXPECT_TRUE(iter != proto_array_.end());
1135 }
1136
TEST_F(RepeatedPtrFieldIteratorTest,STLAlgorithms_lower_bound)1137 TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) {
1138 proto_array_.Clear();
1139 proto_array_.Add()->assign("a");
1140 proto_array_.Add()->assign("c");
1141 proto_array_.Add()->assign("d");
1142 proto_array_.Add()->assign("n");
1143 proto_array_.Add()->assign("p");
1144 proto_array_.Add()->assign("x");
1145 proto_array_.Add()->assign("y");
1146
1147 std::string v = "f";
1148 RepeatedPtrField<std::string>::const_iterator it =
1149 std::lower_bound(proto_array_.begin(), proto_array_.end(), v);
1150
1151 EXPECT_EQ(*it, "n");
1152 EXPECT_TRUE(it == proto_array_.begin() + 3);
1153 }
1154
TEST_F(RepeatedPtrFieldIteratorTest,Mutation)1155 TEST_F(RepeatedPtrFieldIteratorTest, Mutation) {
1156 RepeatedPtrField<std::string>::iterator iter = proto_array_.begin();
1157 *iter = "moo";
1158 EXPECT_EQ("moo", proto_array_.Get(0));
1159 }
1160
1161 // -------------------------------------------------------------------
1162
1163 class RepeatedPtrFieldPtrsIteratorTest : public testing::Test {
1164 protected:
SetUp()1165 void SetUp() override {
1166 proto_array_.Add()->assign("foo");
1167 proto_array_.Add()->assign("bar");
1168 proto_array_.Add()->assign("baz");
1169 const_proto_array_ = &proto_array_;
1170 }
1171
1172 RepeatedPtrField<std::string> proto_array_;
1173 const RepeatedPtrField<std::string>* const_proto_array_;
1174 };
1175
TEST_F(RepeatedPtrFieldPtrsIteratorTest,ConvertiblePtr)1176 TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) {
1177 RepeatedPtrField<std::string>::pointer_iterator iter =
1178 proto_array_.pointer_begin();
1179 static_cast<void>(iter);
1180 }
1181
TEST_F(RepeatedPtrFieldPtrsIteratorTest,ConvertibleConstPtr)1182 TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) {
1183 RepeatedPtrField<std::string>::const_pointer_iterator iter =
1184 const_proto_array_->pointer_begin();
1185 static_cast<void>(iter);
1186 }
1187
TEST_F(RepeatedPtrFieldPtrsIteratorTest,MutablePtrIteration)1188 TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) {
1189 RepeatedPtrField<std::string>::pointer_iterator iter =
1190 proto_array_.pointer_begin();
1191 EXPECT_EQ("foo", **iter);
1192 ++iter;
1193 EXPECT_EQ("bar", **(iter++));
1194 EXPECT_EQ("baz", **iter);
1195 ++iter;
1196 EXPECT_TRUE(proto_array_.pointer_end() == iter);
1197 EXPECT_EQ("baz", **(--proto_array_.pointer_end()));
1198 }
1199
TEST_F(RepeatedPtrFieldPtrsIteratorTest,MutableConstPtrIteration)1200 TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutableConstPtrIteration) {
1201 RepeatedPtrField<std::string>::const_pointer_iterator iter =
1202 const_proto_array_->pointer_begin();
1203 EXPECT_EQ("foo", **iter);
1204 ++iter;
1205 EXPECT_EQ("bar", **(iter++));
1206 EXPECT_EQ("baz", **iter);
1207 ++iter;
1208 EXPECT_TRUE(const_proto_array_->pointer_end() == iter);
1209 EXPECT_EQ("baz", **(--const_proto_array_->pointer_end()));
1210 }
1211
TEST_F(RepeatedPtrFieldPtrsIteratorTest,RandomPtrAccess)1212 TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) {
1213 RepeatedPtrField<std::string>::pointer_iterator iter =
1214 proto_array_.pointer_begin();
1215 RepeatedPtrField<std::string>::pointer_iterator iter2 = iter;
1216 ++iter2;
1217 ++iter2;
1218 EXPECT_TRUE(iter + 2 == iter2);
1219 EXPECT_TRUE(iter == iter2 - 2);
1220 EXPECT_EQ("baz", *iter[2]);
1221 EXPECT_EQ("baz", **(iter + 2));
1222 EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
1223 }
1224
TEST_F(RepeatedPtrFieldPtrsIteratorTest,RandomConstPtrAccess)1225 TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomConstPtrAccess) {
1226 RepeatedPtrField<std::string>::const_pointer_iterator iter =
1227 const_proto_array_->pointer_begin();
1228 RepeatedPtrField<std::string>::const_pointer_iterator iter2 = iter;
1229 ++iter2;
1230 ++iter2;
1231 EXPECT_TRUE(iter + 2 == iter2);
1232 EXPECT_TRUE(iter == iter2 - 2);
1233 EXPECT_EQ("baz", *iter[2]);
1234 EXPECT_EQ("baz", **(iter + 2));
1235 EXPECT_EQ(3, const_proto_array_->end() - const_proto_array_->begin());
1236 }
1237
TEST_F(RepeatedPtrFieldPtrsIteratorTest,DifferenceConstConversion)1238 TEST_F(RepeatedPtrFieldPtrsIteratorTest, DifferenceConstConversion) {
1239 EXPECT_EQ(3,
1240 proto_array_.pointer_end() - const_proto_array_->pointer_begin());
1241 EXPECT_EQ(3,
1242 const_proto_array_->pointer_end() - proto_array_.pointer_begin());
1243 }
1244
TEST_F(RepeatedPtrFieldPtrsIteratorTest,ComparablePtr)1245 TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) {
1246 RepeatedPtrField<std::string>::pointer_iterator iter =
1247 proto_array_.pointer_begin();
1248 RepeatedPtrField<std::string>::pointer_iterator iter2 = iter + 1;
1249 EXPECT_TRUE(iter == iter);
1250 EXPECT_TRUE(iter != iter2);
1251 EXPECT_TRUE(iter < iter2);
1252 EXPECT_TRUE(iter <= iter2);
1253 EXPECT_TRUE(iter <= iter);
1254 EXPECT_TRUE(iter2 > iter);
1255 EXPECT_TRUE(iter2 >= iter);
1256 EXPECT_TRUE(iter >= iter);
1257 }
1258
TEST_F(RepeatedPtrFieldPtrsIteratorTest,ComparableConstPtr)1259 TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstPtr) {
1260 RepeatedPtrField<std::string>::const_pointer_iterator iter =
1261 const_proto_array_->pointer_begin();
1262 RepeatedPtrField<std::string>::const_pointer_iterator iter2 = iter + 1;
1263 EXPECT_TRUE(iter == iter);
1264 EXPECT_TRUE(iter != iter2);
1265 EXPECT_TRUE(iter < iter2);
1266 EXPECT_TRUE(iter <= iter2);
1267 EXPECT_TRUE(iter <= iter);
1268 EXPECT_TRUE(iter2 > iter);
1269 EXPECT_TRUE(iter2 >= iter);
1270 EXPECT_TRUE(iter >= iter);
1271 }
1272
TEST_F(RepeatedPtrFieldPtrsIteratorTest,ComparableConstConversion)1273 TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstConversion) {
1274 RepeatedPtrField<std::string>::pointer_iterator iter =
1275 proto_array_.pointer_begin();
1276 RepeatedPtrField<std::string>::const_pointer_iterator iter2 = iter + 1;
1277 EXPECT_TRUE(iter == iter);
1278 EXPECT_TRUE(iter == const_proto_array_->pointer_begin());
1279 EXPECT_TRUE(const_proto_array_->pointer_begin() == iter);
1280 EXPECT_TRUE(iter != iter2);
1281 EXPECT_TRUE(iter2 != iter);
1282 EXPECT_TRUE(iter < iter2);
1283 EXPECT_TRUE(iter <= iter2);
1284 EXPECT_TRUE(iter <= iter);
1285 EXPECT_TRUE(iter2 > iter);
1286 EXPECT_TRUE(iter2 >= iter);
1287 EXPECT_TRUE(iter >= iter);
1288 }
1289
1290 // Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs.
1291 // Dereferencing an uninitialized iterator crashes the process.
TEST_F(RepeatedPtrFieldPtrsIteratorTest,UninitializedPtrIterator)1292 TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) {
1293 RepeatedPtrField<std::string>::pointer_iterator iter;
1294 EXPECT_TRUE(iter != proto_array_.pointer_begin());
1295 EXPECT_TRUE(iter != proto_array_.pointer_begin() + 1);
1296 EXPECT_TRUE(iter != proto_array_.pointer_begin() + 2);
1297 EXPECT_TRUE(iter != proto_array_.pointer_begin() + 3);
1298 EXPECT_TRUE(iter != proto_array_.pointer_end());
1299 }
1300
TEST_F(RepeatedPtrFieldPtrsIteratorTest,UninitializedConstPtrIterator)1301 TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedConstPtrIterator) {
1302 RepeatedPtrField<std::string>::const_pointer_iterator iter;
1303 EXPECT_TRUE(iter != const_proto_array_->pointer_begin());
1304 EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 1);
1305 EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 2);
1306 EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 3);
1307 EXPECT_TRUE(iter != const_proto_array_->pointer_end());
1308 }
1309
1310 // This comparison functor is required by the tests for RepeatedPtrOverPtrs.
1311 // They operate on strings and need to compare strings as strings in
1312 // any stl algorithm, even though the iterator returns a pointer to a
1313 // string
1314 // - i.e. *iter has type std::string*.
1315 struct StringLessThan {
operator ()google::protobuf::__anon8b66761c0111::StringLessThan1316 bool operator()(const std::string* z, const std::string* y) const {
1317 return *z < *y;
1318 }
1319 };
1320
TEST_F(RepeatedPtrFieldPtrsIteratorTest,PtrSTLAlgorithms_lower_bound)1321 TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) {
1322 proto_array_.Clear();
1323 proto_array_.Add()->assign("a");
1324 proto_array_.Add()->assign("c");
1325 proto_array_.Add()->assign("d");
1326 proto_array_.Add()->assign("n");
1327 proto_array_.Add()->assign("p");
1328 proto_array_.Add()->assign("x");
1329 proto_array_.Add()->assign("y");
1330
1331 {
1332 std::string v = "f";
1333 RepeatedPtrField<std::string>::pointer_iterator it =
1334 std::lower_bound(proto_array_.pointer_begin(),
1335 proto_array_.pointer_end(), &v, StringLessThan());
1336
1337 ABSL_CHECK(*it != nullptr);
1338
1339 EXPECT_EQ(**it, "n");
1340 EXPECT_TRUE(it == proto_array_.pointer_begin() + 3);
1341 }
1342 {
1343 std::string v = "f";
1344 RepeatedPtrField<std::string>::const_pointer_iterator it = std::lower_bound(
1345 const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(),
1346 &v, StringLessThan());
1347
1348 ABSL_CHECK(*it != nullptr);
1349
1350 EXPECT_EQ(**it, "n");
1351 EXPECT_EQ(it, const_proto_array_->pointer_begin() + 3);
1352 }
1353 }
1354
TEST_F(RepeatedPtrFieldPtrsIteratorTest,PtrMutation)1355 TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) {
1356 RepeatedPtrField<std::string>::pointer_iterator iter =
1357 proto_array_.pointer_begin();
1358 **iter = "moo";
1359 EXPECT_EQ("moo", proto_array_.Get(0));
1360
1361 EXPECT_EQ("bar", proto_array_.Get(1));
1362 EXPECT_EQ("baz", proto_array_.Get(2));
1363 ++iter;
1364 delete *iter;
1365 *iter = new std::string("a");
1366 ++iter;
1367 delete *iter;
1368 *iter = new std::string("b");
1369 EXPECT_EQ("a", proto_array_.Get(1));
1370 EXPECT_EQ("b", proto_array_.Get(2));
1371 }
1372
TEST_F(RepeatedPtrFieldPtrsIteratorTest,Sort)1373 TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) {
1374 proto_array_.Add()->assign("c");
1375 proto_array_.Add()->assign("d");
1376 proto_array_.Add()->assign("n");
1377 proto_array_.Add()->assign("p");
1378 proto_array_.Add()->assign("a");
1379 proto_array_.Add()->assign("y");
1380 proto_array_.Add()->assign("x");
1381 EXPECT_EQ("foo", proto_array_.Get(0));
1382 EXPECT_EQ("n", proto_array_.Get(5));
1383 EXPECT_EQ("x", proto_array_.Get(9));
1384 std::sort(proto_array_.pointer_begin(), proto_array_.pointer_end(),
1385 StringLessThan());
1386 EXPECT_EQ("a", proto_array_.Get(0));
1387 EXPECT_EQ("baz", proto_array_.Get(2));
1388 EXPECT_EQ("y", proto_array_.Get(9));
1389 }
1390
1391 // -----------------------------------------------------------------------------
1392 // Unit-tests for the insert iterators
1393 // `google::protobuf::RepeatedPtrFieldBackInserter`,
1394 // `google::protobuf::AllocatedRepeatedPtrFieldBackInserter`
1395 // Ported from util/gtl/proto-array-iterators_unittest.
1396
1397 class RepeatedPtrFieldInsertionIteratorsTest : public testing::Test {
1398 protected:
1399 using Nested = TestAllTypes::NestedMessage;
1400
1401 std::vector<std::string> words_;
1402 Nested nesteds_[2];
1403 std::vector<Nested*> nested_ptrs_;
1404 TestAllTypes protobuffer_;
1405
SetUp()1406 void SetUp() override {
1407 words_.push_back("Able");
1408 words_.push_back("was");
1409 words_.push_back("I");
1410 words_.push_back("ere");
1411 words_.push_back("I");
1412 words_.push_back("saw");
1413 words_.push_back("Elba");
1414 std::copy(
1415 words_.begin(), words_.end(),
1416 RepeatedFieldBackInserter(protobuffer_.mutable_repeated_string()));
1417
1418 nesteds_[0].set_bb(17);
1419 nesteds_[1].set_bb(4711);
1420 std::copy(&nesteds_[0], &nesteds_[2],
1421 RepeatedFieldBackInserter(
1422 protobuffer_.mutable_repeated_nested_message()));
1423
1424 nested_ptrs_.push_back(new Nested);
1425 nested_ptrs_.back()->set_bb(170);
1426 nested_ptrs_.push_back(new Nested);
1427 nested_ptrs_.back()->set_bb(47110);
1428 std::copy(nested_ptrs_.begin(), nested_ptrs_.end(),
1429 RepeatedFieldBackInserter(
1430 protobuffer_.mutable_repeated_nested_message()));
1431 }
1432
TearDown()1433 void TearDown() override {
1434 for (auto ptr : nested_ptrs_) {
1435 delete ptr;
1436 }
1437 }
1438 };
1439
TEST_F(RepeatedPtrFieldInsertionIteratorsTest,Words1)1440 TEST_F(RepeatedPtrFieldInsertionIteratorsTest, Words1) {
1441 ASSERT_EQ(words_.size(), protobuffer_.repeated_string_size());
1442 for (size_t i = 0; i < words_.size(); ++i) {
1443 EXPECT_EQ(words_.at(i), protobuffer_.repeated_string(i));
1444 }
1445 }
1446
TEST_F(RepeatedPtrFieldInsertionIteratorsTest,Words2)1447 TEST_F(RepeatedPtrFieldInsertionIteratorsTest, Words2) {
1448 words_.clear();
1449 words_.push_back("sing");
1450 words_.push_back("a");
1451 words_.push_back("song");
1452 words_.push_back("of");
1453 words_.push_back("six");
1454 words_.push_back("pence");
1455 protobuffer_.mutable_repeated_string()->Clear();
1456 std::copy(
1457 words_.begin(), words_.end(),
1458 RepeatedPtrFieldBackInserter(protobuffer_.mutable_repeated_string()));
1459 ASSERT_EQ(words_.size(), protobuffer_.repeated_string_size());
1460 for (size_t i = 0; i < words_.size(); ++i) {
1461 EXPECT_EQ(words_.at(i), protobuffer_.repeated_string(i));
1462 }
1463 }
1464
TEST_F(RepeatedPtrFieldInsertionIteratorsTest,Nesteds)1465 TEST_F(RepeatedPtrFieldInsertionIteratorsTest, Nesteds) {
1466 ASSERT_EQ(protobuffer_.repeated_nested_message_size(), 4);
1467 EXPECT_EQ(protobuffer_.repeated_nested_message(0).bb(), 17);
1468 EXPECT_EQ(protobuffer_.repeated_nested_message(1).bb(), 4711);
1469 EXPECT_EQ(protobuffer_.repeated_nested_message(2).bb(), 170);
1470 EXPECT_EQ(protobuffer_.repeated_nested_message(3).bb(), 47110);
1471 }
1472
TEST_F(RepeatedPtrFieldInsertionIteratorsTest,AllocatedRepeatedPtrFieldWithStringIntData)1473 TEST_F(RepeatedPtrFieldInsertionIteratorsTest,
1474 AllocatedRepeatedPtrFieldWithStringIntData) {
1475 std::vector<Nested*> data;
1476 TestAllTypes goldenproto;
1477 for (int i = 0; i < 10; ++i) {
1478 Nested* new_data = new Nested;
1479 new_data->set_bb(i);
1480 data.push_back(new_data);
1481
1482 new_data = goldenproto.add_repeated_nested_message();
1483 new_data->set_bb(i);
1484 }
1485 TestAllTypes testproto;
1486 std::copy(data.begin(), data.end(),
1487 AllocatedRepeatedPtrFieldBackInserter(
1488 testproto.mutable_repeated_nested_message()));
1489 EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
1490 }
1491
TEST_F(RepeatedPtrFieldInsertionIteratorsTest,AllocatedRepeatedPtrFieldWithString)1492 TEST_F(RepeatedPtrFieldInsertionIteratorsTest,
1493 AllocatedRepeatedPtrFieldWithString) {
1494 std::vector<std::string*> data;
1495 TestAllTypes goldenproto;
1496 for (int i = 0; i < 10; ++i) {
1497 std::string* new_data = new std::string;
1498 *new_data = absl::StrCat("name-", i);
1499 data.push_back(new_data);
1500
1501 new_data = goldenproto.add_repeated_string();
1502 *new_data = absl::StrCat("name-", i);
1503 }
1504 TestAllTypes testproto;
1505 std::copy(data.begin(), data.end(),
1506 AllocatedRepeatedPtrFieldBackInserter(
1507 testproto.mutable_repeated_string()));
1508 EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
1509 }
1510
TEST_F(RepeatedPtrFieldInsertionIteratorsTest,UnsafeArenaAllocatedRepeatedPtrFieldWithStringIntData)1511 TEST_F(RepeatedPtrFieldInsertionIteratorsTest,
1512 UnsafeArenaAllocatedRepeatedPtrFieldWithStringIntData) {
1513 std::vector<Nested*> data;
1514 Arena arena;
1515 auto* goldenproto = Arena::Create<TestAllTypes>(&arena);
1516 for (int i = 0; i < 10; ++i) {
1517 auto* new_data = goldenproto->add_repeated_nested_message();
1518 new_data->set_bb(i);
1519 data.push_back(new_data);
1520 }
1521 auto* testproto = Arena::Create<TestAllTypes>(&arena);
1522 std::copy(data.begin(), data.end(),
1523 UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
1524 testproto->mutable_repeated_nested_message()));
1525 EXPECT_EQ(testproto->DebugString(), goldenproto->DebugString());
1526 }
1527
TEST_F(RepeatedPtrFieldInsertionIteratorsTest,UnsafeArenaAllocatedRepeatedPtrFieldWithString)1528 TEST_F(RepeatedPtrFieldInsertionIteratorsTest,
1529 UnsafeArenaAllocatedRepeatedPtrFieldWithString) {
1530 std::vector<std::string*> data;
1531 Arena arena;
1532 auto* goldenproto = Arena::Create<TestAllTypes>(&arena);
1533 for (int i = 0; i < 10; ++i) {
1534 auto* new_data = goldenproto->add_repeated_string();
1535 *new_data = absl::StrCat("name-", i);
1536 data.push_back(new_data);
1537 }
1538 auto* testproto = Arena::Create<TestAllTypes>(&arena);
1539 std::copy(data.begin(), data.end(),
1540 UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
1541 testproto->mutable_repeated_string()));
1542 EXPECT_EQ(testproto->DebugString(), goldenproto->DebugString());
1543 }
1544
TEST_F(RepeatedPtrFieldInsertionIteratorsTest,MoveStrings)1545 TEST_F(RepeatedPtrFieldInsertionIteratorsTest, MoveStrings) {
1546 std::vector<std::string> src = {"a", "b", "c", "d"};
1547 std::vector<std::string> copy =
1548 src; // copy since move leaves in undefined state
1549 TestAllTypes testproto;
1550 std::move(copy.begin(), copy.end(),
1551 RepeatedFieldBackInserter(testproto.mutable_repeated_string()));
1552
1553 ASSERT_THAT(testproto.repeated_string(), testing::ElementsAreArray(src));
1554 }
1555
TEST_F(RepeatedPtrFieldInsertionIteratorsTest,MoveProtos)1556 TEST_F(RepeatedPtrFieldInsertionIteratorsTest, MoveProtos) {
1557 auto make_nested = [](int32_t x) {
1558 Nested ret;
1559 ret.set_bb(x);
1560 return ret;
1561 };
1562 std::vector<Nested> src = {make_nested(3), make_nested(5), make_nested(7)};
1563 std::vector<Nested> copy = src; // copy since move leaves in undefined state
1564 TestAllTypes testproto;
1565 std::move(
1566 copy.begin(), copy.end(),
1567 RepeatedFieldBackInserter(testproto.mutable_repeated_nested_message()));
1568
1569 ASSERT_EQ(src.size(), testproto.repeated_nested_message_size());
1570 for (int i = 0; i < src.size(); ++i) {
1571 EXPECT_EQ(src[i].DebugString(),
1572 testproto.repeated_nested_message(i).DebugString());
1573 }
1574 }
1575
1576 } // namespace
1577
1578 } // namespace protobuf
1579 } // namespace google
1580
1581 #include "google/protobuf/port_undef.inc"
1582