blob: 39b24b3375ee35ef0ee5e823322f2ae0a8a498b4 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
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>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000039#include <limits>
kenton@google.comd37d46d2009-04-25 02:53:47 +000040#include <list>
kenton@google.comfccb1462009-12-18 02:11:36 +000041#include <vector>
temporal40ee5512008-07-10 02:12:20 +000042
43#include <google/protobuf/repeated_field.h>
44
Feng Xiaoeee38b02015-08-22 18:25:48 -070045#include <google/protobuf/stubs/logging.h>
temporal40ee5512008-07-10 02:12:20 +000046#include <google/protobuf/stubs/common.h>
kenton@google.comd37d46d2009-04-25 02:53:47 +000047#include <google/protobuf/unittest.pb.h>
48#include <google/protobuf/stubs/strutil.h>
temporal40ee5512008-07-10 02:12:20 +000049#include <google/protobuf/testing/googletest.h>
50#include <gtest/gtest.h>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000051#include <google/protobuf/stubs/stl_util.h>
temporal40ee5512008-07-10 02:12:20 +000052
53namespace google {
kenton@google.comd37d46d2009-04-25 02:53:47 +000054using protobuf_unittest::TestAllTypes;
55
temporal40ee5512008-07-10 02:12:20 +000056namespace protobuf {
kenton@google.comd37d46d2009-04-25 02:53:47 +000057namespace {
temporal40ee5512008-07-10 02:12:20 +000058
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000059// Test operations on a small RepeatedField.
temporal40ee5512008-07-10 02:12:20 +000060TEST(RepeatedField, Small) {
61 RepeatedField<int> field;
62
jieluo@google.com4de8f552014-07-18 00:47:59 +000063 EXPECT_TRUE(field.empty());
temporal40ee5512008-07-10 02:12:20 +000064 EXPECT_EQ(field.size(), 0);
65
66 field.Add(5);
67
jieluo@google.com4de8f552014-07-18 00:47:59 +000068 EXPECT_FALSE(field.empty());
temporal40ee5512008-07-10 02:12:20 +000069 EXPECT_EQ(field.size(), 1);
70 EXPECT_EQ(field.Get(0), 5);
71
72 field.Add(42);
73
jieluo@google.com4de8f552014-07-18 00:47:59 +000074 EXPECT_FALSE(field.empty());
temporal40ee5512008-07-10 02:12:20 +000075 EXPECT_EQ(field.size(), 2);
76 EXPECT_EQ(field.Get(0), 5);
77 EXPECT_EQ(field.Get(1), 42);
78
79 field.Set(1, 23);
80
jieluo@google.com4de8f552014-07-18 00:47:59 +000081 EXPECT_FALSE(field.empty());
temporal40ee5512008-07-10 02:12:20 +000082 EXPECT_EQ(field.size(), 2);
83 EXPECT_EQ(field.Get(0), 5);
84 EXPECT_EQ(field.Get(1), 23);
85
86 field.RemoveLast();
87
jieluo@google.com4de8f552014-07-18 00:47:59 +000088 EXPECT_FALSE(field.empty());
temporal40ee5512008-07-10 02:12:20 +000089 EXPECT_EQ(field.size(), 1);
90 EXPECT_EQ(field.Get(0), 5);
91
92 field.Clear();
93
jieluo@google.com4de8f552014-07-18 00:47:59 +000094 EXPECT_TRUE(field.empty());
temporal40ee5512008-07-10 02:12:20 +000095 EXPECT_EQ(field.size(), 0);
Feng Xiaobe20ae02014-12-05 02:54:43 -080096 // Additional bytes are for 'struct Rep' header.
97 int expected_usage = 4 * sizeof(int) + sizeof(Arena*);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000098 EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage);
temporal40ee5512008-07-10 02:12:20 +000099}
100
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000101
temporal40ee5512008-07-10 02:12:20 +0000102// Test operations on a RepeatedField which is large enough to allocate a
103// separate array.
104TEST(RepeatedField, Large) {
105 RepeatedField<int> field;
106
107 for (int i = 0; i < 16; i++) {
108 field.Add(i * i);
109 }
110
jieluo@google.com4de8f552014-07-18 00:47:59 +0000111 EXPECT_FALSE(field.empty());
temporal40ee5512008-07-10 02:12:20 +0000112 EXPECT_EQ(field.size(), 16);
113
114 for (int i = 0; i < 16; i++) {
115 EXPECT_EQ(field.Get(i), i * i);
116 }
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000117
118 int expected_usage = 16 * sizeof(int);
119 EXPECT_GE(field.SpaceUsedExcludingSelf(), expected_usage);
temporal40ee5512008-07-10 02:12:20 +0000120}
121
122// Test swapping between various types of RepeatedFields.
123TEST(RepeatedField, SwapSmallSmall) {
124 RepeatedField<int> field1;
125 RepeatedField<int> field2;
126
127 field1.Add(5);
128 field1.Add(42);
129
jieluo@google.com4de8f552014-07-18 00:47:59 +0000130 EXPECT_FALSE(field1.empty());
131 EXPECT_EQ(field1.size(), 2);
132 EXPECT_EQ(field1.Get(0), 5);
133 EXPECT_EQ(field1.Get(1), 42);
134
135 EXPECT_TRUE(field2.empty());
136 EXPECT_EQ(field2.size(), 0);
137
temporal40ee5512008-07-10 02:12:20 +0000138 field1.Swap(&field2);
139
jieluo@google.com4de8f552014-07-18 00:47:59 +0000140 EXPECT_TRUE(field1.empty());
temporal40ee5512008-07-10 02:12:20 +0000141 EXPECT_EQ(field1.size(), 0);
jieluo@google.com4de8f552014-07-18 00:47:59 +0000142
143 EXPECT_FALSE(field2.empty());
temporal40ee5512008-07-10 02:12:20 +0000144 EXPECT_EQ(field2.size(), 2);
145 EXPECT_EQ(field2.Get(0), 5);
146 EXPECT_EQ(field2.Get(1), 42);
147}
148
149TEST(RepeatedField, SwapLargeSmall) {
150 RepeatedField<int> field1;
151 RepeatedField<int> field2;
152
153 for (int i = 0; i < 16; i++) {
154 field1.Add(i * i);
155 }
156 field2.Add(5);
157 field2.Add(42);
158 field1.Swap(&field2);
159
160 EXPECT_EQ(field1.size(), 2);
161 EXPECT_EQ(field1.Get(0), 5);
162 EXPECT_EQ(field1.Get(1), 42);
163 EXPECT_EQ(field2.size(), 16);
164 for (int i = 0; i < 16; i++) {
165 EXPECT_EQ(field2.Get(i), i * i);
166 }
167}
168
169TEST(RepeatedField, SwapLargeLarge) {
170 RepeatedField<int> field1;
171 RepeatedField<int> field2;
172
173 field1.Add(5);
174 field1.Add(42);
175 for (int i = 0; i < 16; i++) {
176 field1.Add(i);
177 field2.Add(i * i);
178 }
179 field2.Swap(&field1);
180
181 EXPECT_EQ(field1.size(), 16);
182 for (int i = 0; i < 16; i++) {
183 EXPECT_EQ(field1.Get(i), i * i);
184 }
185 EXPECT_EQ(field2.size(), 18);
186 EXPECT_EQ(field2.Get(0), 5);
187 EXPECT_EQ(field2.Get(1), 42);
188 for (int i = 2; i < 18; i++) {
189 EXPECT_EQ(field2.Get(i), i - 2);
190 }
191}
192
193// Determines how much space was reserved by the given field by adding elements
194// to it until it re-allocates its space.
195static int ReservedSpace(RepeatedField<int>* field) {
196 const int* ptr = field->data();
197 do {
198 field->Add(0);
199 } while (field->data() == ptr);
200
201 return field->size() - 1;
202}
203
204TEST(RepeatedField, ReserveMoreThanDouble) {
205 // Reserve more than double the previous space in the field and expect the
206 // field to reserve exactly the amount specified.
207 RepeatedField<int> field;
208 field.Reserve(20);
209
210 EXPECT_EQ(20, ReservedSpace(&field));
211}
212
213TEST(RepeatedField, ReserveLessThanDouble) {
214 // Reserve less than double the previous space in the field and expect the
215 // field to grow by double instead.
216 RepeatedField<int> field;
217 field.Reserve(20);
218 field.Reserve(30);
219
220 EXPECT_EQ(40, ReservedSpace(&field));
221}
222
223TEST(RepeatedField, ReserveLessThanExisting) {
224 // Reserve less than the previous space in the field and expect the
225 // field to not re-allocate at all.
226 RepeatedField<int> field;
227 field.Reserve(20);
228 const int* previous_ptr = field.data();
229 field.Reserve(10);
230
231 EXPECT_EQ(previous_ptr, field.data());
232 EXPECT_EQ(20, ReservedSpace(&field));
233}
234
jieluo@google.com4de8f552014-07-18 00:47:59 +0000235TEST(RepeatedField, Resize) {
236 RepeatedField<int> field;
237 field.Resize(2, 1);
238 EXPECT_EQ(2, field.size());
239 field.Resize(5, 2);
240 EXPECT_EQ(5, field.size());
241 field.Resize(4, 3);
242 ASSERT_EQ(4, field.size());
243 EXPECT_EQ(1, field.Get(0));
244 EXPECT_EQ(1, field.Get(1));
245 EXPECT_EQ(2, field.Get(2));
246 EXPECT_EQ(2, field.Get(3));
247 field.Resize(0, 4);
248 EXPECT_TRUE(field.empty());
249}
250
temporal40ee5512008-07-10 02:12:20 +0000251TEST(RepeatedField, MergeFrom) {
252 RepeatedField<int> source, destination;
temporal40ee5512008-07-10 02:12:20 +0000253 source.Add(4);
254 source.Add(5);
temporal40ee5512008-07-10 02:12:20 +0000255 destination.Add(1);
256 destination.Add(2);
257 destination.Add(3);
258
259 destination.MergeFrom(source);
260
261 ASSERT_EQ(5, destination.size());
temporal40ee5512008-07-10 02:12:20 +0000262 EXPECT_EQ(1, destination.Get(0));
263 EXPECT_EQ(2, destination.Get(1));
264 EXPECT_EQ(3, destination.Get(2));
265 EXPECT_EQ(4, destination.Get(3));
266 EXPECT_EQ(5, destination.Get(4));
267}
268
jieluo@google.com4de8f552014-07-18 00:47:59 +0000269#ifdef PROTOBUF_HAS_DEATH_TEST
270TEST(RepeatedField, MergeFromSelf) {
271 RepeatedField<int> me;
272 me.Add(3);
273 EXPECT_DEATH(me.MergeFrom(me), "");
274}
275#endif // PROTOBUF_HAS_DEATH_TEST
276
liujisi@google.com33165fe2010-11-02 13:14:58 +0000277TEST(RepeatedField, CopyFrom) {
278 RepeatedField<int> source, destination;
liujisi@google.com33165fe2010-11-02 13:14:58 +0000279 source.Add(4);
280 source.Add(5);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000281 destination.Add(1);
282 destination.Add(2);
283 destination.Add(3);
284
285 destination.CopyFrom(source);
286
287 ASSERT_EQ(2, destination.size());
liujisi@google.com33165fe2010-11-02 13:14:58 +0000288 EXPECT_EQ(4, destination.Get(0));
289 EXPECT_EQ(5, destination.Get(1));
290}
291
jieluo@google.com4de8f552014-07-18 00:47:59 +0000292TEST(RepeatedField, CopyFromSelf) {
293 RepeatedField<int> me;
294 me.Add(3);
295 me.CopyFrom(me);
296 ASSERT_EQ(1, me.size());
297 EXPECT_EQ(3, me.Get(0));
298}
299
Feng Xiao6ef984a2014-11-10 17:34:54 -0800300TEST(RepeatedField, Erase) {
301 RepeatedField<int> me;
302 RepeatedField<int>::iterator it = me.erase(me.begin(), me.end());
303 EXPECT_TRUE(me.begin() == it);
304 EXPECT_EQ(0, me.size());
305
306 me.Add(1);
307 me.Add(2);
308 me.Add(3);
309 it = me.erase(me.begin(), me.end());
310 EXPECT_TRUE(me.begin() == it);
311 EXPECT_EQ(0, me.size());
312
313 me.Add(4);
314 me.Add(5);
315 me.Add(6);
316 it = me.erase(me.begin() + 2, me.end());
317 EXPECT_TRUE(me.begin() + 2 == it);
318 EXPECT_EQ(2, me.size());
319 EXPECT_EQ(4, me.Get(0));
320 EXPECT_EQ(5, me.Get(1));
321
322 me.Add(6);
323 me.Add(7);
324 me.Add(8);
325 it = me.erase(me.begin() + 1, me.begin() + 3);
326 EXPECT_TRUE(me.begin() + 1 == it);
327 EXPECT_EQ(3, me.size());
328 EXPECT_EQ(4, me.Get(0));
329 EXPECT_EQ(7, me.Get(1));
330 EXPECT_EQ(8, me.Get(2));
331}
332
liujisi@google.com33165fe2010-11-02 13:14:58 +0000333TEST(RepeatedField, CopyConstruct) {
334 RepeatedField<int> source;
335 source.Add(1);
336 source.Add(2);
337
338 RepeatedField<int> destination(source);
339
340 ASSERT_EQ(2, destination.size());
341 EXPECT_EQ(1, destination.Get(0));
342 EXPECT_EQ(2, destination.Get(1));
343}
344
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000345TEST(RepeatedField, IteratorConstruct) {
346 vector<int> values;
347 values.push_back(1);
348 values.push_back(2);
349
350 RepeatedField<int> field(values.begin(), values.end());
351 ASSERT_EQ(values.size(), field.size());
352 EXPECT_EQ(values[0], field.Get(0));
353 EXPECT_EQ(values[1], field.Get(1));
354
355 RepeatedField<int> other(field.begin(), field.end());
356 ASSERT_EQ(values.size(), other.size());
357 EXPECT_EQ(values[0], other.Get(0));
358 EXPECT_EQ(values[1], other.Get(1));
359}
360
liujisi@google.com33165fe2010-11-02 13:14:58 +0000361TEST(RepeatedField, CopyAssign) {
362 RepeatedField<int> source, destination;
liujisi@google.com33165fe2010-11-02 13:14:58 +0000363 source.Add(4);
364 source.Add(5);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000365 destination.Add(1);
366 destination.Add(2);
367 destination.Add(3);
368
369 destination = source;
370
371 ASSERT_EQ(2, destination.size());
liujisi@google.com33165fe2010-11-02 13:14:58 +0000372 EXPECT_EQ(4, destination.Get(0));
373 EXPECT_EQ(5, destination.Get(1));
374}
375
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000376TEST(RepeatedField, SelfAssign) {
377 // Verify that assignment to self does not destroy data.
378 RepeatedField<int> source, *p;
379 p = &source;
380 source.Add(7);
381 source.Add(8);
382
383 *p = source;
384
385 ASSERT_EQ(2, source.size());
386 EXPECT_EQ(7, source.Get(0));
387 EXPECT_EQ(8, source.Get(1));
388}
389
temporal40ee5512008-07-10 02:12:20 +0000390TEST(RepeatedField, MutableDataIsMutable) {
391 RepeatedField<int> field;
392 field.Add(1);
393 EXPECT_EQ(1, field.Get(0));
394 // The fact that this line compiles would be enough, but we'll check the
395 // value anyway.
396 *field.mutable_data() = 2;
397 EXPECT_EQ(2, field.Get(0));
398}
399
kenton@google.comfccb1462009-12-18 02:11:36 +0000400TEST(RepeatedField, Truncate) {
401 RepeatedField<int> field;
402
403 field.Add(12);
404 field.Add(34);
405 field.Add(56);
406 field.Add(78);
407 EXPECT_EQ(4, field.size());
408
409 field.Truncate(3);
410 EXPECT_EQ(3, field.size());
411
412 field.Add(90);
413 EXPECT_EQ(4, field.size());
414 EXPECT_EQ(90, field.Get(3));
415
416 // Truncations that don't change the size are allowed, but growing is not
417 // allowed.
418 field.Truncate(field.size());
liujisi@google.comf5d5b4d2012-12-05 05:54:48 +0000419#ifdef PROTOBUF_HAS_DEATH_TEST
kenton@google.comfccb1462009-12-18 02:11:36 +0000420 EXPECT_DEBUG_DEATH(field.Truncate(field.size() + 1), "new_size");
kenton@google.com684d45b2009-12-19 04:50:00 +0000421#endif
kenton@google.comfccb1462009-12-18 02:11:36 +0000422}
423
424
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000425TEST(RepeatedField, ExtractSubrange) {
426 // Exhaustively test every subrange in arrays of all sizes from 0 through 9.
427 for (int sz = 0; sz < 10; ++sz) {
428 for (int num = 0; num <= sz; ++num) {
429 for (int start = 0; start < sz - num; ++start) {
430 // Create RepeatedField with sz elements having values 0 through sz-1.
431 RepeatedField<int32> field;
432 for (int i = 0; i < sz; ++i)
433 field.Add(i);
434 EXPECT_EQ(field.size(), sz);
435
436 // Create a catcher array and call ExtractSubrange.
437 int32 catcher[10];
438 for (int i = 0; i < 10; ++i)
439 catcher[i] = -1;
440 field.ExtractSubrange(start, num, catcher);
441
442 // Does the resulting array have the right size?
443 EXPECT_EQ(field.size(), sz - num);
444
445 // Were the removed elements extracted into the catcher array?
446 for (int i = 0; i < num; ++i)
447 EXPECT_EQ(catcher[i], start + i);
448 EXPECT_EQ(catcher[num], -1);
449
450 // Does the resulting array contain the right values?
451 for (int i = 0; i < start; ++i)
452 EXPECT_EQ(field.Get(i), i);
453 for (int i = start; i < field.size(); ++i)
454 EXPECT_EQ(field.Get(i), i + num);
455 }
456 }
457 }
458}
459
Bo Yang5db21732015-05-21 14:28:59 -0700460TEST(RepeatedField, ClearThenReserveMore) {
461 // Test that Reserve properly destroys the old internal array when it's forced
462 // to allocate a new one, even when cleared-but-not-deleted objects are
463 // present. Use a 'string' and > 16 bytes length so that the elements are
464 // non-POD and allocate -- the leak checker will catch any skipped destructor
465 // calls here.
466 RepeatedField<string> field;
467 for (int i = 0; i < 32; i++) {
468 field.Add(string("abcdefghijklmnopqrstuvwxyz0123456789"));
469 }
470 EXPECT_EQ(32, field.size());
471 field.Clear();
472 EXPECT_EQ(0, field.size());
473 EXPECT_EQ(32, field.Capacity());
474
475 field.Reserve(1024);
476 EXPECT_EQ(0, field.size());
477 EXPECT_EQ(1024, field.Capacity());
478 // Finish test -- |field| should destroy the cleared-but-not-yet-destroyed
479 // strings.
480}
481
temporal40ee5512008-07-10 02:12:20 +0000482// ===================================================================
483// RepeatedPtrField tests. These pretty much just mirror the RepeatedField
484// tests above.
485
486TEST(RepeatedPtrField, Small) {
487 RepeatedPtrField<string> field;
488
jieluo@google.com4de8f552014-07-18 00:47:59 +0000489 EXPECT_TRUE(field.empty());
temporal40ee5512008-07-10 02:12:20 +0000490 EXPECT_EQ(field.size(), 0);
491
492 field.Add()->assign("foo");
493
jieluo@google.com4de8f552014-07-18 00:47:59 +0000494 EXPECT_FALSE(field.empty());
temporal40ee5512008-07-10 02:12:20 +0000495 EXPECT_EQ(field.size(), 1);
496 EXPECT_EQ(field.Get(0), "foo");
497
498 field.Add()->assign("bar");
499
jieluo@google.com4de8f552014-07-18 00:47:59 +0000500 EXPECT_FALSE(field.empty());
temporal40ee5512008-07-10 02:12:20 +0000501 EXPECT_EQ(field.size(), 2);
502 EXPECT_EQ(field.Get(0), "foo");
503 EXPECT_EQ(field.Get(1), "bar");
504
505 field.Mutable(1)->assign("baz");
506
jieluo@google.com4de8f552014-07-18 00:47:59 +0000507 EXPECT_FALSE(field.empty());
temporal40ee5512008-07-10 02:12:20 +0000508 EXPECT_EQ(field.size(), 2);
509 EXPECT_EQ(field.Get(0), "foo");
510 EXPECT_EQ(field.Get(1), "baz");
511
512 field.RemoveLast();
513
jieluo@google.com4de8f552014-07-18 00:47:59 +0000514 EXPECT_FALSE(field.empty());
temporal40ee5512008-07-10 02:12:20 +0000515 EXPECT_EQ(field.size(), 1);
516 EXPECT_EQ(field.Get(0), "foo");
517
518 field.Clear();
519
jieluo@google.com4de8f552014-07-18 00:47:59 +0000520 EXPECT_TRUE(field.empty());
temporal40ee5512008-07-10 02:12:20 +0000521 EXPECT_EQ(field.size(), 0);
522}
523
524TEST(RepeatedPtrField, Large) {
525 RepeatedPtrField<string> field;
526
527 for (int i = 0; i < 16; i++) {
528 *field.Add() += 'a' + i;
529 }
530
531 EXPECT_EQ(field.size(), 16);
532
533 for (int i = 0; i < 16; i++) {
534 EXPECT_EQ(field.Get(i).size(), 1);
535 EXPECT_EQ(field.Get(i)[0], 'a' + i);
536 }
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000537
538 int min_expected_usage = 16 * sizeof(string);
539 EXPECT_GE(field.SpaceUsedExcludingSelf(), min_expected_usage);
temporal40ee5512008-07-10 02:12:20 +0000540}
541
542TEST(RepeatedPtrField, SwapSmallSmall) {
543 RepeatedPtrField<string> field1;
544 RepeatedPtrField<string> field2;
545
jieluo@google.com4de8f552014-07-18 00:47:59 +0000546 EXPECT_TRUE(field1.empty());
547 EXPECT_EQ(field1.size(), 0);
548 EXPECT_TRUE(field2.empty());
549 EXPECT_EQ(field2.size(), 0);
550
temporal40ee5512008-07-10 02:12:20 +0000551 field1.Add()->assign("foo");
552 field1.Add()->assign("bar");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000553
554 EXPECT_FALSE(field1.empty());
555 EXPECT_EQ(field1.size(), 2);
556 EXPECT_EQ(field1.Get(0), "foo");
557 EXPECT_EQ(field1.Get(1), "bar");
558
559 EXPECT_TRUE(field2.empty());
560 EXPECT_EQ(field2.size(), 0);
561
temporal40ee5512008-07-10 02:12:20 +0000562 field1.Swap(&field2);
563
jieluo@google.com4de8f552014-07-18 00:47:59 +0000564 EXPECT_TRUE(field1.empty());
temporal40ee5512008-07-10 02:12:20 +0000565 EXPECT_EQ(field1.size(), 0);
jieluo@google.com4de8f552014-07-18 00:47:59 +0000566
temporal40ee5512008-07-10 02:12:20 +0000567 EXPECT_EQ(field2.size(), 2);
568 EXPECT_EQ(field2.Get(0), "foo");
569 EXPECT_EQ(field2.Get(1), "bar");
570}
571
572TEST(RepeatedPtrField, SwapLargeSmall) {
573 RepeatedPtrField<string> field1;
574 RepeatedPtrField<string> field2;
575
576 field2.Add()->assign("foo");
577 field2.Add()->assign("bar");
578 for (int i = 0; i < 16; i++) {
579 *field1.Add() += 'a' + i;
580 }
581 field1.Swap(&field2);
582
583 EXPECT_EQ(field1.size(), 2);
584 EXPECT_EQ(field1.Get(0), "foo");
585 EXPECT_EQ(field1.Get(1), "bar");
586 EXPECT_EQ(field2.size(), 16);
587 for (int i = 0; i < 16; i++) {
588 EXPECT_EQ(field2.Get(i).size(), 1);
589 EXPECT_EQ(field2.Get(i)[0], 'a' + i);
590 }
591}
592
593TEST(RepeatedPtrField, SwapLargeLarge) {
594 RepeatedPtrField<string> field1;
595 RepeatedPtrField<string> field2;
596
597 field1.Add()->assign("foo");
598 field1.Add()->assign("bar");
599 for (int i = 0; i < 16; i++) {
600 *field1.Add() += 'A' + i;
601 *field2.Add() += 'a' + i;
602 }
603 field2.Swap(&field1);
604
605 EXPECT_EQ(field1.size(), 16);
606 for (int i = 0; i < 16; i++) {
607 EXPECT_EQ(field1.Get(i).size(), 1);
608 EXPECT_EQ(field1.Get(i)[0], 'a' + i);
609 }
610 EXPECT_EQ(field2.size(), 18);
611 EXPECT_EQ(field2.Get(0), "foo");
612 EXPECT_EQ(field2.Get(1), "bar");
613 for (int i = 2; i < 18; i++) {
614 EXPECT_EQ(field2.Get(i).size(), 1);
615 EXPECT_EQ(field2.Get(i)[0], 'A' + i - 2);
616 }
617}
618
619static int ReservedSpace(RepeatedPtrField<string>* field) {
620 const string* const* ptr = field->data();
621 do {
622 field->Add();
623 } while (field->data() == ptr);
624
625 return field->size() - 1;
626}
627
628TEST(RepeatedPtrField, ReserveMoreThanDouble) {
629 RepeatedPtrField<string> field;
630 field.Reserve(20);
631
632 EXPECT_EQ(20, ReservedSpace(&field));
633}
634
635TEST(RepeatedPtrField, ReserveLessThanDouble) {
636 RepeatedPtrField<string> field;
637 field.Reserve(20);
638 field.Reserve(30);
639
640 EXPECT_EQ(40, ReservedSpace(&field));
641}
642
643TEST(RepeatedPtrField, ReserveLessThanExisting) {
644 RepeatedPtrField<string> field;
645 field.Reserve(20);
646 const string* const* previous_ptr = field.data();
647 field.Reserve(10);
648
649 EXPECT_EQ(previous_ptr, field.data());
650 EXPECT_EQ(20, ReservedSpace(&field));
651}
652
653TEST(RepeatedPtrField, ReserveDoesntLoseAllocated) {
654 // Check that a bug is fixed: An earlier implementation of Reserve()
655 // failed to copy pointers to allocated-but-cleared objects, possibly
656 // leading to segfaults.
657 RepeatedPtrField<string> field;
658 string* first = field.Add();
659 field.RemoveLast();
660
661 field.Reserve(20);
662 EXPECT_EQ(first, field.Add());
663}
664
665// Clearing elements is tricky with RepeatedPtrFields since the memory for
666// the elements is retained and reused.
667TEST(RepeatedPtrField, ClearedElements) {
668 RepeatedPtrField<string> field;
669
670 string* original = field.Add();
671 *original = "foo";
672
673 EXPECT_EQ(field.ClearedCount(), 0);
674
675 field.RemoveLast();
676 EXPECT_TRUE(original->empty());
677 EXPECT_EQ(field.ClearedCount(), 1);
678
679 EXPECT_EQ(field.Add(), original); // Should return same string for reuse.
680
681 EXPECT_EQ(field.ReleaseLast(), original); // We take ownership.
682 EXPECT_EQ(field.ClearedCount(), 0);
683
684 EXPECT_NE(field.Add(), original); // Should NOT return the same string.
685 EXPECT_EQ(field.ClearedCount(), 0);
686
687 field.AddAllocated(original); // Give ownership back.
688 EXPECT_EQ(field.ClearedCount(), 0);
689 EXPECT_EQ(field.Mutable(1), original);
690
691 field.Clear();
692 EXPECT_EQ(field.ClearedCount(), 2);
693 EXPECT_EQ(field.ReleaseCleared(), original); // Take ownership again.
694 EXPECT_EQ(field.ClearedCount(), 1);
695 EXPECT_NE(field.Add(), original);
696 EXPECT_EQ(field.ClearedCount(), 0);
697 EXPECT_NE(field.Add(), original);
698 EXPECT_EQ(field.ClearedCount(), 0);
699
700 field.AddCleared(original); // Give ownership back, but as a cleared object.
701 EXPECT_EQ(field.ClearedCount(), 1);
702 EXPECT_EQ(field.Add(), original);
703 EXPECT_EQ(field.ClearedCount(), 0);
704}
705
kenton@google.comfccb1462009-12-18 02:11:36 +0000706// Test all code paths in AddAllocated().
707TEST(RepeatedPtrField, AddAlocated) {
708 RepeatedPtrField<string> field;
709 while (field.size() < field.Capacity()) {
710 field.Add()->assign("filler");
711 }
712
713 int index = field.size();
714
715 // First branch: Field is at capacity with no cleared objects.
716 string* foo = new string("foo");
717 field.AddAllocated(foo);
718 EXPECT_EQ(index + 1, field.size());
719 EXPECT_EQ(0, field.ClearedCount());
720 EXPECT_EQ(foo, &field.Get(index));
721
722 // Last branch: Field is not at capacity and there are no cleared objects.
723 string* bar = new string("bar");
724 field.AddAllocated(bar);
725 ++index;
726 EXPECT_EQ(index + 1, field.size());
727 EXPECT_EQ(0, field.ClearedCount());
728 EXPECT_EQ(bar, &field.Get(index));
729
730 // Third branch: Field is not at capacity and there are no cleared objects.
731 field.RemoveLast();
732 string* baz = new string("baz");
733 field.AddAllocated(baz);
734 EXPECT_EQ(index + 1, field.size());
735 EXPECT_EQ(1, field.ClearedCount());
736 EXPECT_EQ(baz, &field.Get(index));
737
738 // Second branch: Field is at capacity but has some cleared objects.
739 while (field.size() < field.Capacity()) {
740 field.Add()->assign("filler2");
741 }
742 field.RemoveLast();
743 index = field.size();
744 string* qux = new string("qux");
745 field.AddAllocated(qux);
746 EXPECT_EQ(index + 1, field.size());
747 // We should have discarded the cleared object.
748 EXPECT_EQ(0, field.ClearedCount());
749 EXPECT_EQ(qux, &field.Get(index));
750}
751
temporal40ee5512008-07-10 02:12:20 +0000752TEST(RepeatedPtrField, MergeFrom) {
753 RepeatedPtrField<string> source, destination;
temporal40ee5512008-07-10 02:12:20 +0000754 source.Add()->assign("4");
755 source.Add()->assign("5");
temporal40ee5512008-07-10 02:12:20 +0000756 destination.Add()->assign("1");
757 destination.Add()->assign("2");
758 destination.Add()->assign("3");
759
760 destination.MergeFrom(source);
761
762 ASSERT_EQ(5, destination.size());
temporal40ee5512008-07-10 02:12:20 +0000763 EXPECT_EQ("1", destination.Get(0));
764 EXPECT_EQ("2", destination.Get(1));
765 EXPECT_EQ("3", destination.Get(2));
766 EXPECT_EQ("4", destination.Get(3));
767 EXPECT_EQ("5", destination.Get(4));
768}
769
jieluo@google.com4de8f552014-07-18 00:47:59 +0000770#ifdef PROTOBUF_HAS_DEATH_TEST
771TEST(RepeatedPtrField, MergeFromSelf) {
772 RepeatedPtrField<string> me;
773 me.Add()->assign("1");
774 EXPECT_DEATH(me.MergeFrom(me), "");
775}
776#endif // PROTOBUF_HAS_DEATH_TEST
777
liujisi@google.com33165fe2010-11-02 13:14:58 +0000778TEST(RepeatedPtrField, CopyFrom) {
779 RepeatedPtrField<string> source, destination;
liujisi@google.com33165fe2010-11-02 13:14:58 +0000780 source.Add()->assign("4");
781 source.Add()->assign("5");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000782 destination.Add()->assign("1");
783 destination.Add()->assign("2");
784 destination.Add()->assign("3");
785
786 destination.CopyFrom(source);
787
788 ASSERT_EQ(2, destination.size());
liujisi@google.com33165fe2010-11-02 13:14:58 +0000789 EXPECT_EQ("4", destination.Get(0));
790 EXPECT_EQ("5", destination.Get(1));
791}
792
jieluo@google.com4de8f552014-07-18 00:47:59 +0000793TEST(RepeatedPtrField, CopyFromSelf) {
794 RepeatedPtrField<string> me;
795 me.Add()->assign("1");
796 me.CopyFrom(me);
797 ASSERT_EQ(1, me.size());
798 EXPECT_EQ("1", me.Get(0));
799}
800
Feng Xiao6ef984a2014-11-10 17:34:54 -0800801TEST(RepeatedPtrField, Erase) {
802 RepeatedPtrField<string> me;
803 RepeatedPtrField<string>::iterator it = me.erase(me.begin(), me.end());
804 EXPECT_TRUE(me.begin() == it);
805 EXPECT_EQ(0, me.size());
806
807 *me.Add() = "1";
808 *me.Add() = "2";
809 *me.Add() = "3";
810 it = me.erase(me.begin(), me.end());
811 EXPECT_TRUE(me.begin() == it);
812 EXPECT_EQ(0, me.size());
813
814 *me.Add() = "4";
815 *me.Add() = "5";
816 *me.Add() = "6";
817 it = me.erase(me.begin() + 2, me.end());
818 EXPECT_TRUE(me.begin() + 2 == it);
819 EXPECT_EQ(2, me.size());
820 EXPECT_EQ("4", me.Get(0));
821 EXPECT_EQ("5", me.Get(1));
822
823 *me.Add() = "6";
824 *me.Add() = "7";
825 *me.Add() = "8";
826 it = me.erase(me.begin() + 1, me.begin() + 3);
827 EXPECT_TRUE(me.begin() + 1 == it);
828 EXPECT_EQ(3, me.size());
829 EXPECT_EQ("4", me.Get(0));
830 EXPECT_EQ("7", me.Get(1));
831 EXPECT_EQ("8", me.Get(2));
832}
833
liujisi@google.com33165fe2010-11-02 13:14:58 +0000834TEST(RepeatedPtrField, CopyConstruct) {
835 RepeatedPtrField<string> source;
liujisi@google.com33165fe2010-11-02 13:14:58 +0000836 source.Add()->assign("1");
837 source.Add()->assign("2");
838
839 RepeatedPtrField<string> destination(source);
840
841 ASSERT_EQ(2, destination.size());
842 EXPECT_EQ("1", destination.Get(0));
843 EXPECT_EQ("2", destination.Get(1));
844}
845
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000846TEST(RepeatedPtrField, IteratorConstruct_String) {
847 vector<string> values;
848 values.push_back("1");
849 values.push_back("2");
850
851 RepeatedPtrField<string> field(values.begin(), values.end());
852 ASSERT_EQ(values.size(), field.size());
853 EXPECT_EQ(values[0], field.Get(0));
854 EXPECT_EQ(values[1], field.Get(1));
855
856 RepeatedPtrField<string> other(field.begin(), field.end());
857 ASSERT_EQ(values.size(), other.size());
858 EXPECT_EQ(values[0], other.Get(0));
859 EXPECT_EQ(values[1], other.Get(1));
860}
861
862TEST(RepeatedPtrField, IteratorConstruct_Proto) {
863 typedef TestAllTypes::NestedMessage Nested;
864 vector<Nested> values;
865 values.push_back(Nested());
866 values.back().set_bb(1);
867 values.push_back(Nested());
868 values.back().set_bb(2);
869
870 RepeatedPtrField<Nested> field(values.begin(), values.end());
871 ASSERT_EQ(values.size(), field.size());
872 EXPECT_EQ(values[0].bb(), field.Get(0).bb());
873 EXPECT_EQ(values[1].bb(), field.Get(1).bb());
874
875 RepeatedPtrField<Nested> other(field.begin(), field.end());
876 ASSERT_EQ(values.size(), other.size());
877 EXPECT_EQ(values[0].bb(), other.Get(0).bb());
878 EXPECT_EQ(values[1].bb(), other.Get(1).bb());
879}
880
liujisi@google.com33165fe2010-11-02 13:14:58 +0000881TEST(RepeatedPtrField, CopyAssign) {
882 RepeatedPtrField<string> source, destination;
liujisi@google.com33165fe2010-11-02 13:14:58 +0000883 source.Add()->assign("4");
884 source.Add()->assign("5");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000885 destination.Add()->assign("1");
886 destination.Add()->assign("2");
887 destination.Add()->assign("3");
888
889 destination = source;
890
891 ASSERT_EQ(2, destination.size());
liujisi@google.com33165fe2010-11-02 13:14:58 +0000892 EXPECT_EQ("4", destination.Get(0));
893 EXPECT_EQ("5", destination.Get(1));
894}
895
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000896TEST(RepeatedPtrField, SelfAssign) {
897 // Verify that assignment to self does not destroy data.
898 RepeatedPtrField<string> source, *p;
899 p = &source;
900 source.Add()->assign("7");
901 source.Add()->assign("8");
902
903 *p = source;
904
905 ASSERT_EQ(2, source.size());
906 EXPECT_EQ("7", source.Get(0));
907 EXPECT_EQ("8", source.Get(1));
908}
909
temporal40ee5512008-07-10 02:12:20 +0000910TEST(RepeatedPtrField, MutableDataIsMutable) {
911 RepeatedPtrField<string> field;
912 *field.Add() = "1";
913 EXPECT_EQ("1", field.Get(0));
914 // The fact that this line compiles would be enough, but we'll check the
915 // value anyway.
916 string** data = field.mutable_data();
917 **data = "2";
918 EXPECT_EQ("2", field.Get(0));
919}
920
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000921TEST(RepeatedPtrField, ExtractSubrange) {
922 // Exhaustively test every subrange in arrays of all sizes from 0 through 9
923 // with 0 through 3 cleared elements at the end.
924 for (int sz = 0; sz < 10; ++sz) {
925 for (int num = 0; num <= sz; ++num) {
926 for (int start = 0; start < sz - num; ++start) {
927 for (int extra = 0; extra < 4; ++extra) {
928 vector<string*> subject;
929
930 // Create an array with "sz" elements and "extra" cleared elements.
931 RepeatedPtrField<string> field;
932 for (int i = 0; i < sz + extra; ++i) {
933 subject.push_back(new string());
934 field.AddAllocated(subject[i]);
935 }
936 EXPECT_EQ(field.size(), sz + extra);
937 for (int i = 0; i < extra; ++i)
938 field.RemoveLast();
939 EXPECT_EQ(field.size(), sz);
940 EXPECT_EQ(field.ClearedCount(), extra);
941
942 // Create a catcher array and call ExtractSubrange.
943 string* catcher[10];
944 for (int i = 0; i < 10; ++i)
945 catcher[i] = NULL;
946 field.ExtractSubrange(start, num, catcher);
947
948 // Does the resulting array have the right size?
949 EXPECT_EQ(field.size(), sz - num);
950
951 // Were the removed elements extracted into the catcher array?
952 for (int i = 0; i < num; ++i)
953 EXPECT_EQ(catcher[i], subject[start + i]);
954 EXPECT_EQ(NULL, catcher[num]);
955
956 // Does the resulting array contain the right values?
957 for (int i = 0; i < start; ++i)
958 EXPECT_EQ(field.Mutable(i), subject[i]);
959 for (int i = start; i < field.size(); ++i)
960 EXPECT_EQ(field.Mutable(i), subject[i + num]);
961
962 // Reinstate the cleared elements.
963 EXPECT_EQ(field.ClearedCount(), extra);
964 for (int i = 0; i < extra; ++i)
965 field.Add();
966 EXPECT_EQ(field.ClearedCount(), 0);
967 EXPECT_EQ(field.size(), sz - num + extra);
968
969 // Make sure the extra elements are all there (in some order).
970 for (int i = sz; i < sz + extra; ++i) {
971 int count = 0;
972 for (int j = sz; j < sz + extra; ++j) {
973 if (field.Mutable(j - num) == subject[i])
974 count += 1;
975 }
976 EXPECT_EQ(count, 1);
977 }
978
979 // Release the caught elements.
980 for (int i = 0; i < num; ++i)
981 delete catcher[i];
982 }
983 }
984 }
985 }
986}
987
988TEST(RepeatedPtrField, DeleteSubrange) {
989 // DeleteSubrange is a trivial extension of ExtendSubrange.
990}
991
temporal40ee5512008-07-10 02:12:20 +0000992// ===================================================================
993
994// Iterator tests stolen from net/proto/proto-array_unittest.
995class RepeatedFieldIteratorTest : public testing::Test {
996 protected:
997 virtual void SetUp() {
998 for (int i = 0; i < 3; ++i) {
999 proto_array_.Add(i);
1000 }
1001 }
1002
1003 RepeatedField<int> proto_array_;
1004};
1005
1006TEST_F(RepeatedFieldIteratorTest, Convertible) {
1007 RepeatedField<int>::iterator iter = proto_array_.begin();
1008 RepeatedField<int>::const_iterator c_iter = iter;
liujisi@google.com33165fe2010-11-02 13:14:58 +00001009 RepeatedField<int>::value_type value = *c_iter;
1010 EXPECT_EQ(0, value);
temporal40ee5512008-07-10 02:12:20 +00001011}
1012
1013TEST_F(RepeatedFieldIteratorTest, MutableIteration) {
1014 RepeatedField<int>::iterator iter = proto_array_.begin();
1015 EXPECT_EQ(0, *iter);
1016 ++iter;
1017 EXPECT_EQ(1, *iter++);
1018 EXPECT_EQ(2, *iter);
1019 ++iter;
1020 EXPECT_TRUE(proto_array_.end() == iter);
1021
1022 EXPECT_EQ(2, *(proto_array_.end() - 1));
1023}
1024
1025TEST_F(RepeatedFieldIteratorTest, ConstIteration) {
1026 const RepeatedField<int>& const_proto_array = proto_array_;
1027 RepeatedField<int>::const_iterator iter = const_proto_array.begin();
1028 EXPECT_EQ(0, *iter);
1029 ++iter;
1030 EXPECT_EQ(1, *iter++);
1031 EXPECT_EQ(2, *iter);
1032 ++iter;
1033 EXPECT_TRUE(proto_array_.end() == iter);
1034 EXPECT_EQ(2, *(proto_array_.end() - 1));
1035}
1036
1037TEST_F(RepeatedFieldIteratorTest, Mutation) {
1038 RepeatedField<int>::iterator iter = proto_array_.begin();
1039 *iter = 7;
1040 EXPECT_EQ(7, proto_array_.Get(0));
1041}
1042
1043// -------------------------------------------------------------------
1044
1045class RepeatedPtrFieldIteratorTest : public testing::Test {
1046 protected:
1047 virtual void SetUp() {
1048 proto_array_.Add()->assign("foo");
1049 proto_array_.Add()->assign("bar");
1050 proto_array_.Add()->assign("baz");
1051 }
1052
1053 RepeatedPtrField<string> proto_array_;
1054};
1055
1056TEST_F(RepeatedPtrFieldIteratorTest, Convertible) {
1057 RepeatedPtrField<string>::iterator iter = proto_array_.begin();
1058 RepeatedPtrField<string>::const_iterator c_iter = iter;
liujisi@google.com33165fe2010-11-02 13:14:58 +00001059 RepeatedPtrField<string>::value_type value = *c_iter;
1060 EXPECT_EQ("foo", value);
temporal40ee5512008-07-10 02:12:20 +00001061}
1062
1063TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) {
1064 RepeatedPtrField<string>::iterator iter = proto_array_.begin();
1065 EXPECT_EQ("foo", *iter);
1066 ++iter;
1067 EXPECT_EQ("bar", *(iter++));
1068 EXPECT_EQ("baz", *iter);
1069 ++iter;
1070 EXPECT_TRUE(proto_array_.end() == iter);
1071 EXPECT_EQ("baz", *(--proto_array_.end()));
1072}
1073
1074TEST_F(RepeatedPtrFieldIteratorTest, ConstIteration) {
1075 const RepeatedPtrField<string>& const_proto_array = proto_array_;
1076 RepeatedPtrField<string>::const_iterator iter = const_proto_array.begin();
1077 EXPECT_EQ("foo", *iter);
1078 ++iter;
1079 EXPECT_EQ("bar", *(iter++));
1080 EXPECT_EQ("baz", *iter);
1081 ++iter;
1082 EXPECT_TRUE(const_proto_array.end() == iter);
1083 EXPECT_EQ("baz", *(--const_proto_array.end()));
1084}
1085
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001086TEST_F(RepeatedPtrFieldIteratorTest, MutableReverseIteration) {
1087 RepeatedPtrField<string>::reverse_iterator iter = proto_array_.rbegin();
1088 EXPECT_EQ("baz", *iter);
1089 ++iter;
1090 EXPECT_EQ("bar", *(iter++));
1091 EXPECT_EQ("foo", *iter);
1092 ++iter;
1093 EXPECT_TRUE(proto_array_.rend() == iter);
1094 EXPECT_EQ("foo", *(--proto_array_.rend()));
1095}
1096
1097TEST_F(RepeatedPtrFieldIteratorTest, ConstReverseIteration) {
1098 const RepeatedPtrField<string>& const_proto_array = proto_array_;
1099 RepeatedPtrField<string>::const_reverse_iterator iter
1100 = const_proto_array.rbegin();
1101 EXPECT_EQ("baz", *iter);
1102 ++iter;
1103 EXPECT_EQ("bar", *(iter++));
1104 EXPECT_EQ("foo", *iter);
1105 ++iter;
1106 EXPECT_TRUE(const_proto_array.rend() == iter);
1107 EXPECT_EQ("foo", *(--const_proto_array.rend()));
1108}
1109
temporal40ee5512008-07-10 02:12:20 +00001110TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) {
1111 RepeatedPtrField<string>::iterator iter = proto_array_.begin();
1112 RepeatedPtrField<string>::iterator iter2 = iter;
1113 ++iter2;
1114 ++iter2;
1115 EXPECT_TRUE(iter + 2 == iter2);
1116 EXPECT_TRUE(iter == iter2 - 2);
1117 EXPECT_EQ("baz", iter[2]);
1118 EXPECT_EQ("baz", *(iter + 2));
1119 EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
1120}
1121
1122TEST_F(RepeatedPtrFieldIteratorTest, Comparable) {
1123 RepeatedPtrField<string>::const_iterator iter = proto_array_.begin();
1124 RepeatedPtrField<string>::const_iterator iter2 = iter + 1;
1125 EXPECT_TRUE(iter == iter);
1126 EXPECT_TRUE(iter != iter2);
1127 EXPECT_TRUE(iter < iter2);
1128 EXPECT_TRUE(iter <= iter2);
1129 EXPECT_TRUE(iter <= iter);
1130 EXPECT_TRUE(iter2 > iter);
1131 EXPECT_TRUE(iter2 >= iter);
1132 EXPECT_TRUE(iter >= iter);
1133}
1134
1135// Uninitialized iterator does not point to any of the RepeatedPtrField.
temporal40ee5512008-07-10 02:12:20 +00001136TEST_F(RepeatedPtrFieldIteratorTest, UninitializedIterator) {
1137 RepeatedPtrField<string>::iterator iter;
1138 EXPECT_TRUE(iter != proto_array_.begin());
1139 EXPECT_TRUE(iter != proto_array_.begin() + 1);
1140 EXPECT_TRUE(iter != proto_array_.begin() + 2);
1141 EXPECT_TRUE(iter != proto_array_.begin() + 3);
1142 EXPECT_TRUE(iter != proto_array_.end());
temporal40ee5512008-07-10 02:12:20 +00001143}
1144
1145TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) {
1146 proto_array_.Clear();
1147 proto_array_.Add()->assign("a");
1148 proto_array_.Add()->assign("c");
1149 proto_array_.Add()->assign("d");
1150 proto_array_.Add()->assign("n");
1151 proto_array_.Add()->assign("p");
1152 proto_array_.Add()->assign("x");
1153 proto_array_.Add()->assign("y");
1154
1155 string v = "f";
1156 RepeatedPtrField<string>::const_iterator it =
Jisi Liu885b6122015-02-28 14:51:22 -08001157 std::lower_bound(proto_array_.begin(), proto_array_.end(), v);
kenton@google.comfccb1462009-12-18 02:11:36 +00001158
temporal40ee5512008-07-10 02:12:20 +00001159 EXPECT_EQ(*it, "n");
1160 EXPECT_TRUE(it == proto_array_.begin() + 3);
1161}
1162
1163TEST_F(RepeatedPtrFieldIteratorTest, Mutation) {
1164 RepeatedPtrField<string>::iterator iter = proto_array_.begin();
1165 *iter = "qux";
1166 EXPECT_EQ("qux", proto_array_.Get(0));
1167}
1168
kenton@google.comfccb1462009-12-18 02:11:36 +00001169// -------------------------------------------------------------------
1170
1171class RepeatedPtrFieldPtrsIteratorTest : public testing::Test {
1172 protected:
1173 virtual void SetUp() {
1174 proto_array_.Add()->assign("foo");
1175 proto_array_.Add()->assign("bar");
1176 proto_array_.Add()->assign("baz");
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001177 const_proto_array_ = &proto_array_;
kenton@google.comfccb1462009-12-18 02:11:36 +00001178 }
1179
1180 RepeatedPtrField<string> proto_array_;
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001181 const RepeatedPtrField<string>* const_proto_array_;
kenton@google.comfccb1462009-12-18 02:11:36 +00001182};
1183
1184TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) {
1185 RepeatedPtrField<string>::pointer_iterator iter =
1186 proto_array_.pointer_begin();
jieluo@google.com4de8f552014-07-18 00:47:59 +00001187 static_cast<void>(iter);
kenton@google.comfccb1462009-12-18 02:11:36 +00001188}
1189
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001190TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) {
1191 RepeatedPtrField<string>::const_pointer_iterator iter =
1192 const_proto_array_->pointer_begin();
jieluo@google.com4de8f552014-07-18 00:47:59 +00001193 static_cast<void>(iter);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001194}
1195
kenton@google.comfccb1462009-12-18 02:11:36 +00001196TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) {
1197 RepeatedPtrField<string>::pointer_iterator iter =
1198 proto_array_.pointer_begin();
1199 EXPECT_EQ("foo", **iter);
1200 ++iter;
1201 EXPECT_EQ("bar", **(iter++));
1202 EXPECT_EQ("baz", **iter);
1203 ++iter;
1204 EXPECT_TRUE(proto_array_.pointer_end() == iter);
1205 EXPECT_EQ("baz", **(--proto_array_.pointer_end()));
1206}
1207
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001208TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutableConstPtrIteration) {
1209 RepeatedPtrField<string>::const_pointer_iterator iter =
1210 const_proto_array_->pointer_begin();
1211 EXPECT_EQ("foo", **iter);
1212 ++iter;
1213 EXPECT_EQ("bar", **(iter++));
1214 EXPECT_EQ("baz", **iter);
1215 ++iter;
1216 EXPECT_TRUE(const_proto_array_->pointer_end() == iter);
1217 EXPECT_EQ("baz", **(--const_proto_array_->pointer_end()));
1218}
1219
kenton@google.comfccb1462009-12-18 02:11:36 +00001220TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) {
1221 RepeatedPtrField<string>::pointer_iterator iter =
1222 proto_array_.pointer_begin();
1223 RepeatedPtrField<string>::pointer_iterator iter2 = iter;
1224 ++iter2;
1225 ++iter2;
1226 EXPECT_TRUE(iter + 2 == iter2);
1227 EXPECT_TRUE(iter == iter2 - 2);
1228 EXPECT_EQ("baz", *iter[2]);
1229 EXPECT_EQ("baz", **(iter + 2));
1230 EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
1231}
1232
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001233TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomConstPtrAccess) {
1234 RepeatedPtrField<string>::const_pointer_iterator iter =
1235 const_proto_array_->pointer_begin();
1236 RepeatedPtrField<string>::const_pointer_iterator iter2 = iter;
1237 ++iter2;
1238 ++iter2;
1239 EXPECT_TRUE(iter + 2 == iter2);
1240 EXPECT_TRUE(iter == iter2 - 2);
1241 EXPECT_EQ("baz", *iter[2]);
1242 EXPECT_EQ("baz", **(iter + 2));
1243 EXPECT_EQ(3, const_proto_array_->end() - const_proto_array_->begin());
1244}
1245
kenton@google.comfccb1462009-12-18 02:11:36 +00001246TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) {
1247 RepeatedPtrField<string>::pointer_iterator iter =
1248 proto_array_.pointer_begin();
1249 RepeatedPtrField<string>::pointer_iterator iter2 = iter + 1;
1250 EXPECT_TRUE(iter == iter);
1251 EXPECT_TRUE(iter != iter2);
1252 EXPECT_TRUE(iter < iter2);
1253 EXPECT_TRUE(iter <= iter2);
1254 EXPECT_TRUE(iter <= iter);
1255 EXPECT_TRUE(iter2 > iter);
1256 EXPECT_TRUE(iter2 >= iter);
1257 EXPECT_TRUE(iter >= iter);
1258}
1259
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001260TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstPtr) {
1261 RepeatedPtrField<string>::const_pointer_iterator iter =
1262 const_proto_array_->pointer_begin();
1263 RepeatedPtrField<string>::const_pointer_iterator iter2 = iter + 1;
1264 EXPECT_TRUE(iter == iter);
1265 EXPECT_TRUE(iter != iter2);
1266 EXPECT_TRUE(iter < iter2);
1267 EXPECT_TRUE(iter <= iter2);
1268 EXPECT_TRUE(iter <= iter);
1269 EXPECT_TRUE(iter2 > iter);
1270 EXPECT_TRUE(iter2 >= iter);
1271 EXPECT_TRUE(iter >= iter);
1272}
1273
kenton@google.comfccb1462009-12-18 02:11:36 +00001274// Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs.
1275// Dereferencing an uninitialized iterator crashes the process.
1276TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) {
1277 RepeatedPtrField<string>::pointer_iterator iter;
1278 EXPECT_TRUE(iter != proto_array_.pointer_begin());
1279 EXPECT_TRUE(iter != proto_array_.pointer_begin() + 1);
1280 EXPECT_TRUE(iter != proto_array_.pointer_begin() + 2);
1281 EXPECT_TRUE(iter != proto_array_.pointer_begin() + 3);
1282 EXPECT_TRUE(iter != proto_array_.pointer_end());
1283}
1284
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001285TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedConstPtrIterator) {
1286 RepeatedPtrField<string>::const_pointer_iterator iter;
1287 EXPECT_TRUE(iter != const_proto_array_->pointer_begin());
1288 EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 1);
1289 EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 2);
1290 EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 3);
1291 EXPECT_TRUE(iter != const_proto_array_->pointer_end());
1292}
kenton@google.comfccb1462009-12-18 02:11:36 +00001293
1294// This comparison functor is required by the tests for RepeatedPtrOverPtrs.
1295// They operate on strings and need to compare strings as strings in
1296// any stl algorithm, even though the iterator returns a pointer to a string
1297// - i.e. *iter has type string*.
1298struct StringLessThan {
1299 bool operator()(const string* z, const string& y) {
1300 return *z < y;
1301 }
jieluo@google.com4de8f552014-07-18 00:47:59 +00001302 bool operator()(const string* z, const string* y) const { return *z < *y; }
kenton@google.comfccb1462009-12-18 02:11:36 +00001303};
1304
1305TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) {
1306 proto_array_.Clear();
1307 proto_array_.Add()->assign("a");
1308 proto_array_.Add()->assign("c");
1309 proto_array_.Add()->assign("d");
1310 proto_array_.Add()->assign("n");
1311 proto_array_.Add()->assign("p");
1312 proto_array_.Add()->assign("x");
1313 proto_array_.Add()->assign("y");
1314
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001315 {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001316 string v = "f";
1317 RepeatedPtrField<string>::pointer_iterator it =
Jisi Liu885b6122015-02-28 14:51:22 -08001318 std::lower_bound(proto_array_.pointer_begin(),
1319 proto_array_.pointer_end(), &v, StringLessThan());
kenton@google.comfccb1462009-12-18 02:11:36 +00001320
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001321 GOOGLE_CHECK(*it != NULL);
kenton@google.comfccb1462009-12-18 02:11:36 +00001322
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001323 EXPECT_EQ(**it, "n");
1324 EXPECT_TRUE(it == proto_array_.pointer_begin() + 3);
1325 }
1326 {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001327 string v = "f";
Jisi Liu885b6122015-02-28 14:51:22 -08001328 RepeatedPtrField<string>::const_pointer_iterator it = std::lower_bound(
1329 const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(),
1330 &v, StringLessThan());
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001331
1332 GOOGLE_CHECK(*it != NULL);
1333
1334 EXPECT_EQ(**it, "n");
1335 EXPECT_TRUE(it == const_proto_array_->pointer_begin() + 3);
1336 }
kenton@google.comfccb1462009-12-18 02:11:36 +00001337}
1338
1339TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) {
1340 RepeatedPtrField<string>::pointer_iterator iter =
1341 proto_array_.pointer_begin();
1342 **iter = "qux";
1343 EXPECT_EQ("qux", proto_array_.Get(0));
1344
1345 EXPECT_EQ("bar", proto_array_.Get(1));
1346 EXPECT_EQ("baz", proto_array_.Get(2));
1347 ++iter;
1348 delete *iter;
1349 *iter = new string("a");
1350 ++iter;
1351 delete *iter;
1352 *iter = new string("b");
1353 EXPECT_EQ("a", proto_array_.Get(1));
1354 EXPECT_EQ("b", proto_array_.Get(2));
1355}
1356
1357TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) {
1358 proto_array_.Add()->assign("c");
1359 proto_array_.Add()->assign("d");
1360 proto_array_.Add()->assign("n");
1361 proto_array_.Add()->assign("p");
1362 proto_array_.Add()->assign("a");
1363 proto_array_.Add()->assign("y");
1364 proto_array_.Add()->assign("x");
1365 EXPECT_EQ("foo", proto_array_.Get(0));
1366 EXPECT_EQ("n", proto_array_.Get(5));
1367 EXPECT_EQ("x", proto_array_.Get(9));
Jisi Liu885b6122015-02-28 14:51:22 -08001368 std::sort(proto_array_.pointer_begin(), proto_array_.pointer_end(),
1369 StringLessThan());
kenton@google.comfccb1462009-12-18 02:11:36 +00001370 EXPECT_EQ("a", proto_array_.Get(0));
1371 EXPECT_EQ("baz", proto_array_.Get(2));
1372 EXPECT_EQ("y", proto_array_.Get(9));
1373}
1374
1375
kenton@google.comd37d46d2009-04-25 02:53:47 +00001376// -----------------------------------------------------------------------------
1377// Unit-tests for the insert iterators
1378// google::protobuf::RepeatedFieldBackInserter,
1379// google::protobuf::AllocatedRepeatedPtrFieldBackInserter
1380// Ported from util/gtl/proto-array-iterators_unittest.
1381
1382class RepeatedFieldInsertionIteratorsTest : public testing::Test {
1383 protected:
1384 std::list<double> halves;
1385 std::list<int> fibonacci;
1386 std::vector<string> words;
1387 typedef TestAllTypes::NestedMessage Nested;
1388 Nested nesteds[2];
1389 std::vector<Nested*> nested_ptrs;
1390 TestAllTypes protobuffer;
1391
1392 virtual void SetUp() {
1393 fibonacci.push_back(1);
1394 fibonacci.push_back(1);
1395 fibonacci.push_back(2);
1396 fibonacci.push_back(3);
1397 fibonacci.push_back(5);
1398 fibonacci.push_back(8);
1399 std::copy(fibonacci.begin(), fibonacci.end(),
1400 RepeatedFieldBackInserter(protobuffer.mutable_repeated_int32()));
1401
1402 halves.push_back(1.0);
1403 halves.push_back(0.5);
1404 halves.push_back(0.25);
1405 halves.push_back(0.125);
1406 halves.push_back(0.0625);
1407 std::copy(halves.begin(), halves.end(),
1408 RepeatedFieldBackInserter(protobuffer.mutable_repeated_double()));
1409
1410 words.push_back("Able");
1411 words.push_back("was");
1412 words.push_back("I");
1413 words.push_back("ere");
1414 words.push_back("I");
1415 words.push_back("saw");
1416 words.push_back("Elba");
1417 std::copy(words.begin(), words.end(),
1418 RepeatedFieldBackInserter(protobuffer.mutable_repeated_string()));
1419
1420 nesteds[0].set_bb(17);
1421 nesteds[1].set_bb(4711);
1422 std::copy(&nesteds[0], &nesteds[2],
1423 RepeatedFieldBackInserter(
1424 protobuffer.mutable_repeated_nested_message()));
1425
1426 nested_ptrs.push_back(new Nested);
1427 nested_ptrs.back()->set_bb(170);
1428 nested_ptrs.push_back(new Nested);
1429 nested_ptrs.back()->set_bb(47110);
1430 std::copy(nested_ptrs.begin(), nested_ptrs.end(),
1431 RepeatedFieldBackInserter(
1432 protobuffer.mutable_repeated_nested_message()));
kenton@google.comd37d46d2009-04-25 02:53:47 +00001433 }
1434
1435 virtual void TearDown() {
1436 STLDeleteContainerPointers(nested_ptrs.begin(), nested_ptrs.end());
1437 }
1438};
1439
1440TEST_F(RepeatedFieldInsertionIteratorsTest, Fibonacci) {
1441 EXPECT_TRUE(std::equal(fibonacci.begin(),
1442 fibonacci.end(),
1443 protobuffer.repeated_int32().begin()));
1444 EXPECT_TRUE(std::equal(protobuffer.repeated_int32().begin(),
1445 protobuffer.repeated_int32().end(),
1446 fibonacci.begin()));
1447}
1448
1449TEST_F(RepeatedFieldInsertionIteratorsTest, Halves) {
1450 EXPECT_TRUE(std::equal(halves.begin(),
1451 halves.end(),
1452 protobuffer.repeated_double().begin()));
1453 EXPECT_TRUE(std::equal(protobuffer.repeated_double().begin(),
1454 protobuffer.repeated_double().end(),
1455 halves.begin()));
1456}
1457
1458TEST_F(RepeatedFieldInsertionIteratorsTest, Words) {
1459 ASSERT_EQ(words.size(), protobuffer.repeated_string_size());
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001460 for (int i = 0; i < words.size(); ++i)
1461 EXPECT_EQ(words.at(i), protobuffer.repeated_string(i));
1462}
1463
1464TEST_F(RepeatedFieldInsertionIteratorsTest, Words2) {
1465 words.clear();
1466 words.push_back("sing");
1467 words.push_back("a");
1468 words.push_back("song");
1469 words.push_back("of");
1470 words.push_back("six");
1471 words.push_back("pence");
1472 protobuffer.mutable_repeated_string()->Clear();
1473 std::copy(words.begin(), words.end(), RepeatedPtrFieldBackInserter(
1474 protobuffer.mutable_repeated_string()));
1475 ASSERT_EQ(words.size(), protobuffer.repeated_string_size());
1476 for (int i = 0; i < words.size(); ++i)
1477 EXPECT_EQ(words.at(i), protobuffer.repeated_string(i));
kenton@google.comd37d46d2009-04-25 02:53:47 +00001478}
1479
1480TEST_F(RepeatedFieldInsertionIteratorsTest, Nesteds) {
1481 ASSERT_EQ(protobuffer.repeated_nested_message_size(), 4);
1482 EXPECT_EQ(protobuffer.repeated_nested_message(0).bb(), 17);
1483 EXPECT_EQ(protobuffer.repeated_nested_message(1).bb(), 4711);
1484 EXPECT_EQ(protobuffer.repeated_nested_message(2).bb(), 170);
1485 EXPECT_EQ(protobuffer.repeated_nested_message(3).bb(), 47110);
1486}
1487
1488TEST_F(RepeatedFieldInsertionIteratorsTest,
1489 AllocatedRepeatedPtrFieldWithStringIntData) {
1490 vector<Nested*> data;
1491 TestAllTypes goldenproto;
1492 for (int i = 0; i < 10; ++i) {
1493 Nested* new_data = new Nested;
1494 new_data->set_bb(i);
1495 data.push_back(new_data);
1496
1497 new_data = goldenproto.add_repeated_nested_message();
1498 new_data->set_bb(i);
1499 }
1500 TestAllTypes testproto;
Jisi Liu885b6122015-02-28 14:51:22 -08001501 std::copy(data.begin(), data.end(),
1502 AllocatedRepeatedPtrFieldBackInserter(
1503 testproto.mutable_repeated_nested_message()));
kenton@google.comd37d46d2009-04-25 02:53:47 +00001504 EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
1505}
1506
1507TEST_F(RepeatedFieldInsertionIteratorsTest,
1508 AllocatedRepeatedPtrFieldWithString) {
1509 vector<string*> data;
1510 TestAllTypes goldenproto;
1511 for (int i = 0; i < 10; ++i) {
1512 string* new_data = new string;
1513 *new_data = "name-" + SimpleItoa(i);
1514 data.push_back(new_data);
1515
1516 new_data = goldenproto.add_repeated_string();
1517 *new_data = "name-" + SimpleItoa(i);
1518 }
1519 TestAllTypes testproto;
Jisi Liu885b6122015-02-28 14:51:22 -08001520 std::copy(data.begin(), data.end(), AllocatedRepeatedPtrFieldBackInserter(
1521 testproto.mutable_repeated_string()));
kenton@google.comd37d46d2009-04-25 02:53:47 +00001522 EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
1523}
1524
Jisi Liu3b3c8ab2016-03-30 11:39:59 -07001525TEST_F(RepeatedFieldInsertionIteratorsTest,
1526 UnsafeArenaAllocatedRepeatedPtrFieldWithStringIntData) {
1527 vector<Nested*> data;
1528 TestAllTypes goldenproto;
1529 for (int i = 0; i < 10; ++i) {
1530 Nested* new_data = new Nested;
1531 new_data->set_bb(i);
1532 data.push_back(new_data);
1533
1534 new_data = goldenproto.add_repeated_nested_message();
1535 new_data->set_bb(i);
1536 }
1537 TestAllTypes testproto;
1538 std::copy(data.begin(), data.end(),
1539 UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
1540 testproto.mutable_repeated_nested_message()));
1541 EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
1542}
1543
1544TEST_F(RepeatedFieldInsertionIteratorsTest,
1545 UnsafeArenaAllocatedRepeatedPtrFieldWithString) {
1546 vector<string*> data;
1547 TestAllTypes goldenproto;
1548 for (int i = 0; i < 10; ++i) {
1549 string* new_data = new string;
1550 *new_data = "name-" + SimpleItoa(i);
1551 data.push_back(new_data);
1552
1553 new_data = goldenproto.add_repeated_string();
1554 *new_data = "name-" + SimpleItoa(i);
1555 }
1556 TestAllTypes testproto;
1557 std::copy(data.begin(), data.end(),
1558 UnsafeArenaAllocatedRepeatedPtrFieldBackInserter(
1559 testproto.mutable_repeated_string()));
1560 EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
1561}
1562
kenton@google.comd37d46d2009-04-25 02:53:47 +00001563} // namespace
1564
temporal40ee5512008-07-10 02:12:20 +00001565} // namespace protobuf
1566} // namespace google