1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
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 #include <google/protobuf/arena.h>
32
33 #include <algorithm>
34 #include <cstring>
35 #include <memory>
36 #ifndef _SHARED_PTR_H
37 #include <google/protobuf/stubs/shared_ptr.h>
38 #endif
39 #include <string>
40 #include <typeinfo>
41 #include <vector>
42
43 #include <google/protobuf/stubs/logging.h>
44 #include <google/protobuf/stubs/common.h>
45 #include <google/protobuf/arena_test_util.h>
46 #include <google/protobuf/test_util.h>
47 #include <google/protobuf/unittest.pb.h>
48 #include <google/protobuf/unittest_arena.pb.h>
49 #include <google/protobuf/unittest_no_arena.pb.h>
50 #include <google/protobuf/io/coded_stream.h>
51 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
52 #include <google/protobuf/descriptor.h>
53 #include <google/protobuf/extension_set.h>
54 #include <google/protobuf/message.h>
55 #include <google/protobuf/message_lite.h>
56 #include <google/protobuf/repeated_field.h>
57 #include <google/protobuf/wire_format_lite.h>
58 #include <google/protobuf/unknown_field_set.h>
59 #include <gtest/gtest.h>
60
61
62 namespace google {
63 using proto2_arena_unittest::ArenaMessage;
64 using protobuf_unittest::TestAllTypes;
65 using protobuf_unittest::TestAllExtensions;
66 using protobuf_unittest::TestOneof2;
67 using protobuf_unittest::TestEmptyMessage;
68
69 namespace protobuf {
70 namespace {
71
72 class Notifier {
73 public:
Notifier()74 Notifier() : count_(0) {}
Notify()75 void Notify() {
76 count_++;
77 }
GetCount()78 int GetCount() {
79 return count_;
80 }
81
82 private:
83 int count_;
84 };
85
86 class SimpleDataType {
87 public:
SimpleDataType()88 SimpleDataType() : notifier_(NULL) {}
SetNotifier(Notifier * notifier)89 void SetNotifier(Notifier* notifier) {
90 notifier_ = notifier;
91 }
~SimpleDataType()92 virtual ~SimpleDataType() {
93 if (notifier_ != NULL) {
94 notifier_->Notify();
95 }
96 };
97 private:
98 Notifier* notifier_;
99 };
100
101 // A simple class that does not allow copying and so cannot be used as a
102 // parameter type without "const &".
103 class PleaseDontCopyMe {
104 public:
PleaseDontCopyMe(int value)105 explicit PleaseDontCopyMe(int value) : value_(value) {}
106
value() const107 int value() const { return value_; }
108
109 private:
110 int value_;
111 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PleaseDontCopyMe);
112 };
113
114 // A class that takes four different types as constructor arguments.
115 class MustBeConstructedWithOneThroughFour {
116 public:
MustBeConstructedWithOneThroughFour(int one,const char * two,const string & three,const PleaseDontCopyMe * four)117 MustBeConstructedWithOneThroughFour(
118 int one, const char* two, const string& three,
119 const PleaseDontCopyMe* four)
120 : one_(one), two_(two), three_(three), four_(four) {}
121
122 int one_;
123 const char* const two_;
124 string three_;
125 const PleaseDontCopyMe* four_;
126
127 private:
128 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughFour);
129 };
130
131 // A class that takes eight different types as constructor arguments.
132 class MustBeConstructedWithOneThroughEight {
133 public:
MustBeConstructedWithOneThroughEight(int one,const char * two,const string & three,const PleaseDontCopyMe * four,int five,const char * six,const string & seven,const string & eight)134 MustBeConstructedWithOneThroughEight(
135 int one, const char* two, const string& three,
136 const PleaseDontCopyMe* four, int five, const char* six,
137 const string& seven, const string& eight)
138 : one_(one), two_(two), three_(three), four_(four), five_(five),
139 six_(six), seven_(seven), eight_(eight) {}
140
141 int one_;
142 const char* const two_;
143 string three_;
144 const PleaseDontCopyMe* four_;
145 int five_;
146 const char* const six_;
147 string seven_;
148 string eight_;
149
150 private:
151 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughEight);
152 };
153
154 } // namespace
155
TEST(ArenaTest,ArenaConstructable)156 TEST(ArenaTest, ArenaConstructable) {
157 EXPECT_TRUE(Arena::is_arena_constructable<TestAllTypes>::type::value);
158 EXPECT_TRUE(Arena::is_arena_constructable<const TestAllTypes>::type::value);
159 EXPECT_FALSE(Arena::is_arena_constructable<Arena>::type::value);
160 }
161
TEST(ArenaTest,BasicCreate)162 TEST(ArenaTest, BasicCreate) {
163 Arena arena;
164 EXPECT_TRUE(Arena::Create<int32>(&arena) != NULL);
165 EXPECT_TRUE(Arena::Create<int64>(&arena) != NULL);
166 EXPECT_TRUE(Arena::Create<float>(&arena) != NULL);
167 EXPECT_TRUE(Arena::Create<double>(&arena) != NULL);
168 EXPECT_TRUE(Arena::Create<string>(&arena) != NULL);
169 arena.Own(new int32);
170 arena.Own(new int64);
171 arena.Own(new float);
172 arena.Own(new double);
173 arena.Own(new string);
174 arena.Own<int>(NULL);
175 Notifier notifier;
176 SimpleDataType* data = Arena::Create<SimpleDataType>(&arena);
177 data->SetNotifier(¬ifier);
178 data = new SimpleDataType;
179 data->SetNotifier(¬ifier);
180 arena.Own(data);
181 arena.Reset();
182 EXPECT_EQ(2, notifier.GetCount());
183 }
184
TEST(ArenaTest,CreateWithFourConstructorArguments)185 TEST(ArenaTest, CreateWithFourConstructorArguments) {
186 Arena arena;
187 const string three("3");
188 const PleaseDontCopyMe four(4);
189 const MustBeConstructedWithOneThroughFour* new_object =
190 Arena::Create<MustBeConstructedWithOneThroughFour>(
191 &arena, 1, "2", three, &four);
192 EXPECT_TRUE(new_object != NULL);
193 ASSERT_EQ(1, new_object->one_);
194 ASSERT_STREQ("2", new_object->two_);
195 ASSERT_EQ("3", new_object->three_);
196 ASSERT_EQ(4, new_object->four_->value());
197 }
198
TEST(ArenaTest,CreateWithEightConstructorArguments)199 TEST(ArenaTest, CreateWithEightConstructorArguments) {
200 Arena arena;
201 const string three("3");
202 const PleaseDontCopyMe four(4);
203 const string seven("7");
204 const string eight("8");
205 const MustBeConstructedWithOneThroughEight* new_object =
206 Arena::Create<MustBeConstructedWithOneThroughEight>(
207 &arena, 1, "2", three, &four, 5, "6", seven, eight);
208 EXPECT_TRUE(new_object != NULL);
209 ASSERT_EQ(1, new_object->one_);
210 ASSERT_STREQ("2", new_object->two_);
211 ASSERT_EQ("3", new_object->three_);
212 ASSERT_EQ(4, new_object->four_->value());
213 ASSERT_EQ(5, new_object->five_);
214 ASSERT_STREQ("6", new_object->six_);
215 ASSERT_EQ("7", new_object->seven_);
216 ASSERT_EQ("8", new_object->eight_);
217 }
218
TEST(ArenaTest,InitialBlockTooSmall)219 TEST(ArenaTest, InitialBlockTooSmall) {
220 // Construct a small (64 byte) initial block of memory to be used by the
221 // arena allocator; then, allocate an object which will not fit in the
222 // initial block.
223 std::vector<char> arena_block(64);
224 ArenaOptions options;
225 options.initial_block = &arena_block[0];
226 options.initial_block_size = arena_block.size();
227 Arena arena(options);
228
229 char* p = ::google::protobuf::Arena::CreateArray<char>(&arena, 96);
230 uintptr_t allocation = reinterpret_cast<uintptr_t>(p);
231
232 // Ensure that the arena allocator did not return memory pointing into the
233 // initial block of memory.
234 uintptr_t arena_start = reinterpret_cast<uintptr_t>(&arena_block[0]);
235 uintptr_t arena_end = arena_start + arena_block.size();
236 EXPECT_FALSE(allocation >= arena_start && allocation < arena_end);
237
238 // Write to the memory we allocated; this should (but is not guaranteed to)
239 // trigger a check for heap corruption if the object was allocated from the
240 // initially-provided block.
241 memset(p, '\0', 96);
242 }
243
TEST(ArenaTest,Parsing)244 TEST(ArenaTest, Parsing) {
245 TestAllTypes original;
246 TestUtil::SetAllFields(&original);
247
248 // Test memory leak.
249 Arena arena;
250 TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
251 arena_message->ParseFromString(original.SerializeAsString());
252 TestUtil::ExpectAllFieldsSet(*arena_message);
253
254 // Test that string fields have null terminator bytes (earlier bug).
255 EXPECT_EQ(strlen(original.optional_string().c_str()),
256 strlen(arena_message->optional_string().c_str()));
257 }
258
TEST(ArenaTest,UnknownFields)259 TEST(ArenaTest, UnknownFields) {
260 TestAllTypes original;
261 TestUtil::SetAllFields(&original);
262
263 // Test basic parsing into (populating) and reading out of unknown fields on
264 // an arena.
265 Arena arena;
266 TestEmptyMessage* arena_message =
267 Arena::CreateMessage<TestEmptyMessage>(&arena);
268 arena_message->ParseFromString(original.SerializeAsString());
269
270 TestAllTypes copied;
271 copied.ParseFromString(arena_message->SerializeAsString());
272 TestUtil::ExpectAllFieldsSet(copied);
273
274 // Exercise UFS manual manipulation (setters).
275 arena_message = Arena::CreateMessage<TestEmptyMessage>(&arena);
276 arena_message->mutable_unknown_fields()->AddVarint(
277 TestAllTypes::kOptionalInt32FieldNumber, 42);
278 copied.Clear();
279 copied.ParseFromString(arena_message->SerializeAsString());
280 EXPECT_TRUE(copied.has_optional_int32());
281 EXPECT_EQ(42, copied.optional_int32());
282
283 // Exercise UFS swap path.
284 TestEmptyMessage* arena_message_2 =
285 Arena::CreateMessage<TestEmptyMessage>(&arena);
286 arena_message_2->Swap(arena_message);
287 copied.Clear();
288 copied.ParseFromString(arena_message_2->SerializeAsString());
289 EXPECT_TRUE(copied.has_optional_int32());
290 EXPECT_EQ(42, copied.optional_int32());
291
292 // Test field manipulation.
293 TestEmptyMessage* arena_message_3 =
294 Arena::CreateMessage<TestEmptyMessage>(&arena);
295 arena_message_3->mutable_unknown_fields()->AddVarint(1000, 42);
296 arena_message_3->mutable_unknown_fields()->AddFixed32(1001, 42);
297 arena_message_3->mutable_unknown_fields()->AddFixed64(1002, 42);
298 arena_message_3->mutable_unknown_fields()->AddLengthDelimited(1003);
299 arena_message_3->mutable_unknown_fields()->DeleteSubrange(0, 2);
300 arena_message_3->mutable_unknown_fields()->DeleteByNumber(1002);
301 arena_message_3->mutable_unknown_fields()->DeleteByNumber(1003);
302 EXPECT_TRUE(arena_message_3->unknown_fields().empty());
303 }
304
TEST(ArenaTest,Swap)305 TEST(ArenaTest, Swap) {
306 Arena arena1;
307 Arena arena2;
308 TestAllTypes* arena1_message;
309 TestAllTypes* arena2_message;
310
311 // Case 1: Swap(), no UFS on either message, both messages on different
312 // arenas. Arena pointers should remain the same after swap.
313 arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
314 arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
315 arena1_message->Swap(arena2_message);
316 EXPECT_EQ(&arena1, arena1_message->GetArena());
317 EXPECT_EQ(&arena2, arena2_message->GetArena());
318
319 // Case 2: Swap(), UFS on one message, both messages on different arenas.
320 arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
321 arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
322 arena1_message->mutable_unknown_fields()->AddVarint(1, 42);
323 arena1_message->Swap(arena2_message);
324 EXPECT_EQ(&arena1, arena1_message->GetArena());
325 EXPECT_EQ(&arena2, arena2_message->GetArena());
326 EXPECT_EQ(0, arena1_message->unknown_fields().field_count());
327 EXPECT_EQ(1, arena2_message->unknown_fields().field_count());
328 EXPECT_EQ(42, arena2_message->unknown_fields().field(0).varint());
329
330 // Case 3: Swap(), UFS on both messages, both messages on different arenas.
331 arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
332 arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
333 arena1_message->mutable_unknown_fields()->AddVarint(1, 42);
334 arena2_message->mutable_unknown_fields()->AddVarint(2, 84);
335 arena1_message->Swap(arena2_message);
336 EXPECT_EQ(&arena1, arena1_message->GetArena());
337 EXPECT_EQ(&arena2, arena2_message->GetArena());
338 EXPECT_EQ(1, arena1_message->unknown_fields().field_count());
339 EXPECT_EQ(1, arena2_message->unknown_fields().field_count());
340 EXPECT_EQ(84, arena1_message->unknown_fields().field(0).varint());
341 EXPECT_EQ(42, arena2_message->unknown_fields().field(0).varint());
342 }
343
TEST(ArenaTest,ReflectionSwapFields)344 TEST(ArenaTest, ReflectionSwapFields) {
345 Arena arena1;
346 Arena arena2;
347 TestAllTypes* arena1_message;
348 TestAllTypes* arena2_message;
349
350 // Case 1: messages on different arenas, only one message is set.
351 arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
352 arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
353 TestUtil::SetAllFields(arena1_message);
354 const Reflection* reflection = arena1_message->GetReflection();
355 std::vector<const FieldDescriptor*> fields;
356 reflection->ListFields(*arena1_message, &fields);
357 reflection->SwapFields(arena1_message, arena2_message, fields);
358 EXPECT_EQ(&arena1, arena1_message->GetArena());
359 EXPECT_EQ(&arena2, arena2_message->GetArena());
360 string output;
361 arena1_message->SerializeToString(&output);
362 EXPECT_EQ(0, output.size());
363 TestUtil::ExpectAllFieldsSet(*arena2_message);
364 reflection->SwapFields(arena1_message, arena2_message, fields);
365 arena2_message->SerializeToString(&output);
366 EXPECT_EQ(0, output.size());
367 TestUtil::ExpectAllFieldsSet(*arena1_message);
368
369 // Case 2: messages on different arenas, both messages are set.
370 arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
371 arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
372 TestUtil::SetAllFields(arena1_message);
373 TestUtil::SetAllFields(arena2_message);
374 reflection->SwapFields(arena1_message, arena2_message, fields);
375 EXPECT_EQ(&arena1, arena1_message->GetArena());
376 EXPECT_EQ(&arena2, arena2_message->GetArena());
377 TestUtil::ExpectAllFieldsSet(*arena1_message);
378 TestUtil::ExpectAllFieldsSet(*arena2_message);
379
380 // Case 3: messages on different arenas with different lifetimes.
381 arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
382 {
383 Arena arena3;
384 TestAllTypes* arena3_message = Arena::CreateMessage<TestAllTypes>(&arena3);
385 TestUtil::SetAllFields(arena3_message);
386 reflection->SwapFields(arena1_message, arena3_message, fields);
387 }
388 TestUtil::ExpectAllFieldsSet(*arena1_message);
389
390 // Case 4: one message on arena, the other on heap.
391 arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
392 TestAllTypes message;
393 TestUtil::SetAllFields(arena1_message);
394 reflection->SwapFields(arena1_message, &message, fields);
395 EXPECT_EQ(&arena1, arena1_message->GetArena());
396 EXPECT_EQ(NULL, message.GetArena());
397 arena1_message->SerializeToString(&output);
398 EXPECT_EQ(0, output.size());
399 TestUtil::ExpectAllFieldsSet(message);
400 }
401
TEST(ArenaTest,SetAllocatedMessage)402 TEST(ArenaTest, SetAllocatedMessage) {
403 Arena arena;
404 TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
405 TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage;
406 nested->set_bb(118);
407 arena_message->set_allocated_optional_nested_message(nested);
408 EXPECT_EQ(118, arena_message->optional_nested_message().bb());
409
410 protobuf_unittest_no_arena::TestNoArenaMessage no_arena_message;
411 EXPECT_FALSE(no_arena_message.has_arena_message());
412 no_arena_message.set_allocated_arena_message(NULL);
413 EXPECT_FALSE(no_arena_message.has_arena_message());
414 no_arena_message.set_allocated_arena_message(new ArenaMessage);
415 EXPECT_TRUE(no_arena_message.has_arena_message());
416 }
417
TEST(ArenaTest,ReleaseMessage)418 TEST(ArenaTest, ReleaseMessage) {
419 Arena arena;
420 TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
421 arena_message->mutable_optional_nested_message()->set_bb(118);
422 google::protobuf::scoped_ptr<TestAllTypes::NestedMessage> nested(
423 arena_message->release_optional_nested_message());
424 EXPECT_EQ(118, nested->bb());
425
426 TestAllTypes::NestedMessage* released_null =
427 arena_message->release_optional_nested_message();
428 EXPECT_EQ(NULL, released_null);
429 }
430
TEST(ArenaTest,SetAllocatedString)431 TEST(ArenaTest, SetAllocatedString) {
432 Arena arena;
433 TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
434 string* allocated_str = new string("hello");
435 arena_message->set_allocated_optional_string(allocated_str);
436 EXPECT_EQ("hello", arena_message->optional_string());
437 }
438
TEST(ArenaTest,ReleaseString)439 TEST(ArenaTest, ReleaseString) {
440 Arena arena;
441 TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
442 arena_message->set_optional_string("hello");
443 google::protobuf::scoped_ptr<string> released_str(
444 arena_message->release_optional_string());
445 EXPECT_EQ("hello", *released_str);
446
447 // Test default value.
448 }
449
450
TEST(ArenaTest,SwapBetweenArenasWithAllFieldsSet)451 TEST(ArenaTest, SwapBetweenArenasWithAllFieldsSet) {
452 Arena arena1;
453 TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
454 {
455 Arena arena2;
456 TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
457 TestUtil::SetAllFields(arena2_message);
458 arena2_message->Swap(arena1_message);
459 string output;
460 arena2_message->SerializeToString(&output);
461 EXPECT_EQ(0, output.size());
462 }
463 TestUtil::ExpectAllFieldsSet(*arena1_message);
464 }
465
TEST(ArenaTest,SwapBetweenArenaAndNonArenaWithAllFieldsSet)466 TEST(ArenaTest, SwapBetweenArenaAndNonArenaWithAllFieldsSet) {
467 TestAllTypes non_arena_message;
468 TestUtil::SetAllFields(&non_arena_message);
469 {
470 Arena arena2;
471 TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
472 TestUtil::SetAllFields(arena2_message);
473 arena2_message->Swap(&non_arena_message);
474 TestUtil::ExpectAllFieldsSet(*arena2_message);
475 TestUtil::ExpectAllFieldsSet(non_arena_message);
476 }
477 }
478
TEST(ArenaTest,UnsafeArenaSwap)479 TEST(ArenaTest, UnsafeArenaSwap) {
480 Arena shared_arena;
481 TestAllTypes* message1 = Arena::CreateMessage<TestAllTypes>(&shared_arena);
482 TestAllTypes* message2 = Arena::CreateMessage<TestAllTypes>(&shared_arena);
483 TestUtil::SetAllFields(message1);
484 message1->UnsafeArenaSwap(message2);
485 TestUtil::ExpectAllFieldsSet(*message2);
486 }
487
TEST(ArenaTest,SwapBetweenArenasUsingReflection)488 TEST(ArenaTest, SwapBetweenArenasUsingReflection) {
489 Arena arena1;
490 TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
491 {
492 Arena arena2;
493 TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
494 TestUtil::SetAllFields(arena2_message);
495 const Reflection* r = arena2_message->GetReflection();
496 r->Swap(arena1_message, arena2_message);
497 string output;
498 arena2_message->SerializeToString(&output);
499 EXPECT_EQ(0, output.size());
500 }
501 TestUtil::ExpectAllFieldsSet(*arena1_message);
502 }
503
TEST(ArenaTest,SwapBetweenArenaAndNonArenaUsingReflection)504 TEST(ArenaTest, SwapBetweenArenaAndNonArenaUsingReflection) {
505 TestAllTypes non_arena_message;
506 TestUtil::SetAllFields(&non_arena_message);
507 {
508 Arena arena2;
509 TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
510 TestUtil::SetAllFields(arena2_message);
511 const Reflection* r = arena2_message->GetReflection();
512 r->Swap(&non_arena_message, arena2_message);
513 TestUtil::ExpectAllFieldsSet(*arena2_message);
514 TestUtil::ExpectAllFieldsSet(non_arena_message);
515 }
516 }
517
TEST(ArenaTest,ReleaseFromArenaMessageMakesCopy)518 TEST(ArenaTest, ReleaseFromArenaMessageMakesCopy) {
519 TestAllTypes::NestedMessage* nested_msg = NULL;
520 string* nested_string = NULL;
521 {
522 Arena arena;
523 TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
524 arena_message->mutable_optional_nested_message()->set_bb(42);
525 *arena_message->mutable_optional_string() = "Hello";
526 nested_msg = arena_message->release_optional_nested_message();
527 nested_string = arena_message->release_optional_string();
528 }
529 EXPECT_EQ(42, nested_msg->bb());
530 EXPECT_EQ("Hello", *nested_string);
531 delete nested_msg;
532 delete nested_string;
533 }
534
535 #ifndef GOOGLE_PROTOBUF_NO_RTTI
TEST(ArenaTest,ReleaseFromArenaMessageUsingReflectionMakesCopy)536 TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) {
537 TestAllTypes::NestedMessage* nested_msg = NULL;
538 // Note: no string: reflection API only supports releasing submessages.
539 {
540 Arena arena;
541 TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
542 arena_message->mutable_optional_nested_message()->set_bb(42);
543 const Reflection* r = arena_message->GetReflection();
544 const FieldDescriptor* f = arena_message->GetDescriptor()->FindFieldByName(
545 "optional_nested_message");
546 nested_msg = static_cast<TestAllTypes::NestedMessage*>(
547 r->ReleaseMessage(arena_message, f));
548 }
549 EXPECT_EQ(42, nested_msg->bb());
550 delete nested_msg;
551 }
552 #endif // !GOOGLE_PROTOBUF_NO_RTTI
553
TEST(ArenaTest,UnsafeArenaReleaseDoesNotMakeCopy)554 TEST(ArenaTest, UnsafeArenaReleaseDoesNotMakeCopy) {
555 Arena arena;
556 TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
557 TestAllTypes::NestedMessage* nested_msg = NULL;
558 TestAllTypes::NestedMessage* orig_nested_msg = NULL;
559 string* nested_string = NULL;
560 string* orig_nested_string = NULL;
561 arena_message->mutable_optional_nested_message()->set_bb(42);
562 *arena_message->mutable_optional_string() = "Hello";
563 orig_nested_msg = arena_message->mutable_optional_nested_message();
564 orig_nested_string = arena_message->mutable_optional_string();
565 nested_msg = arena_message->unsafe_arena_release_optional_nested_message();
566 nested_string = arena_message->unsafe_arena_release_optional_string();
567
568 EXPECT_EQ(orig_nested_msg, nested_msg);
569 EXPECT_EQ(orig_nested_string, nested_string);
570 // Released pointers still on arena; no 'delete' calls needed here.
571 }
572
TEST(ArenaTest,SetAllocatedAcrossArenas)573 TEST(ArenaTest, SetAllocatedAcrossArenas) {
574 Arena arena1;
575 TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
576 TestAllTypes::NestedMessage* heap_submessage =
577 new TestAllTypes::NestedMessage();
578 heap_submessage->set_bb(42);
579 arena1_message->set_allocated_optional_nested_message(heap_submessage);
580 // Should keep same object and add to arena's Own()-list.
581 EXPECT_EQ(heap_submessage,
582 arena1_message->mutable_optional_nested_message());
583 {
584 Arena arena2;
585 TestAllTypes::NestedMessage* arena2_submessage =
586 Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
587 arena2_submessage->set_bb(42);
588 arena1_message->set_allocated_optional_nested_message(arena2_submessage);
589 EXPECT_NE(arena2_submessage,
590 arena1_message->mutable_optional_nested_message());
591 }
592
593 TestAllTypes::NestedMessage* arena1_submessage =
594 Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena1);
595 arena1_submessage->set_bb(42);
596 TestAllTypes* heap_message = new TestAllTypes;
597 heap_message->set_allocated_optional_nested_message(arena1_submessage);
598 EXPECT_NE(arena1_submessage,
599 heap_message->mutable_optional_nested_message());
600 delete heap_message;
601 }
602
TEST(ArenaTest,SetAllocatedAcrossArenasWithReflection)603 TEST(ArenaTest, SetAllocatedAcrossArenasWithReflection) {
604 // Same as above, with reflection.
605 Arena arena1;
606 TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
607 const Reflection* r = arena1_message->GetReflection();
608 const Descriptor* d = arena1_message->GetDescriptor();
609 const FieldDescriptor* msg_field = d->FindFieldByName(
610 "optional_nested_message");
611 TestAllTypes::NestedMessage* heap_submessage =
612 new TestAllTypes::NestedMessage();
613 heap_submessage->set_bb(42);
614 r->SetAllocatedMessage(arena1_message, heap_submessage, msg_field);
615 // Should keep same object and add to arena's Own()-list.
616 EXPECT_EQ(heap_submessage,
617 arena1_message->mutable_optional_nested_message());
618 {
619 Arena arena2;
620 TestAllTypes::NestedMessage* arena2_submessage =
621 Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
622 arena2_submessage->set_bb(42);
623 r->SetAllocatedMessage(arena1_message, arena2_submessage, msg_field);
624 EXPECT_NE(arena2_submessage,
625 arena1_message->mutable_optional_nested_message());
626 }
627
628 TestAllTypes::NestedMessage* arena1_submessage =
629 Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena1);
630 arena1_submessage->set_bb(42);
631 TestAllTypes* heap_message = new TestAllTypes;
632 r->SetAllocatedMessage(heap_message, arena1_submessage, msg_field);
633 EXPECT_NE(arena1_submessage,
634 heap_message->mutable_optional_nested_message());
635 delete heap_message;
636 }
637
TEST(ArenaTest,AddAllocatedWithReflection)638 TEST(ArenaTest, AddAllocatedWithReflection) {
639 Arena arena1;
640 ArenaMessage* arena1_message = Arena::CreateMessage<ArenaMessage>(&arena1);
641 const Reflection* r = arena1_message->GetReflection();
642 const Descriptor* d = arena1_message->GetDescriptor();
643 const FieldDescriptor* fd =
644 d->FindFieldByName("repeated_import_no_arena_message");
645 // Message with cc_enable_arenas = false;
646 r->AddMessage(arena1_message, fd);
647 r->AddMessage(arena1_message, fd);
648 r->AddMessage(arena1_message, fd);
649 EXPECT_EQ(3, r->FieldSize(*arena1_message, fd));
650 // Message with cc_enable_arenas = true;
651 fd = d->FindFieldByName("repeated_nested_message");
652 r->AddMessage(arena1_message, fd);
653 r->AddMessage(arena1_message, fd);
654 r->AddMessage(arena1_message, fd);
655 EXPECT_EQ(3, r->FieldSize(*arena1_message, fd));
656 }
657
TEST(ArenaTest,RepeatedPtrFieldAddClearedTest)658 TEST(ArenaTest, RepeatedPtrFieldAddClearedTest) {
659 {
660 RepeatedPtrField<TestAllTypes> repeated_field;
661 EXPECT_TRUE(repeated_field.empty());
662 EXPECT_EQ(0, repeated_field.size());
663 // Ownership is passed to repeated_field.
664 TestAllTypes* cleared = new TestAllTypes();
665 repeated_field.AddCleared(cleared);
666 EXPECT_TRUE(repeated_field.empty());
667 EXPECT_EQ(0, repeated_field.size());
668 }
669 {
670 RepeatedPtrField<TestAllTypes> repeated_field;
671 EXPECT_TRUE(repeated_field.empty());
672 EXPECT_EQ(0, repeated_field.size());
673 // Ownership is passed to repeated_field.
674 TestAllTypes* cleared = new TestAllTypes();
675 repeated_field.AddAllocated(cleared);
676 EXPECT_FALSE(repeated_field.empty());
677 EXPECT_EQ(1, repeated_field.size());
678 }
679 }
680
TEST(ArenaTest,AddAllocatedToRepeatedField)681 TEST(ArenaTest, AddAllocatedToRepeatedField) {
682 // Heap->arena case.
683 Arena arena1;
684 TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
685 for (int i = 0; i < 10; i++) {
686 TestAllTypes::NestedMessage* heap_submessage =
687 new TestAllTypes::NestedMessage();
688 heap_submessage->set_bb(42);
689 arena1_message->mutable_repeated_nested_message()->
690 AddAllocated(heap_submessage);
691 // Should not copy object -- will use arena_->Own().
692 EXPECT_EQ(heap_submessage,
693 &arena1_message->repeated_nested_message(i));
694 EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
695 }
696
697 // Arena1->Arena2 case.
698 arena1_message->Clear();
699 for (int i = 0; i < 10; i++) {
700 Arena arena2;
701 TestAllTypes::NestedMessage* arena2_submessage =
702 Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
703 arena2_submessage->set_bb(42);
704 arena1_message->mutable_repeated_nested_message()->
705 AddAllocated(arena2_submessage);
706 // Should copy object.
707 EXPECT_NE(arena2_submessage,
708 &arena1_message->repeated_nested_message(i));
709 EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
710 }
711
712 // Arena->heap case.
713 TestAllTypes* heap_message = new TestAllTypes();
714 for (int i = 0; i < 10; i++) {
715 Arena arena2;
716 TestAllTypes::NestedMessage* arena2_submessage =
717 Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
718 arena2_submessage->set_bb(42);
719 heap_message->mutable_repeated_nested_message()->
720 AddAllocated(arena2_submessage);
721 // Should copy object.
722 EXPECT_NE(arena2_submessage,
723 &heap_message->repeated_nested_message(i));
724 EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb());
725 }
726 delete heap_message;
727
728 // Heap-arena case for strings (which are not arena-allocated).
729 arena1_message->Clear();
730 for (int i = 0; i < 10; i++) {
731 string* s = new string("Test");
732 arena1_message->mutable_repeated_string()->
733 AddAllocated(s);
734 // Should not copy.
735 EXPECT_EQ(s, &arena1_message->repeated_string(i));
736 EXPECT_EQ("Test", arena1_message->repeated_string(i));
737 }
738 }
739
TEST(ArenaTest,AddAllocatedToRepeatedFieldViaReflection)740 TEST(ArenaTest, AddAllocatedToRepeatedFieldViaReflection) {
741 // Heap->arena case.
742 Arena arena1;
743 TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
744 const Reflection* r = arena1_message->GetReflection();
745 const Descriptor* d = arena1_message->GetDescriptor();
746 const FieldDescriptor* fd =
747 d->FindFieldByName("repeated_nested_message");
748 for (int i = 0; i < 10; i++) {
749 TestAllTypes::NestedMessage* heap_submessage =
750 new TestAllTypes::NestedMessage;
751 heap_submessage->set_bb(42);
752 r->AddAllocatedMessage(arena1_message, fd, heap_submessage);
753 // Should not copy object -- will use arena_->Own().
754 EXPECT_EQ(heap_submessage,
755 &arena1_message->repeated_nested_message(i));
756 EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
757 }
758
759 // Arena1->Arena2 case.
760 arena1_message->Clear();
761 for (int i = 0; i < 10; i++) {
762 Arena arena2;
763 TestAllTypes::NestedMessage* arena2_submessage =
764 Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
765 arena2_submessage->set_bb(42);
766 r->AddAllocatedMessage(arena1_message, fd, arena2_submessage);
767 // Should copy object.
768 EXPECT_NE(arena2_submessage,
769 &arena1_message->repeated_nested_message(i));
770 EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
771 }
772
773 // Arena->heap case.
774 TestAllTypes* heap_message = new TestAllTypes;
775 for (int i = 0; i < 10; i++) {
776 Arena arena2;
777 TestAllTypes::NestedMessage* arena2_submessage =
778 Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
779 arena2_submessage->set_bb(42);
780 r->AddAllocatedMessage(heap_message, fd, arena2_submessage);
781 // Should copy object.
782 EXPECT_NE(arena2_submessage,
783 &heap_message->repeated_nested_message(i));
784 EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb());
785 }
786 delete heap_message;
787 }
788
TEST(ArenaTest,ReleaseLastRepeatedField)789 TEST(ArenaTest, ReleaseLastRepeatedField) {
790 // Release from arena-allocated repeated field and ensure that returned object
791 // is heap-allocated.
792 Arena arena;
793 TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
794 for (int i = 0; i < 10; i++) {
795 TestAllTypes::NestedMessage* nested =
796 Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena);
797 nested->set_bb(42);
798 arena_message->mutable_repeated_nested_message()->AddAllocated(nested);
799 }
800
801 for (int i = 0; i < 10; i++) {
802 const TestAllTypes::NestedMessage *orig_submessage =
803 &arena_message->repeated_nested_message(10 - 1 - i); // last element
804 TestAllTypes::NestedMessage *released =
805 arena_message->mutable_repeated_nested_message()->ReleaseLast();
806 EXPECT_NE(released, orig_submessage);
807 EXPECT_EQ(42, released->bb());
808 delete released;
809 }
810
811 // Test UnsafeArenaReleaseLast().
812 for (int i = 0; i < 10; i++) {
813 TestAllTypes::NestedMessage* nested =
814 Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena);
815 nested->set_bb(42);
816 arena_message->mutable_repeated_nested_message()->AddAllocated(nested);
817 }
818
819 for (int i = 0; i < 10; i++) {
820 const TestAllTypes::NestedMessage *orig_submessage =
821 &arena_message->repeated_nested_message(10 - 1 - i); // last element
822 TestAllTypes::NestedMessage *released =
823 arena_message->mutable_repeated_nested_message()->
824 UnsafeArenaReleaseLast();
825 EXPECT_EQ(released, orig_submessage);
826 EXPECT_EQ(42, released->bb());
827 // no delete -- |released| is on the arena.
828 }
829
830 // Test string case as well. ReleaseLast() in this case must copy the string,
831 // even though it was originally heap-allocated and its pointer was simply
832 // appended to the repeated field's internal vector, because the string was
833 // placed on the arena's destructor list and cannot be removed from that list
834 // (so the arena permanently owns the original instance).
835 arena_message->Clear();
836 for (int i = 0; i < 10; i++) {
837 string* s = new string("Test");
838 arena_message->mutable_repeated_string()->AddAllocated(s);
839 }
840 for (int i = 0; i < 10; i++) {
841 const string* orig_element = &arena_message->repeated_string(10 - 1 - i);
842 string* released = arena_message->mutable_repeated_string()->ReleaseLast();
843 EXPECT_NE(released, orig_element);
844 EXPECT_EQ("Test", *released);
845 delete released;
846 }
847 }
848
TEST(ArenaTest,UnsafeArenaReleaseAdd)849 TEST(ArenaTest, UnsafeArenaReleaseAdd) {
850 // Use unsafe_arena_release() and unsafe_arena_set_allocated() to transfer an
851 // arena-allocated string from one message to another.
852 Arena arena;
853 TestAllTypes* message1 = Arena::CreateMessage<TestAllTypes>(&arena);
854 TestAllTypes* message2 = Arena::CreateMessage<TestAllTypes>(&arena);
855 string* arena_string = Arena::Create<string>(&arena);
856 *arena_string = "Test content";
857
858 message1->unsafe_arena_set_allocated_optional_string(arena_string);
859 EXPECT_EQ(arena_string, message1->mutable_optional_string());
860 message2->unsafe_arena_set_allocated_optional_string(
861 message1->unsafe_arena_release_optional_string());
862 EXPECT_EQ(arena_string, message2->mutable_optional_string());
863 }
864
TEST(ArenaTest,UnsafeArenaAddAllocated)865 TEST(ArenaTest, UnsafeArenaAddAllocated) {
866 Arena arena;
867 TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
868 for (int i = 0; i < 10; i++) {
869 string* arena_string = Arena::Create<string>(&arena);
870 message->mutable_repeated_string()->UnsafeArenaAddAllocated(arena_string);
871 EXPECT_EQ(arena_string, message->mutable_repeated_string(i));
872 }
873 }
874
TEST(ArenaTest,UnsafeArenaRelease)875 TEST(ArenaTest, UnsafeArenaRelease) {
876 Arena arena;
877 TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
878
879 string* s = new string("test string");
880 message->unsafe_arena_set_allocated_optional_string(s);
881 EXPECT_TRUE(message->has_optional_string());
882 EXPECT_EQ("test string", message->optional_string());
883 s = message->unsafe_arena_release_optional_string();
884 EXPECT_FALSE(message->has_optional_string());
885 delete s;
886
887 s = new string("test string");
888 message->unsafe_arena_set_allocated_oneof_string(s);
889 EXPECT_TRUE(message->has_oneof_string());
890 EXPECT_EQ("test string", message->oneof_string());
891 s = message->unsafe_arena_release_oneof_string();
892 EXPECT_FALSE(message->has_oneof_string());
893 delete s;
894 }
895
TEST(ArenaTest,ArenaOneofReflection)896 TEST(ArenaTest, ArenaOneofReflection) {
897 Arena arena;
898 TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
899 const Descriptor* desc = message->GetDescriptor();
900 const Reflection* refl = message->GetReflection();
901
902 const FieldDescriptor* string_field = desc->FindFieldByName(
903 "oneof_string");
904 const FieldDescriptor* msg_field = desc->FindFieldByName(
905 "oneof_nested_message");
906 const OneofDescriptor* oneof = desc->FindOneofByName(
907 "oneof_field");
908
909 refl->SetString(message, string_field, "Test value");
910 EXPECT_TRUE(refl->HasOneof(*message, oneof));
911 refl->ClearOneof(message, oneof);
912 EXPECT_FALSE(refl->HasOneof(*message, oneof));
913
914 Message* submsg = refl->MutableMessage(message, msg_field);
915 EXPECT_TRUE(refl->HasOneof(*message, oneof));
916 refl->ClearOneof(message, oneof);
917 EXPECT_FALSE(refl->HasOneof(*message, oneof));
918 refl->MutableMessage(message, msg_field);
919 EXPECT_TRUE(refl->HasOneof(*message, oneof));
920 submsg = refl->ReleaseMessage(message, msg_field);
921 EXPECT_FALSE(refl->HasOneof(*message, oneof));
922 EXPECT_TRUE(submsg->GetArena() == NULL);
923 delete submsg;
924 }
925
926 namespace {
TestSwapRepeatedField(Arena * arena1,Arena * arena2)927 void TestSwapRepeatedField(Arena* arena1, Arena* arena2) {
928 // Test "safe" (copying) semantics for direct Swap() on RepeatedPtrField
929 // between arenas.
930 RepeatedPtrField<TestAllTypes> field1(arena1);
931 RepeatedPtrField<TestAllTypes> field2(arena2);
932 for (int i = 0; i < 10; i++) {
933 TestAllTypes* t = Arena::CreateMessage<TestAllTypes>(arena1);
934 t->set_optional_string("field1");
935 t->set_optional_int32(i);
936 if (arena1 != NULL) {
937 field1.UnsafeArenaAddAllocated(t);
938 } else {
939 field1.AddAllocated(t);
940 }
941 }
942 for (int i = 0; i < 5; i++) {
943 TestAllTypes* t = Arena::CreateMessage<TestAllTypes>(arena2);
944 t->set_optional_string("field2");
945 t->set_optional_int32(i);
946 if (arena2 != NULL) {
947 field2.UnsafeArenaAddAllocated(t);
948 } else {
949 field2.AddAllocated(t);
950 }
951 }
952 field1.Swap(&field2);
953 EXPECT_EQ(5, field1.size());
954 EXPECT_EQ(10, field2.size());
955 EXPECT_TRUE(string("field1") == field2.Get(0).optional_string());
956 EXPECT_TRUE(string("field2") == field1.Get(0).optional_string());
957 // Ensure that fields retained their original order:
958 for (int i = 0; i < field1.size(); i++) {
959 EXPECT_EQ(i, field1.Get(i).optional_int32());
960 }
961 for (int i = 0; i < field2.size(); i++) {
962 EXPECT_EQ(i, field2.Get(i).optional_int32());
963 }
964 }
965 } // namespace
966
TEST(ArenaTest,SwapRepeatedField)967 TEST(ArenaTest, SwapRepeatedField) {
968 Arena arena;
969 TestSwapRepeatedField(&arena, &arena);
970 }
971
TEST(ArenaTest,SwapRepeatedFieldWithDifferentArenas)972 TEST(ArenaTest, SwapRepeatedFieldWithDifferentArenas) {
973 Arena arena1;
974 Arena arena2;
975 TestSwapRepeatedField(&arena1, &arena2);
976 }
977
TEST(ArenaTest,SwapRepeatedFieldWithNoArenaOnRightHandSide)978 TEST(ArenaTest, SwapRepeatedFieldWithNoArenaOnRightHandSide) {
979 Arena arena;
980 TestSwapRepeatedField(&arena, NULL);
981 }
982
TEST(ArenaTest,SwapRepeatedFieldWithNoArenaOnLeftHandSide)983 TEST(ArenaTest, SwapRepeatedFieldWithNoArenaOnLeftHandSide) {
984 Arena arena;
985 TestSwapRepeatedField(NULL, &arena);
986 }
987
TEST(ArenaTest,ExtensionsOnArena)988 TEST(ArenaTest, ExtensionsOnArena) {
989 Arena arena;
990 // Ensure no leaks.
991 TestAllExtensions* message_ext =
992 Arena::CreateMessage<TestAllExtensions>(&arena);
993 message_ext->SetExtension(
994 protobuf_unittest::optional_int32_extension, 42);
995 message_ext->SetExtension(
996 protobuf_unittest::optional_string_extension, string("test"));
997 message_ext->MutableExtension(
998 protobuf_unittest::optional_nested_message_extension)->set_bb(42);
999 }
1000
TEST(ArenaTest,RepeatedFieldOnArena)1001 TEST(ArenaTest, RepeatedFieldOnArena) {
1002 // Preallocate an initial arena block to avoid mallocs during hooked region.
1003 std::vector<char> arena_block(1024 * 1024);
1004 ArenaOptions options;
1005 options.initial_block = &arena_block[0];
1006 options.initial_block_size = arena_block.size();
1007 Arena arena(options);
1008
1009 {
1010 internal::NoHeapChecker no_heap;
1011
1012 // Fill some repeated fields on the arena to test for leaks. Also verify no
1013 // memory allocations.
1014 RepeatedField<int32> repeated_int32(&arena);
1015 RepeatedPtrField<TestAllTypes> repeated_message(&arena);
1016 for (int i = 0; i < 100; i++) {
1017 repeated_int32.Add(42);
1018 repeated_message.Add()->set_optional_int32(42);
1019 EXPECT_EQ(&arena, repeated_message.Get(0).GetArena());
1020 const TestAllTypes* msg_in_repeated_field = &repeated_message.Get(0);
1021 TestAllTypes* msg = repeated_message.UnsafeArenaReleaseLast();
1022 EXPECT_EQ(msg_in_repeated_field, msg);
1023 }
1024
1025 // UnsafeArenaExtractSubrange (i) should not leak and (ii) should return
1026 // on-arena pointers.
1027 for (int i = 0; i < 10; i++) {
1028 repeated_message.Add()->set_optional_int32(42);
1029 }
1030 TestAllTypes* extracted_messages[5];
1031 repeated_message.UnsafeArenaExtractSubrange(0, 5, extracted_messages);
1032 EXPECT_EQ(&arena, repeated_message.Get(0).GetArena());
1033 EXPECT_EQ(5, repeated_message.size());
1034 }
1035
1036 // Now, outside the scope of the NoHeapChecker, test ExtractSubrange's copying
1037 // semantics.
1038 {
1039 RepeatedPtrField<TestAllTypes> repeated_message(&arena);
1040 for (int i = 0; i < 100; i++) {
1041 repeated_message.Add()->set_optional_int32(42);
1042 }
1043
1044 TestAllTypes* extracted_messages[5];
1045 // ExtractSubrange should copy to the heap.
1046 repeated_message.ExtractSubrange(0, 5, extracted_messages);
1047 EXPECT_EQ(NULL, extracted_messages[0]->GetArena());
1048 // We need to free the heap-allocated messages to prevent a leak.
1049 for (int i = 0; i < 5; i++) {
1050 delete extracted_messages[i];
1051 extracted_messages[i] = NULL;
1052 }
1053 }
1054
1055 // Now check that we can create RepeatedFields/RepeatedPtrFields themselves on
1056 // the arena. They have the necessary type traits so that they can behave like
1057 // messages in this way. This is useful for higher-level generic templated
1058 // code that may allocate messages or repeated fields of messages on an arena.
1059 {
1060 RepeatedPtrField<TestAllTypes>* repeated_ptr_on_arena =
1061 Arena::CreateMessage< RepeatedPtrField<TestAllTypes> >(&arena);
1062 for (int i = 0; i < 10; i++) {
1063 // Add some elements and let the leak-checker ensure that everything is
1064 // freed.
1065 repeated_ptr_on_arena->Add();
1066 }
1067
1068 RepeatedField<int>* repeated_int_on_arena =
1069 Arena::CreateMessage< RepeatedField<int> >(&arena);
1070 for (int i = 0; i < 100; i++) {
1071 repeated_int_on_arena->Add(i);
1072 }
1073
1074 }
1075
1076 arena.Reset();
1077 }
1078
1079
1080 #ifndef GOOGLE_PROTOBUF_NO_RTTI
TEST(ArenaTest,MutableMessageReflection)1081 TEST(ArenaTest, MutableMessageReflection) {
1082 Arena arena;
1083 TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
1084 const Reflection* r = message->GetReflection();
1085 const Descriptor* d = message->GetDescriptor();
1086 const FieldDescriptor* field = d->FindFieldByName("optional_nested_message");
1087 TestAllTypes::NestedMessage* submessage =
1088 static_cast<TestAllTypes::NestedMessage*>(
1089 r->MutableMessage(message, field));
1090 TestAllTypes::NestedMessage* submessage_expected =
1091 message->mutable_optional_nested_message();
1092
1093 EXPECT_EQ(submessage_expected, submessage);
1094 EXPECT_EQ(&arena, submessage->GetArena());
1095
1096 const FieldDescriptor* oneof_field = d->FindFieldByName("oneof_nested_message");
1097 submessage = static_cast<TestAllTypes::NestedMessage*>(
1098 r->MutableMessage(message, oneof_field));
1099 submessage_expected = message->mutable_oneof_nested_message();
1100
1101 EXPECT_EQ(submessage_expected, submessage);
1102 EXPECT_EQ(&arena, submessage->GetArena());
1103 }
1104 #endif // !GOOGLE_PROTOBUF_NO_RTTI
1105
1106
1107 namespace {
1108
FillArenaAwareFields(TestAllTypes * message)1109 void FillArenaAwareFields(TestAllTypes* message) {
1110 string test_string = "hello world";
1111 message->set_optional_int32(42);
1112 message->set_optional_string(test_string);
1113 message->set_optional_bytes(test_string);
1114 message->mutable_optional_nested_message()->set_bb(42);
1115
1116 message->set_oneof_uint32(42);
1117 message->mutable_oneof_nested_message()->set_bb(42);
1118 message->set_oneof_string(test_string);
1119 message->set_oneof_bytes(test_string);
1120
1121 message->add_repeated_int32(42);
1122 // No repeated string: not yet arena-aware.
1123 message->add_repeated_nested_message()->set_bb(42);
1124 message->mutable_optional_lazy_message()->set_bb(42);
1125 }
1126
1127 }
1128
1129 // Test: no allocations occur on heap while touching all supported field types.
TEST(ArenaTest,NoHeapAllocationsTest)1130 TEST(ArenaTest, NoHeapAllocationsTest) {
1131 // Allocate a large initial block to avoid mallocs during hooked test.
1132 std::vector<char> arena_block(128 * 1024);
1133 ArenaOptions options;
1134 options.initial_block = &arena_block[0];
1135 options.initial_block_size = arena_block.size();
1136 Arena arena(options);
1137
1138 {
1139
1140 TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
1141 FillArenaAwareFields(message);
1142 }
1143
1144 arena.Reset();
1145 }
1146
1147 #ifndef GOOGLE_PROTOBUF_NO_RTTI
1148 // Test construction on an arena via generic MessageLite interface. We should be
1149 // able to successfully deserialize on the arena without incurring heap
1150 // allocations, i.e., everything should still be arena-allocation-aware.
TEST(ArenaTest,MessageLiteOnArena)1151 TEST(ArenaTest, MessageLiteOnArena) {
1152 std::vector<char> arena_block(128 * 1024);
1153 ArenaOptions options;
1154 options.initial_block = &arena_block[0];
1155 options.initial_block_size = arena_block.size();
1156 Arena arena(options);
1157 const google::protobuf::MessageLite* prototype = &TestAllTypes::default_instance();
1158
1159 TestAllTypes initial_message;
1160 FillArenaAwareFields(&initial_message);
1161 string serialized;
1162 initial_message.SerializeToString(&serialized);
1163
1164 {
1165
1166 google::protobuf::MessageLite* generic_message = prototype->New(&arena);
1167 EXPECT_TRUE(generic_message != NULL);
1168 EXPECT_EQ(&arena, generic_message->GetArena());
1169 EXPECT_TRUE(generic_message->ParseFromString(serialized));
1170 TestAllTypes* deserialized = static_cast<TestAllTypes*>(generic_message);
1171 EXPECT_EQ(42, deserialized->optional_int32());
1172 }
1173
1174 arena.Reset();
1175 }
1176 #endif // !GOOGLE_PROTOBUF_NO_RTTI
1177
1178
1179 // RepeatedField should support non-POD types, and invoke constructors and
1180 // destructors appropriately, because it's used this way by lots of other code
1181 // (even if this was not its original intent).
TEST(ArenaTest,RepeatedFieldWithNonPODType)1182 TEST(ArenaTest, RepeatedFieldWithNonPODType) {
1183 {
1184 RepeatedField<string> field_on_heap;
1185 for (int i = 0; i < 100; i++) {
1186 *field_on_heap.Add() = "test string long enough to exceed inline buffer";
1187 }
1188 }
1189 {
1190 Arena arena;
1191 RepeatedField<string> field_on_arena(&arena);
1192 for (int i = 0; i < 100; i++) {
1193 *field_on_arena.Add() = "test string long enough to exceed inline buffer";
1194 }
1195 }
1196 }
1197
1198 // Align n to next multiple of 8
1199 namespace {
Align8(uint64 n)1200 uint64 Align8(uint64 n) { return (n + 7) & -8; }
1201 } // namespace
1202
TEST(ArenaTest,SpaceAllocated_and_Used)1203 TEST(ArenaTest, SpaceAllocated_and_Used) {
1204 ArenaOptions options;
1205 options.start_block_size = 256;
1206 options.max_block_size = 8192;
1207 Arena arena_1(options);
1208 EXPECT_EQ(0, arena_1.SpaceAllocated());
1209 EXPECT_EQ(0, arena_1.SpaceUsed());
1210 EXPECT_EQ(0, arena_1.Reset());
1211 ::google::protobuf::Arena::CreateArray<char>(&arena_1, 320);
1212 // Arena will allocate slightly more than 320 for the block headers.
1213 EXPECT_LE(320, arena_1.SpaceAllocated());
1214 EXPECT_EQ(Align8(320), arena_1.SpaceUsed());
1215 EXPECT_LE(320, arena_1.Reset());
1216
1217 // Test with initial block.
1218 std::vector<char> arena_block(1024);
1219 options.initial_block = &arena_block[0];
1220 options.initial_block_size = arena_block.size();
1221 Arena arena_2(options);
1222 EXPECT_EQ(1024, arena_2.SpaceAllocated());
1223 EXPECT_EQ(0, arena_2.SpaceUsed());
1224 EXPECT_EQ(1024, arena_2.Reset());
1225 ::google::protobuf::Arena::CreateArray<char>(&arena_2, 55);
1226 EXPECT_EQ(1024, arena_2.SpaceAllocated());
1227 EXPECT_EQ(Align8(55), arena_2.SpaceUsed());
1228 EXPECT_EQ(1024, arena_2.Reset());
1229
1230 // Reset options to test doubling policy explicitly.
1231 options.initial_block = NULL;
1232 options.initial_block_size = 0;
1233 Arena arena_3(options);
1234 EXPECT_EQ(0, arena_3.SpaceUsed());
1235 ::google::protobuf::Arena::CreateArray<char>(&arena_3, 190);
1236 EXPECT_EQ(256, arena_3.SpaceAllocated());
1237 EXPECT_EQ(Align8(190), arena_3.SpaceUsed());
1238 ::google::protobuf::Arena::CreateArray<char>(&arena_3, 70);
1239 EXPECT_EQ(256 + 512, arena_3.SpaceAllocated());
1240 EXPECT_EQ(Align8(190) + Align8(70), arena_3.SpaceUsed());
1241 EXPECT_EQ(256 + 512, arena_3.Reset());
1242 }
1243
TEST(ArenaTest,Alignment)1244 TEST(ArenaTest, Alignment) {
1245 ::google::protobuf::Arena arena;
1246 for (int i = 0; i < 200; i++) {
1247 void* p = ::google::protobuf::Arena::CreateArray<char>(&arena, i);
1248 GOOGLE_CHECK_EQ(reinterpret_cast<uintptr_t>(p) % 8, 0) << i << ": " << p;
1249 }
1250 }
1251
TEST(ArenaTest,GetArenaShouldReturnTheArenaForArenaAllocatedMessages)1252 TEST(ArenaTest, GetArenaShouldReturnTheArenaForArenaAllocatedMessages) {
1253 ::google::protobuf::Arena arena;
1254 ArenaMessage* message = Arena::CreateMessage<ArenaMessage>(&arena);
1255 const ArenaMessage* const_pointer_to_message = message;
1256 EXPECT_EQ(&arena, Arena::GetArena(message));
1257 EXPECT_EQ(&arena, Arena::GetArena(const_pointer_to_message));
1258 }
1259
TEST(ArenaTest,GetArenaShouldReturnNullForNonArenaAllocatedMessages)1260 TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) {
1261 ArenaMessage message;
1262 const ArenaMessage* const_pointer_to_message = &message;
1263 EXPECT_EQ(NULL, Arena::GetArena(&message));
1264 EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message));
1265 }
1266
TEST(ArenaTest,UnsafeSetAllocatedOnArena)1267 TEST(ArenaTest, UnsafeSetAllocatedOnArena) {
1268 ::google::protobuf::Arena arena;
1269 TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
1270 EXPECT_FALSE(message->has_optional_string());
1271
1272 string owned_string = "test with long enough content to heap-allocate";
1273 message->unsafe_arena_set_allocated_optional_string(&owned_string);
1274 EXPECT_TRUE(message->has_optional_string());
1275
1276 message->unsafe_arena_set_allocated_optional_string(NULL);
1277 EXPECT_FALSE(message->has_optional_string());
1278 }
1279
1280 // A helper utility class to only contain static hook functions, some
1281 // counters to be used to verify the counters have been called and a cookie
1282 // value to be verified.
1283 class ArenaHooksTestUtil {
1284 public:
on_init(::google::protobuf::Arena * arena)1285 static void* on_init(::google::protobuf::Arena* arena) {
1286 ++num_init;
1287 int* cookie = new int(kCookieValue);
1288 return static_cast<void*>(cookie);
1289 }
1290
on_allocation(const std::type_info *,uint64 alloc_size,void * cookie)1291 static void on_allocation(const std::type_info* /*unused*/, uint64 alloc_size,
1292 void* cookie) {
1293 ++num_allocations;
1294 int cookie_value = *static_cast<int*>(cookie);
1295 EXPECT_EQ(kCookieValue, cookie_value);
1296 }
1297
on_reset(::google::protobuf::Arena * arena,void * cookie,uint64 space_used)1298 static void on_reset(::google::protobuf::Arena* arena, void* cookie,
1299 uint64 space_used) {
1300 ++num_reset;
1301 int cookie_value = *static_cast<int*>(cookie);
1302 EXPECT_EQ(kCookieValue, cookie_value);
1303 }
1304
on_destruction(::google::protobuf::Arena * arena,void * cookie,uint64 space_used)1305 static void on_destruction(::google::protobuf::Arena* arena, void* cookie,
1306 uint64 space_used) {
1307 ++num_destruct;
1308 int cookie_value = *static_cast<int*>(cookie);
1309 EXPECT_EQ(kCookieValue, cookie_value);
1310 delete static_cast<int*>(cookie);
1311 }
1312
1313 static const int kCookieValue = 999;
1314 static uint32 num_init;
1315 static uint32 num_allocations;
1316 static uint32 num_reset;
1317 static uint32 num_destruct;
1318 };
1319 uint32 ArenaHooksTestUtil::num_init = 0;
1320 uint32 ArenaHooksTestUtil::num_allocations = 0;
1321 uint32 ArenaHooksTestUtil::num_reset = 0;
1322 uint32 ArenaHooksTestUtil::num_destruct = 0;
1323 const int ArenaHooksTestUtil::kCookieValue;
1324
1325 // Test the hooks are correctly called and that the cookie is passed.
TEST(ArenaTest,ArenaHooksSanity)1326 TEST(ArenaTest, ArenaHooksSanity) {
1327 ::google::protobuf::ArenaOptions options;
1328 options.on_arena_init = ArenaHooksTestUtil::on_init;
1329 options.on_arena_allocation = ArenaHooksTestUtil::on_allocation;
1330 options.on_arena_reset = ArenaHooksTestUtil::on_reset;
1331 options.on_arena_destruction = ArenaHooksTestUtil::on_destruction;
1332
1333 // Scope for defining the arena
1334 {
1335 ::google::protobuf::Arena arena(options);
1336 EXPECT_EQ(1, ArenaHooksTestUtil::num_init);
1337 EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations);
1338 ::google::protobuf::Arena::Create<uint64>(&arena);
1339 if (google::protobuf::internal::has_trivial_destructor<uint64>::value) {
1340 EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations);
1341 } else {
1342 EXPECT_EQ(2, ArenaHooksTestUtil::num_allocations);
1343 }
1344 arena.Reset();
1345 arena.Reset();
1346 EXPECT_EQ(2, ArenaHooksTestUtil::num_reset);
1347 }
1348 EXPECT_EQ(3, ArenaHooksTestUtil::num_reset);
1349 EXPECT_EQ(1, ArenaHooksTestUtil::num_destruct);
1350 }
1351
1352 } // namespace protobuf
1353 } // namespace google
1354