1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34 //
35 // TODO(kenton): Improve this unittest to bring it up to the standards of
36 // other proto2 unittests.
37
38 #include <algorithm>
39 #include <list>
40 #include <vector>
41
42 #include <google/protobuf/repeated_field.h>
43
44 #include <google/protobuf/stubs/common.h>
45 #include <google/protobuf/unittest.pb.h>
46 #include <google/protobuf/stubs/strutil.h>
47 #include <google/protobuf/testing/googletest.h>
48 #include <gtest/gtest.h>
49 #include <google/protobuf/stubs/stl_util-inl.h>
50
51 namespace google {
52 using protobuf_unittest::TestAllTypes;
53
54 namespace protobuf {
55 namespace {
56
57 // Test operations on a RepeatedField which is small enough that it does
58 // not allocate a separate array for storage.
TEST(RepeatedField,Small)59 TEST(RepeatedField, Small) {
60 RepeatedField<int> field;
61
62 EXPECT_EQ(field.size(), 0);
63
64 field.Add(5);
65
66 EXPECT_EQ(field.size(), 1);
67 EXPECT_EQ(field.Get(0), 5);
68
69 field.Add(42);
70
71 EXPECT_EQ(field.size(), 2);
72 EXPECT_EQ(field.Get(0), 5);
73 EXPECT_EQ(field.Get(1), 42);
74
75 field.Set(1, 23);
76
77 EXPECT_EQ(field.size(), 2);
78 EXPECT_EQ(field.Get(0), 5);
79 EXPECT_EQ(field.Get(1), 23);
80 EXPECT_EQ(field.SpaceUsedExcludingSelf(), 0);
81
82 field.RemoveLast();
83
84 EXPECT_EQ(field.size(), 1);
85 EXPECT_EQ(field.Get(0), 5);
86
87 field.Clear();
88
89 EXPECT_EQ(field.size(), 0);
90 EXPECT_EQ(field.SpaceUsedExcludingSelf(), 0);
91 }
92
93 // Test operations on a RepeatedField which is large enough to allocate a
94 // separate array.
TEST(RepeatedField,Large)95 TEST(RepeatedField, Large) {
96 RepeatedField<int> field;
97
98 for (int i = 0; i < 16; i++) {
99 field.Add(i * i);
100 }
101
102 EXPECT_EQ(field.size(), 16);
103
104 for (int i = 0; i < 16; i++) {
105 EXPECT_EQ(field.Get(i), i * i);
106 }
107
108 int expected_usage = 16 * sizeof(int);
109 EXPECT_GE(field.SpaceUsedExcludingSelf(), expected_usage);
110 }
111
112 // Test swapping between various types of RepeatedFields.
TEST(RepeatedField,SwapSmallSmall)113 TEST(RepeatedField, SwapSmallSmall) {
114 RepeatedField<int> field1;
115 RepeatedField<int> field2;
116
117 field1.Add(5);
118 field1.Add(42);
119
120 field1.Swap(&field2);
121
122 EXPECT_EQ(field1.size(), 0);
123 EXPECT_EQ(field2.size(), 2);
124 EXPECT_EQ(field2.Get(0), 5);
125 EXPECT_EQ(field2.Get(1), 42);
126 }
127
TEST(RepeatedField,SwapLargeSmall)128 TEST(RepeatedField, SwapLargeSmall) {
129 RepeatedField<int> field1;
130 RepeatedField<int> field2;
131
132 for (int i = 0; i < 16; i++) {
133 field1.Add(i * i);
134 }
135 field2.Add(5);
136 field2.Add(42);
137 field1.Swap(&field2);
138
139 EXPECT_EQ(field1.size(), 2);
140 EXPECT_EQ(field1.Get(0), 5);
141 EXPECT_EQ(field1.Get(1), 42);
142 EXPECT_EQ(field2.size(), 16);
143 for (int i = 0; i < 16; i++) {
144 EXPECT_EQ(field2.Get(i), i * i);
145 }
146 }
147
TEST(RepeatedField,SwapLargeLarge)148 TEST(RepeatedField, SwapLargeLarge) {
149 RepeatedField<int> field1;
150 RepeatedField<int> field2;
151
152 field1.Add(5);
153 field1.Add(42);
154 for (int i = 0; i < 16; i++) {
155 field1.Add(i);
156 field2.Add(i * i);
157 }
158 field2.Swap(&field1);
159
160 EXPECT_EQ(field1.size(), 16);
161 for (int i = 0; i < 16; i++) {
162 EXPECT_EQ(field1.Get(i), i * i);
163 }
164 EXPECT_EQ(field2.size(), 18);
165 EXPECT_EQ(field2.Get(0), 5);
166 EXPECT_EQ(field2.Get(1), 42);
167 for (int i = 2; i < 18; i++) {
168 EXPECT_EQ(field2.Get(i), i - 2);
169 }
170 }
171
172 // Determines how much space was reserved by the given field by adding elements
173 // to it until it re-allocates its space.
ReservedSpace(RepeatedField<int> * field)174 static int ReservedSpace(RepeatedField<int>* field) {
175 const int* ptr = field->data();
176 do {
177 field->Add(0);
178 } while (field->data() == ptr);
179
180 return field->size() - 1;
181 }
182
TEST(RepeatedField,ReserveMoreThanDouble)183 TEST(RepeatedField, ReserveMoreThanDouble) {
184 // Reserve more than double the previous space in the field and expect the
185 // field to reserve exactly the amount specified.
186 RepeatedField<int> field;
187 field.Reserve(20);
188
189 EXPECT_EQ(20, ReservedSpace(&field));
190 }
191
TEST(RepeatedField,ReserveLessThanDouble)192 TEST(RepeatedField, ReserveLessThanDouble) {
193 // Reserve less than double the previous space in the field and expect the
194 // field to grow by double instead.
195 RepeatedField<int> field;
196 field.Reserve(20);
197 field.Reserve(30);
198
199 EXPECT_EQ(40, ReservedSpace(&field));
200 }
201
TEST(RepeatedField,ReserveLessThanExisting)202 TEST(RepeatedField, ReserveLessThanExisting) {
203 // Reserve less than the previous space in the field and expect the
204 // field to not re-allocate at all.
205 RepeatedField<int> field;
206 field.Reserve(20);
207 const int* previous_ptr = field.data();
208 field.Reserve(10);
209
210 EXPECT_EQ(previous_ptr, field.data());
211 EXPECT_EQ(20, ReservedSpace(&field));
212 }
213
TEST(RepeatedField,MergeFrom)214 TEST(RepeatedField, MergeFrom) {
215 RepeatedField<int> source, destination;
216
217 source.Add(4);
218 source.Add(5);
219
220 destination.Add(1);
221 destination.Add(2);
222 destination.Add(3);
223
224 destination.MergeFrom(source);
225
226 ASSERT_EQ(5, destination.size());
227
228 EXPECT_EQ(1, destination.Get(0));
229 EXPECT_EQ(2, destination.Get(1));
230 EXPECT_EQ(3, destination.Get(2));
231 EXPECT_EQ(4, destination.Get(3));
232 EXPECT_EQ(5, destination.Get(4));
233 }
234
TEST(RepeatedField,MutableDataIsMutable)235 TEST(RepeatedField, MutableDataIsMutable) {
236 RepeatedField<int> field;
237 field.Add(1);
238 EXPECT_EQ(1, field.Get(0));
239 // The fact that this line compiles would be enough, but we'll check the
240 // value anyway.
241 *field.mutable_data() = 2;
242 EXPECT_EQ(2, field.Get(0));
243 }
244
TEST(RepeatedField,Truncate)245 TEST(RepeatedField, Truncate) {
246 RepeatedField<int> field;
247
248 field.Add(12);
249 field.Add(34);
250 field.Add(56);
251 field.Add(78);
252 EXPECT_EQ(4, field.size());
253
254 field.Truncate(3);
255 EXPECT_EQ(3, field.size());
256
257 field.Add(90);
258 EXPECT_EQ(4, field.size());
259 EXPECT_EQ(90, field.Get(3));
260
261 // Truncations that don't change the size are allowed, but growing is not
262 // allowed.
263 field.Truncate(field.size());
264 #ifdef GTEST_HAS_DEATH_TEST
265 EXPECT_DEBUG_DEATH(field.Truncate(field.size() + 1), "new_size");
266 #endif
267 }
268
269
270 // ===================================================================
271 // RepeatedPtrField tests. These pretty much just mirror the RepeatedField
272 // tests above.
273
TEST(RepeatedPtrField,Small)274 TEST(RepeatedPtrField, Small) {
275 RepeatedPtrField<string> field;
276
277 EXPECT_EQ(field.size(), 0);
278
279 field.Add()->assign("foo");
280
281 EXPECT_EQ(field.size(), 1);
282 EXPECT_EQ(field.Get(0), "foo");
283
284 field.Add()->assign("bar");
285
286 EXPECT_EQ(field.size(), 2);
287 EXPECT_EQ(field.Get(0), "foo");
288 EXPECT_EQ(field.Get(1), "bar");
289
290 field.Mutable(1)->assign("baz");
291
292 EXPECT_EQ(field.size(), 2);
293 EXPECT_EQ(field.Get(0), "foo");
294 EXPECT_EQ(field.Get(1), "baz");
295
296 field.RemoveLast();
297
298 EXPECT_EQ(field.size(), 1);
299 EXPECT_EQ(field.Get(0), "foo");
300
301 field.Clear();
302
303 EXPECT_EQ(field.size(), 0);
304 }
305
TEST(RepeatedPtrField,Large)306 TEST(RepeatedPtrField, Large) {
307 RepeatedPtrField<string> field;
308
309 for (int i = 0; i < 16; i++) {
310 *field.Add() += 'a' + i;
311 }
312
313 EXPECT_EQ(field.size(), 16);
314
315 for (int i = 0; i < 16; i++) {
316 EXPECT_EQ(field.Get(i).size(), 1);
317 EXPECT_EQ(field.Get(i)[0], 'a' + i);
318 }
319
320 int min_expected_usage = 16 * sizeof(string);
321 EXPECT_GE(field.SpaceUsedExcludingSelf(), min_expected_usage);
322 }
323
TEST(RepeatedPtrField,SwapSmallSmall)324 TEST(RepeatedPtrField, SwapSmallSmall) {
325 RepeatedPtrField<string> field1;
326 RepeatedPtrField<string> field2;
327
328 field1.Add()->assign("foo");
329 field1.Add()->assign("bar");
330 field1.Swap(&field2);
331
332 EXPECT_EQ(field1.size(), 0);
333 EXPECT_EQ(field2.size(), 2);
334 EXPECT_EQ(field2.Get(0), "foo");
335 EXPECT_EQ(field2.Get(1), "bar");
336 }
337
TEST(RepeatedPtrField,SwapLargeSmall)338 TEST(RepeatedPtrField, SwapLargeSmall) {
339 RepeatedPtrField<string> field1;
340 RepeatedPtrField<string> field2;
341
342 field2.Add()->assign("foo");
343 field2.Add()->assign("bar");
344 for (int i = 0; i < 16; i++) {
345 *field1.Add() += 'a' + i;
346 }
347 field1.Swap(&field2);
348
349 EXPECT_EQ(field1.size(), 2);
350 EXPECT_EQ(field1.Get(0), "foo");
351 EXPECT_EQ(field1.Get(1), "bar");
352 EXPECT_EQ(field2.size(), 16);
353 for (int i = 0; i < 16; i++) {
354 EXPECT_EQ(field2.Get(i).size(), 1);
355 EXPECT_EQ(field2.Get(i)[0], 'a' + i);
356 }
357 }
358
TEST(RepeatedPtrField,SwapLargeLarge)359 TEST(RepeatedPtrField, SwapLargeLarge) {
360 RepeatedPtrField<string> field1;
361 RepeatedPtrField<string> field2;
362
363 field1.Add()->assign("foo");
364 field1.Add()->assign("bar");
365 for (int i = 0; i < 16; i++) {
366 *field1.Add() += 'A' + i;
367 *field2.Add() += 'a' + i;
368 }
369 field2.Swap(&field1);
370
371 EXPECT_EQ(field1.size(), 16);
372 for (int i = 0; i < 16; i++) {
373 EXPECT_EQ(field1.Get(i).size(), 1);
374 EXPECT_EQ(field1.Get(i)[0], 'a' + i);
375 }
376 EXPECT_EQ(field2.size(), 18);
377 EXPECT_EQ(field2.Get(0), "foo");
378 EXPECT_EQ(field2.Get(1), "bar");
379 for (int i = 2; i < 18; i++) {
380 EXPECT_EQ(field2.Get(i).size(), 1);
381 EXPECT_EQ(field2.Get(i)[0], 'A' + i - 2);
382 }
383 }
384
ReservedSpace(RepeatedPtrField<string> * field)385 static int ReservedSpace(RepeatedPtrField<string>* field) {
386 const string* const* ptr = field->data();
387 do {
388 field->Add();
389 } while (field->data() == ptr);
390
391 return field->size() - 1;
392 }
393
TEST(RepeatedPtrField,ReserveMoreThanDouble)394 TEST(RepeatedPtrField, ReserveMoreThanDouble) {
395 RepeatedPtrField<string> field;
396 field.Reserve(20);
397
398 EXPECT_EQ(20, ReservedSpace(&field));
399 }
400
TEST(RepeatedPtrField,ReserveLessThanDouble)401 TEST(RepeatedPtrField, ReserveLessThanDouble) {
402 RepeatedPtrField<string> field;
403 field.Reserve(20);
404 field.Reserve(30);
405
406 EXPECT_EQ(40, ReservedSpace(&field));
407 }
408
TEST(RepeatedPtrField,ReserveLessThanExisting)409 TEST(RepeatedPtrField, ReserveLessThanExisting) {
410 RepeatedPtrField<string> field;
411 field.Reserve(20);
412 const string* const* previous_ptr = field.data();
413 field.Reserve(10);
414
415 EXPECT_EQ(previous_ptr, field.data());
416 EXPECT_EQ(20, ReservedSpace(&field));
417 }
418
TEST(RepeatedPtrField,ReserveDoesntLoseAllocated)419 TEST(RepeatedPtrField, ReserveDoesntLoseAllocated) {
420 // Check that a bug is fixed: An earlier implementation of Reserve()
421 // failed to copy pointers to allocated-but-cleared objects, possibly
422 // leading to segfaults.
423 RepeatedPtrField<string> field;
424 string* first = field.Add();
425 field.RemoveLast();
426
427 field.Reserve(20);
428 EXPECT_EQ(first, field.Add());
429 }
430
431 // Clearing elements is tricky with RepeatedPtrFields since the memory for
432 // the elements is retained and reused.
TEST(RepeatedPtrField,ClearedElements)433 TEST(RepeatedPtrField, ClearedElements) {
434 RepeatedPtrField<string> field;
435
436 string* original = field.Add();
437 *original = "foo";
438
439 EXPECT_EQ(field.ClearedCount(), 0);
440
441 field.RemoveLast();
442 EXPECT_TRUE(original->empty());
443 EXPECT_EQ(field.ClearedCount(), 1);
444
445 EXPECT_EQ(field.Add(), original); // Should return same string for reuse.
446
447 EXPECT_EQ(field.ReleaseLast(), original); // We take ownership.
448 EXPECT_EQ(field.ClearedCount(), 0);
449
450 EXPECT_NE(field.Add(), original); // Should NOT return the same string.
451 EXPECT_EQ(field.ClearedCount(), 0);
452
453 field.AddAllocated(original); // Give ownership back.
454 EXPECT_EQ(field.ClearedCount(), 0);
455 EXPECT_EQ(field.Mutable(1), original);
456
457 field.Clear();
458 EXPECT_EQ(field.ClearedCount(), 2);
459 EXPECT_EQ(field.ReleaseCleared(), original); // Take ownership again.
460 EXPECT_EQ(field.ClearedCount(), 1);
461 EXPECT_NE(field.Add(), original);
462 EXPECT_EQ(field.ClearedCount(), 0);
463 EXPECT_NE(field.Add(), original);
464 EXPECT_EQ(field.ClearedCount(), 0);
465
466 field.AddCleared(original); // Give ownership back, but as a cleared object.
467 EXPECT_EQ(field.ClearedCount(), 1);
468 EXPECT_EQ(field.Add(), original);
469 EXPECT_EQ(field.ClearedCount(), 0);
470 }
471
472 // Test all code paths in AddAllocated().
TEST(RepeatedPtrField,AddAlocated)473 TEST(RepeatedPtrField, AddAlocated) {
474 RepeatedPtrField<string> field;
475 while (field.size() < field.Capacity()) {
476 field.Add()->assign("filler");
477 }
478
479 int index = field.size();
480
481 // First branch: Field is at capacity with no cleared objects.
482 string* foo = new string("foo");
483 field.AddAllocated(foo);
484 EXPECT_EQ(index + 1, field.size());
485 EXPECT_EQ(0, field.ClearedCount());
486 EXPECT_EQ(foo, &field.Get(index));
487
488 // Last branch: Field is not at capacity and there are no cleared objects.
489 string* bar = new string("bar");
490 field.AddAllocated(bar);
491 ++index;
492 EXPECT_EQ(index + 1, field.size());
493 EXPECT_EQ(0, field.ClearedCount());
494 EXPECT_EQ(bar, &field.Get(index));
495
496 // Third branch: Field is not at capacity and there are no cleared objects.
497 field.RemoveLast();
498 string* baz = new string("baz");
499 field.AddAllocated(baz);
500 EXPECT_EQ(index + 1, field.size());
501 EXPECT_EQ(1, field.ClearedCount());
502 EXPECT_EQ(baz, &field.Get(index));
503
504 // Second branch: Field is at capacity but has some cleared objects.
505 while (field.size() < field.Capacity()) {
506 field.Add()->assign("filler2");
507 }
508 field.RemoveLast();
509 index = field.size();
510 string* qux = new string("qux");
511 field.AddAllocated(qux);
512 EXPECT_EQ(index + 1, field.size());
513 // We should have discarded the cleared object.
514 EXPECT_EQ(0, field.ClearedCount());
515 EXPECT_EQ(qux, &field.Get(index));
516 }
517
TEST(RepeatedPtrField,MergeFrom)518 TEST(RepeatedPtrField, MergeFrom) {
519 RepeatedPtrField<string> source, destination;
520
521 source.Add()->assign("4");
522 source.Add()->assign("5");
523
524 destination.Add()->assign("1");
525 destination.Add()->assign("2");
526 destination.Add()->assign("3");
527
528 destination.MergeFrom(source);
529
530 ASSERT_EQ(5, destination.size());
531
532 EXPECT_EQ("1", destination.Get(0));
533 EXPECT_EQ("2", destination.Get(1));
534 EXPECT_EQ("3", destination.Get(2));
535 EXPECT_EQ("4", destination.Get(3));
536 EXPECT_EQ("5", destination.Get(4));
537 }
538
TEST(RepeatedPtrField,MutableDataIsMutable)539 TEST(RepeatedPtrField, MutableDataIsMutable) {
540 RepeatedPtrField<string> field;
541 *field.Add() = "1";
542 EXPECT_EQ("1", field.Get(0));
543 // The fact that this line compiles would be enough, but we'll check the
544 // value anyway.
545 string** data = field.mutable_data();
546 **data = "2";
547 EXPECT_EQ("2", field.Get(0));
548 }
549
550 // ===================================================================
551
552 // Iterator tests stolen from net/proto/proto-array_unittest.
553 class RepeatedFieldIteratorTest : public testing::Test {
554 protected:
SetUp()555 virtual void SetUp() {
556 for (int i = 0; i < 3; ++i) {
557 proto_array_.Add(i);
558 }
559 }
560
561 RepeatedField<int> proto_array_;
562 };
563
TEST_F(RepeatedFieldIteratorTest,Convertible)564 TEST_F(RepeatedFieldIteratorTest, Convertible) {
565 RepeatedField<int>::iterator iter = proto_array_.begin();
566 RepeatedField<int>::const_iterator c_iter = iter;
567 EXPECT_EQ(0, *c_iter);
568 }
569
TEST_F(RepeatedFieldIteratorTest,MutableIteration)570 TEST_F(RepeatedFieldIteratorTest, MutableIteration) {
571 RepeatedField<int>::iterator iter = proto_array_.begin();
572 EXPECT_EQ(0, *iter);
573 ++iter;
574 EXPECT_EQ(1, *iter++);
575 EXPECT_EQ(2, *iter);
576 ++iter;
577 EXPECT_TRUE(proto_array_.end() == iter);
578
579 EXPECT_EQ(2, *(proto_array_.end() - 1));
580 }
581
TEST_F(RepeatedFieldIteratorTest,ConstIteration)582 TEST_F(RepeatedFieldIteratorTest, ConstIteration) {
583 const RepeatedField<int>& const_proto_array = proto_array_;
584 RepeatedField<int>::const_iterator iter = const_proto_array.begin();
585 EXPECT_EQ(0, *iter);
586 ++iter;
587 EXPECT_EQ(1, *iter++);
588 EXPECT_EQ(2, *iter);
589 ++iter;
590 EXPECT_TRUE(proto_array_.end() == iter);
591 EXPECT_EQ(2, *(proto_array_.end() - 1));
592 }
593
TEST_F(RepeatedFieldIteratorTest,Mutation)594 TEST_F(RepeatedFieldIteratorTest, Mutation) {
595 RepeatedField<int>::iterator iter = proto_array_.begin();
596 *iter = 7;
597 EXPECT_EQ(7, proto_array_.Get(0));
598 }
599
600 // -------------------------------------------------------------------
601
602 class RepeatedPtrFieldIteratorTest : public testing::Test {
603 protected:
SetUp()604 virtual void SetUp() {
605 proto_array_.Add()->assign("foo");
606 proto_array_.Add()->assign("bar");
607 proto_array_.Add()->assign("baz");
608 }
609
610 RepeatedPtrField<string> proto_array_;
611 };
612
TEST_F(RepeatedPtrFieldIteratorTest,Convertible)613 TEST_F(RepeatedPtrFieldIteratorTest, Convertible) {
614 RepeatedPtrField<string>::iterator iter = proto_array_.begin();
615 RepeatedPtrField<string>::const_iterator c_iter = iter;
616 }
617
TEST_F(RepeatedPtrFieldIteratorTest,MutableIteration)618 TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) {
619 RepeatedPtrField<string>::iterator iter = proto_array_.begin();
620 EXPECT_EQ("foo", *iter);
621 ++iter;
622 EXPECT_EQ("bar", *(iter++));
623 EXPECT_EQ("baz", *iter);
624 ++iter;
625 EXPECT_TRUE(proto_array_.end() == iter);
626 EXPECT_EQ("baz", *(--proto_array_.end()));
627 }
628
TEST_F(RepeatedPtrFieldIteratorTest,ConstIteration)629 TEST_F(RepeatedPtrFieldIteratorTest, ConstIteration) {
630 const RepeatedPtrField<string>& const_proto_array = proto_array_;
631 RepeatedPtrField<string>::const_iterator iter = const_proto_array.begin();
632 EXPECT_EQ("foo", *iter);
633 ++iter;
634 EXPECT_EQ("bar", *(iter++));
635 EXPECT_EQ("baz", *iter);
636 ++iter;
637 EXPECT_TRUE(const_proto_array.end() == iter);
638 EXPECT_EQ("baz", *(--const_proto_array.end()));
639 }
640
TEST_F(RepeatedPtrFieldIteratorTest,RandomAccess)641 TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) {
642 RepeatedPtrField<string>::iterator iter = proto_array_.begin();
643 RepeatedPtrField<string>::iterator iter2 = iter;
644 ++iter2;
645 ++iter2;
646 EXPECT_TRUE(iter + 2 == iter2);
647 EXPECT_TRUE(iter == iter2 - 2);
648 EXPECT_EQ("baz", iter[2]);
649 EXPECT_EQ("baz", *(iter + 2));
650 EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
651 }
652
TEST_F(RepeatedPtrFieldIteratorTest,Comparable)653 TEST_F(RepeatedPtrFieldIteratorTest, Comparable) {
654 RepeatedPtrField<string>::const_iterator iter = proto_array_.begin();
655 RepeatedPtrField<string>::const_iterator iter2 = iter + 1;
656 EXPECT_TRUE(iter == iter);
657 EXPECT_TRUE(iter != iter2);
658 EXPECT_TRUE(iter < iter2);
659 EXPECT_TRUE(iter <= iter2);
660 EXPECT_TRUE(iter <= iter);
661 EXPECT_TRUE(iter2 > iter);
662 EXPECT_TRUE(iter2 >= iter);
663 EXPECT_TRUE(iter >= iter);
664 }
665
666 // Uninitialized iterator does not point to any of the RepeatedPtrField.
TEST_F(RepeatedPtrFieldIteratorTest,UninitializedIterator)667 TEST_F(RepeatedPtrFieldIteratorTest, UninitializedIterator) {
668 RepeatedPtrField<string>::iterator iter;
669 EXPECT_TRUE(iter != proto_array_.begin());
670 EXPECT_TRUE(iter != proto_array_.begin() + 1);
671 EXPECT_TRUE(iter != proto_array_.begin() + 2);
672 EXPECT_TRUE(iter != proto_array_.begin() + 3);
673 EXPECT_TRUE(iter != proto_array_.end());
674 }
675
TEST_F(RepeatedPtrFieldIteratorTest,STLAlgorithms_lower_bound)676 TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) {
677 proto_array_.Clear();
678 proto_array_.Add()->assign("a");
679 proto_array_.Add()->assign("c");
680 proto_array_.Add()->assign("d");
681 proto_array_.Add()->assign("n");
682 proto_array_.Add()->assign("p");
683 proto_array_.Add()->assign("x");
684 proto_array_.Add()->assign("y");
685
686 string v = "f";
687 RepeatedPtrField<string>::const_iterator it =
688 lower_bound(proto_array_.begin(), proto_array_.end(), v);
689
690 EXPECT_EQ(*it, "n");
691 EXPECT_TRUE(it == proto_array_.begin() + 3);
692 }
693
TEST_F(RepeatedPtrFieldIteratorTest,Mutation)694 TEST_F(RepeatedPtrFieldIteratorTest, Mutation) {
695 RepeatedPtrField<string>::iterator iter = proto_array_.begin();
696 *iter = "qux";
697 EXPECT_EQ("qux", proto_array_.Get(0));
698 }
699
700 // -------------------------------------------------------------------
701
702 class RepeatedPtrFieldPtrsIteratorTest : public testing::Test {
703 protected:
SetUp()704 virtual void SetUp() {
705 proto_array_.Add()->assign("foo");
706 proto_array_.Add()->assign("bar");
707 proto_array_.Add()->assign("baz");
708 }
709
710 RepeatedPtrField<string> proto_array_;
711 };
712
TEST_F(RepeatedPtrFieldPtrsIteratorTest,ConvertiblePtr)713 TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) {
714 RepeatedPtrField<string>::pointer_iterator iter =
715 proto_array_.pointer_begin();
716 }
717
TEST_F(RepeatedPtrFieldPtrsIteratorTest,MutablePtrIteration)718 TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) {
719 RepeatedPtrField<string>::pointer_iterator iter =
720 proto_array_.pointer_begin();
721 EXPECT_EQ("foo", **iter);
722 ++iter;
723 EXPECT_EQ("bar", **(iter++));
724 EXPECT_EQ("baz", **iter);
725 ++iter;
726 EXPECT_TRUE(proto_array_.pointer_end() == iter);
727 EXPECT_EQ("baz", **(--proto_array_.pointer_end()));
728 }
729
TEST_F(RepeatedPtrFieldPtrsIteratorTest,RandomPtrAccess)730 TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) {
731 RepeatedPtrField<string>::pointer_iterator iter =
732 proto_array_.pointer_begin();
733 RepeatedPtrField<string>::pointer_iterator iter2 = iter;
734 ++iter2;
735 ++iter2;
736 EXPECT_TRUE(iter + 2 == iter2);
737 EXPECT_TRUE(iter == iter2 - 2);
738 EXPECT_EQ("baz", *iter[2]);
739 EXPECT_EQ("baz", **(iter + 2));
740 EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
741 }
742
TEST_F(RepeatedPtrFieldPtrsIteratorTest,ComparablePtr)743 TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) {
744 RepeatedPtrField<string>::pointer_iterator iter =
745 proto_array_.pointer_begin();
746 RepeatedPtrField<string>::pointer_iterator iter2 = iter + 1;
747 EXPECT_TRUE(iter == iter);
748 EXPECT_TRUE(iter != iter2);
749 EXPECT_TRUE(iter < iter2);
750 EXPECT_TRUE(iter <= iter2);
751 EXPECT_TRUE(iter <= iter);
752 EXPECT_TRUE(iter2 > iter);
753 EXPECT_TRUE(iter2 >= iter);
754 EXPECT_TRUE(iter >= iter);
755 }
756
757 // Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs.
758 // Dereferencing an uninitialized iterator crashes the process.
TEST_F(RepeatedPtrFieldPtrsIteratorTest,UninitializedPtrIterator)759 TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) {
760 RepeatedPtrField<string>::pointer_iterator iter;
761 EXPECT_TRUE(iter != proto_array_.pointer_begin());
762 EXPECT_TRUE(iter != proto_array_.pointer_begin() + 1);
763 EXPECT_TRUE(iter != proto_array_.pointer_begin() + 2);
764 EXPECT_TRUE(iter != proto_array_.pointer_begin() + 3);
765 EXPECT_TRUE(iter != proto_array_.pointer_end());
766 }
767
768
769 // This comparison functor is required by the tests for RepeatedPtrOverPtrs.
770 // They operate on strings and need to compare strings as strings in
771 // any stl algorithm, even though the iterator returns a pointer to a string
772 // - i.e. *iter has type string*.
773 struct StringLessThan {
operator ()google::protobuf::__anonf5fba83a0111::StringLessThan774 bool operator()(const string* z, const string& y) {
775 return *z < y;
776 }
operator ()google::protobuf::__anonf5fba83a0111::StringLessThan777 bool operator()(const string* z, const string* y) {
778 return *z < *y;
779 }
780 };
781
TEST_F(RepeatedPtrFieldPtrsIteratorTest,PtrSTLAlgorithms_lower_bound)782 TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) {
783 proto_array_.Clear();
784 proto_array_.Add()->assign("a");
785 proto_array_.Add()->assign("c");
786 proto_array_.Add()->assign("d");
787 proto_array_.Add()->assign("n");
788 proto_array_.Add()->assign("p");
789 proto_array_.Add()->assign("x");
790 proto_array_.Add()->assign("y");
791
792 RepeatedPtrField<string>::pointer_iterator iter =
793 proto_array_.pointer_begin();
794 string v = "f";
795 RepeatedPtrField<string>::pointer_iterator it =
796 lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(),
797 &v, StringLessThan());
798
799 GOOGLE_CHECK(*it != NULL);
800
801 EXPECT_EQ(**it, "n");
802 EXPECT_TRUE(it == proto_array_.pointer_begin() + 3);
803 }
804
TEST_F(RepeatedPtrFieldPtrsIteratorTest,PtrMutation)805 TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) {
806 RepeatedPtrField<string>::pointer_iterator iter =
807 proto_array_.pointer_begin();
808 **iter = "qux";
809 EXPECT_EQ("qux", proto_array_.Get(0));
810
811 EXPECT_EQ("bar", proto_array_.Get(1));
812 EXPECT_EQ("baz", proto_array_.Get(2));
813 ++iter;
814 delete *iter;
815 *iter = new string("a");
816 ++iter;
817 delete *iter;
818 *iter = new string("b");
819 EXPECT_EQ("a", proto_array_.Get(1));
820 EXPECT_EQ("b", proto_array_.Get(2));
821 }
822
TEST_F(RepeatedPtrFieldPtrsIteratorTest,Sort)823 TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) {
824 proto_array_.Add()->assign("c");
825 proto_array_.Add()->assign("d");
826 proto_array_.Add()->assign("n");
827 proto_array_.Add()->assign("p");
828 proto_array_.Add()->assign("a");
829 proto_array_.Add()->assign("y");
830 proto_array_.Add()->assign("x");
831 EXPECT_EQ("foo", proto_array_.Get(0));
832 EXPECT_EQ("n", proto_array_.Get(5));
833 EXPECT_EQ("x", proto_array_.Get(9));
834 sort(proto_array_.pointer_begin(),
835 proto_array_.pointer_end(),
836 StringLessThan());
837 EXPECT_EQ("a", proto_array_.Get(0));
838 EXPECT_EQ("baz", proto_array_.Get(2));
839 EXPECT_EQ("y", proto_array_.Get(9));
840 }
841
842
843 // -----------------------------------------------------------------------------
844 // Unit-tests for the insert iterators
845 // google::protobuf::RepeatedFieldBackInserter,
846 // google::protobuf::AllocatedRepeatedPtrFieldBackInserter
847 // Ported from util/gtl/proto-array-iterators_unittest.
848
849 class RepeatedFieldInsertionIteratorsTest : public testing::Test {
850 protected:
851 std::list<double> halves;
852 std::list<int> fibonacci;
853 std::vector<string> words;
854 typedef TestAllTypes::NestedMessage Nested;
855 Nested nesteds[2];
856 std::vector<Nested*> nested_ptrs;
857 TestAllTypes protobuffer;
858
SetUp()859 virtual void SetUp() {
860 fibonacci.push_back(1);
861 fibonacci.push_back(1);
862 fibonacci.push_back(2);
863 fibonacci.push_back(3);
864 fibonacci.push_back(5);
865 fibonacci.push_back(8);
866 std::copy(fibonacci.begin(), fibonacci.end(),
867 RepeatedFieldBackInserter(protobuffer.mutable_repeated_int32()));
868
869 halves.push_back(1.0);
870 halves.push_back(0.5);
871 halves.push_back(0.25);
872 halves.push_back(0.125);
873 halves.push_back(0.0625);
874 std::copy(halves.begin(), halves.end(),
875 RepeatedFieldBackInserter(protobuffer.mutable_repeated_double()));
876
877 words.push_back("Able");
878 words.push_back("was");
879 words.push_back("I");
880 words.push_back("ere");
881 words.push_back("I");
882 words.push_back("saw");
883 words.push_back("Elba");
884 std::copy(words.begin(), words.end(),
885 RepeatedFieldBackInserter(protobuffer.mutable_repeated_string()));
886
887 nesteds[0].set_bb(17);
888 nesteds[1].set_bb(4711);
889 std::copy(&nesteds[0], &nesteds[2],
890 RepeatedFieldBackInserter(
891 protobuffer.mutable_repeated_nested_message()));
892
893 nested_ptrs.push_back(new Nested);
894 nested_ptrs.back()->set_bb(170);
895 nested_ptrs.push_back(new Nested);
896 nested_ptrs.back()->set_bb(47110);
897 std::copy(nested_ptrs.begin(), nested_ptrs.end(),
898 RepeatedFieldBackInserter(
899 protobuffer.mutable_repeated_nested_message()));
900
901 }
902
TearDown()903 virtual void TearDown() {
904 STLDeleteContainerPointers(nested_ptrs.begin(), nested_ptrs.end());
905 }
906 };
907
TEST_F(RepeatedFieldInsertionIteratorsTest,Fibonacci)908 TEST_F(RepeatedFieldInsertionIteratorsTest, Fibonacci) {
909 EXPECT_TRUE(std::equal(fibonacci.begin(),
910 fibonacci.end(),
911 protobuffer.repeated_int32().begin()));
912 EXPECT_TRUE(std::equal(protobuffer.repeated_int32().begin(),
913 protobuffer.repeated_int32().end(),
914 fibonacci.begin()));
915 }
916
TEST_F(RepeatedFieldInsertionIteratorsTest,Halves)917 TEST_F(RepeatedFieldInsertionIteratorsTest, Halves) {
918 EXPECT_TRUE(std::equal(halves.begin(),
919 halves.end(),
920 protobuffer.repeated_double().begin()));
921 EXPECT_TRUE(std::equal(protobuffer.repeated_double().begin(),
922 protobuffer.repeated_double().end(),
923 halves.begin()));
924 }
925
TEST_F(RepeatedFieldInsertionIteratorsTest,Words)926 TEST_F(RepeatedFieldInsertionIteratorsTest, Words) {
927 ASSERT_EQ(words.size(), protobuffer.repeated_string_size());
928 EXPECT_EQ(words.at(0), protobuffer.repeated_string(0));
929 EXPECT_EQ(words.at(1), protobuffer.repeated_string(1));
930 EXPECT_EQ(words.at(2), protobuffer.repeated_string(2));
931 EXPECT_EQ(words.at(3), protobuffer.repeated_string(3));
932 EXPECT_EQ(words.at(4), protobuffer.repeated_string(4));
933 EXPECT_EQ(words.at(5), protobuffer.repeated_string(5));
934 EXPECT_EQ(words.at(6), protobuffer.repeated_string(6));
935 }
936
TEST_F(RepeatedFieldInsertionIteratorsTest,Nesteds)937 TEST_F(RepeatedFieldInsertionIteratorsTest, Nesteds) {
938 ASSERT_EQ(protobuffer.repeated_nested_message_size(), 4);
939 EXPECT_EQ(protobuffer.repeated_nested_message(0).bb(), 17);
940 EXPECT_EQ(protobuffer.repeated_nested_message(1).bb(), 4711);
941 EXPECT_EQ(protobuffer.repeated_nested_message(2).bb(), 170);
942 EXPECT_EQ(protobuffer.repeated_nested_message(3).bb(), 47110);
943 }
944
TEST_F(RepeatedFieldInsertionIteratorsTest,AllocatedRepeatedPtrFieldWithStringIntData)945 TEST_F(RepeatedFieldInsertionIteratorsTest,
946 AllocatedRepeatedPtrFieldWithStringIntData) {
947 vector<Nested*> data;
948 TestAllTypes goldenproto;
949 for (int i = 0; i < 10; ++i) {
950 Nested* new_data = new Nested;
951 new_data->set_bb(i);
952 data.push_back(new_data);
953
954 new_data = goldenproto.add_repeated_nested_message();
955 new_data->set_bb(i);
956 }
957 TestAllTypes testproto;
958 copy(data.begin(), data.end(),
959 AllocatedRepeatedPtrFieldBackInserter(
960 testproto.mutable_repeated_nested_message()));
961 EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
962 }
963
TEST_F(RepeatedFieldInsertionIteratorsTest,AllocatedRepeatedPtrFieldWithString)964 TEST_F(RepeatedFieldInsertionIteratorsTest,
965 AllocatedRepeatedPtrFieldWithString) {
966 vector<string*> data;
967 TestAllTypes goldenproto;
968 for (int i = 0; i < 10; ++i) {
969 string* new_data = new string;
970 *new_data = "name-" + SimpleItoa(i);
971 data.push_back(new_data);
972
973 new_data = goldenproto.add_repeated_string();
974 *new_data = "name-" + SimpleItoa(i);
975 }
976 TestAllTypes testproto;
977 copy(data.begin(), data.end(),
978 AllocatedRepeatedPtrFieldBackInserter(
979 testproto.mutable_repeated_string()));
980 EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
981 }
982
983 } // namespace
984
985 } // namespace protobuf
986 } // namespace google
987