1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "google/protobuf/arena.h"
9
10 #include <time.h>
11
12 #include <algorithm>
13 #include <array>
14 #include <atomic>
15 #include <cstddef>
16 #include <cstdint>
17 #include <cstdlib>
18 #include <cstring>
19 #include <memory>
20 #include <new> // IWYU pragma: keep for operator new
21 #include <string>
22 #include <thread>
23 #include <type_traits>
24 #include <utility>
25 #include <vector>
26
27 #include <gmock/gmock.h>
28 #include <gtest/gtest.h>
29 #include "absl/log/absl_check.h"
30 #include "absl/log/absl_log.h"
31 #include "absl/strings/string_view.h"
32 #include "absl/synchronization/barrier.h"
33 #include "absl/utility/utility.h"
34 #include "google/protobuf/arena_cleanup.h"
35 #include "google/protobuf/arena_test_util.h"
36 #include "google/protobuf/descriptor.h"
37 #include "google/protobuf/extension_set.h"
38 #include "google/protobuf/io/coded_stream.h"
39 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
40 #include "google/protobuf/message.h"
41 #include "google/protobuf/message_lite.h"
42 #include "google/protobuf/port.h"
43 #include "google/protobuf/repeated_field.h"
44 #include "google/protobuf/test_util.h"
45 #include "google/protobuf/unittest.pb.h"
46 #include "google/protobuf/unittest_arena.pb.h"
47 #include "google/protobuf/unknown_field_set.h"
48 #include "google/protobuf/wire_format_lite.h"
49
50 #include "absl/synchronization/mutex.h"
51
52 // Must be included last
53 #include "google/protobuf/port_def.inc"
54
55 using proto2_arena_unittest::ArenaMessage;
56 using protobuf_unittest::NestedTestAllTypes;
57 using protobuf_unittest::TestAllExtensions;
58 using protobuf_unittest::TestAllTypes;
59 using protobuf_unittest::TestEmptyMessage;
60 using protobuf_unittest::TestOneof2;
61 using protobuf_unittest::TestRepeatedString;
62 using ::testing::ElementsAreArray;
63
64 namespace google {
65 namespace protobuf {
66
67 class Notifier {
68 public:
Notifier()69 Notifier() : count_(0) {}
Notify()70 void Notify() { count_++; }
GetCount()71 int GetCount() { return count_; }
72
73 private:
74 int count_;
75 };
76
77 class SimpleDataType {
78 public:
SimpleDataType()79 SimpleDataType() : notifier_(nullptr) {}
SetNotifier(Notifier * notifier)80 void SetNotifier(Notifier* notifier) { notifier_ = notifier; }
~SimpleDataType()81 virtual ~SimpleDataType() {
82 if (notifier_ != nullptr) {
83 notifier_->Notify();
84 }
85 };
86
87 private:
88 Notifier* notifier_;
89 };
90
91 // A simple class that does not allow copying and so cannot be used as a
92 // parameter type without "const &".
93 class PleaseDontCopyMe {
94 public:
PleaseDontCopyMe(int value)95 explicit PleaseDontCopyMe(int value) : value_(value) {}
96 PleaseDontCopyMe(const PleaseDontCopyMe&) = delete;
97 PleaseDontCopyMe& operator=(const PleaseDontCopyMe&) = delete;
98
value() const99 int value() const { return value_; }
100
101 private:
102 int value_;
103 };
104
105 // A class that takes four different types as constructor arguments.
106 class MustBeConstructedWithOneThroughFour {
107 public:
MustBeConstructedWithOneThroughFour(int one,const char * two,const std::string & three,const PleaseDontCopyMe * four)108 MustBeConstructedWithOneThroughFour(int one, const char* two,
109 const std::string& three,
110 const PleaseDontCopyMe* four)
111 : one_(one), two_(two), three_(three), four_(four) {}
112 MustBeConstructedWithOneThroughFour(
113 const MustBeConstructedWithOneThroughFour&) = delete;
114 MustBeConstructedWithOneThroughFour& operator=(
115 const MustBeConstructedWithOneThroughFour&) = delete;
116
117 int one_;
118 const char* const two_;
119 std::string three_;
120 const PleaseDontCopyMe* four_;
121 };
122
123 // A class that takes eight different types as constructor arguments.
124 class MustBeConstructedWithOneThroughEight {
125 public:
MustBeConstructedWithOneThroughEight(int one,const char * two,const std::string & three,const PleaseDontCopyMe * four,int five,const char * six,const std::string & seven,const std::string & eight)126 MustBeConstructedWithOneThroughEight(int one, const char* two,
127 const std::string& three,
128 const PleaseDontCopyMe* four, int five,
129 const char* six,
130 const std::string& seven,
131 const std::string& eight)
132 : one_(one),
133 two_(two),
134 three_(three),
135 four_(four),
136 five_(five),
137 six_(six),
138 seven_(seven),
139 eight_(eight) {}
140 MustBeConstructedWithOneThroughEight(
141 const MustBeConstructedWithOneThroughEight&) = delete;
142 MustBeConstructedWithOneThroughEight& operator=(
143 const MustBeConstructedWithOneThroughEight&) = delete;
144
145 int one_;
146 const char* const two_;
147 std::string three_;
148 const PleaseDontCopyMe* four_;
149 int five_;
150 const char* const six_;
151 std::string seven_;
152 std::string eight_;
153 };
154
TEST(ArenaTest,ArenaConstructable)155 TEST(ArenaTest, ArenaConstructable) {
156 EXPECT_TRUE(Arena::is_arena_constructable<TestAllTypes>::type::value);
157 EXPECT_TRUE(Arena::is_arena_constructable<const TestAllTypes>::type::value);
158 EXPECT_FALSE(Arena::is_arena_constructable<Arena>::type::value);
159 }
160
TEST(ArenaTest,DestructorSkippable)161 TEST(ArenaTest, DestructorSkippable) {
162 EXPECT_TRUE(Arena::is_destructor_skippable<TestAllTypes>::type::value);
163 EXPECT_TRUE(Arena::is_destructor_skippable<const TestAllTypes>::type::value);
164 EXPECT_FALSE(Arena::is_destructor_skippable<Arena>::type::value);
165 }
166
167 template <int>
168 struct EmptyBase {};
169 struct ArenaCtorBase {
170 using InternalArenaConstructable_ = void;
171 };
172 struct ArenaDtorBase {
173 using DestructorSkippable_ = void;
174 };
175
176 template <bool arena_ctor, bool arena_dtor>
TestCtorAndDtorTraits(std::vector<absl::string_view> def,std::vector<absl::string_view> copy,std::vector<absl::string_view> with_int)177 void TestCtorAndDtorTraits(std::vector<absl::string_view> def,
178 std::vector<absl::string_view> copy,
179 std::vector<absl::string_view> with_int) {
180 static auto& actions = *new std::vector<absl::string_view>;
181 struct TraitsProber
182 : std::conditional_t<arena_ctor, ArenaCtorBase, EmptyBase<0>>,
183 std::conditional_t<arena_dtor, ArenaDtorBase, EmptyBase<1>>,
184 Message {
185 TraitsProber() : Message(nullptr, nullptr) { actions.push_back("()"); }
186 TraitsProber(const TraitsProber&) : Message(nullptr, nullptr) {
187 actions.push_back("(const T&)");
188 }
189 explicit TraitsProber(int) : Message(nullptr, nullptr) {
190 actions.push_back("(int)");
191 }
192 explicit TraitsProber(Arena* arena) : Message(nullptr, nullptr) {
193 actions.push_back("(Arena)");
194 }
195 TraitsProber(Arena* arena, const TraitsProber&)
196 : Message(nullptr, nullptr) {
197 actions.push_back("(Arena, const T&)");
198 }
199 TraitsProber(Arena* arena, int) : Message(nullptr, nullptr) {
200 actions.push_back("(Arena, int)");
201 }
202 ~TraitsProber() { actions.push_back("~()"); }
203
204 TraitsProber* New(Arena*) const {
205 ABSL_LOG(FATAL);
206 return nullptr;
207 }
208 const internal::ClassData* GetClassData() const PROTOBUF_FINAL {
209 ABSL_LOG(FATAL);
210 return nullptr;
211 }
212 };
213
214 static_assert(
215 !arena_ctor || Arena::is_arena_constructable<TraitsProber>::value, "");
216 static_assert(
217 !arena_dtor || Arena::is_destructor_skippable<TraitsProber>::value, "");
218
219 {
220 actions.clear();
221 Arena arena;
222 Arena::Create<TraitsProber>(&arena);
223 }
224 EXPECT_THAT(actions, ElementsAreArray(def));
225
226 const TraitsProber p;
227 {
228 actions.clear();
229 Arena arena;
230 Arena::Create<TraitsProber>(&arena, p);
231 }
232 EXPECT_THAT(actions, ElementsAreArray(copy));
233
234 {
235 actions.clear();
236 Arena arena;
237 Arena::Create<TraitsProber>(&arena, 17);
238 }
239 EXPECT_THAT(actions, ElementsAreArray(with_int));
240 }
241
TEST(ArenaTest,AllConstructibleAndDestructibleCombinationsWorkCorrectly)242 TEST(ArenaTest, AllConstructibleAndDestructibleCombinationsWorkCorrectly) {
243 TestCtorAndDtorTraits<false, false>({"()", "~()"}, {"(const T&)", "~()"},
244 {"(int)", "~()"});
245 // If the object is not arena constructible, then the destructor is always
246 // called even if marked as skippable.
247 TestCtorAndDtorTraits<false, true>({"()", "~()"}, {"(const T&)", "~()"},
248 {"(int)", "~()"});
249
250 // Some types are arena constructible but we can't skip the destructor. Those
251 // are constructed with an arena but still destroyed.
252 TestCtorAndDtorTraits<true, false>({"(Arena)", "~()"},
253 {"(Arena, const T&)", "~()"},
254 {"(Arena, int)", "~()"});
255 TestCtorAndDtorTraits<true, true>({"(Arena)"}, {"(Arena, const T&)"},
256 {"(Arena, int)"});
257 }
258
TEST(ArenaTest,BasicCreate)259 TEST(ArenaTest, BasicCreate) {
260 Arena arena;
261 EXPECT_TRUE(Arena::Create<int32_t>(&arena) != nullptr);
262 EXPECT_TRUE(Arena::Create<int64_t>(&arena) != nullptr);
263 EXPECT_TRUE(Arena::Create<float>(&arena) != nullptr);
264 EXPECT_TRUE(Arena::Create<double>(&arena) != nullptr);
265 EXPECT_TRUE(Arena::Create<std::string>(&arena) != nullptr);
266 arena.Own(new int32_t);
267 arena.Own(new int64_t);
268 arena.Own(new float);
269 arena.Own(new double);
270 arena.Own(new std::string);
271 arena.Own<int>(nullptr);
272 Notifier notifier;
273 SimpleDataType* data = Arena::Create<SimpleDataType>(&arena);
274 data->SetNotifier(¬ifier);
275 data = new SimpleDataType;
276 data->SetNotifier(¬ifier);
277 arena.Own(data);
278 arena.Reset();
279 EXPECT_EQ(2, notifier.GetCount());
280 }
281
TEST(ArenaTest,CreateAndConstCopy)282 TEST(ArenaTest, CreateAndConstCopy) {
283 Arena arena;
284 const std::string s("foo");
285 const std::string* s_copy = Arena::Create<std::string>(&arena, s);
286 EXPECT_TRUE(s_copy != nullptr);
287 EXPECT_EQ("foo", s);
288 EXPECT_EQ("foo", *s_copy);
289 }
290
TEST(ArenaTest,CreateAndNonConstCopy)291 TEST(ArenaTest, CreateAndNonConstCopy) {
292 Arena arena;
293 std::string s("foo");
294 const std::string* s_copy = Arena::Create<std::string>(&arena, s);
295 EXPECT_TRUE(s_copy != nullptr);
296 EXPECT_EQ("foo", s);
297 EXPECT_EQ("foo", *s_copy);
298 }
299
TEST(ArenaTest,CreateAndMove)300 TEST(ArenaTest, CreateAndMove) {
301 Arena arena;
302 std::string s("foo");
303 const std::string* s_move = Arena::Create<std::string>(&arena, std::move(s));
304 EXPECT_TRUE(s_move != nullptr);
305 EXPECT_TRUE(s.empty()); // NOLINT
306 EXPECT_EQ("foo", *s_move);
307 }
308
TEST(ArenaTest,CreateWithFourConstructorArguments)309 TEST(ArenaTest, CreateWithFourConstructorArguments) {
310 Arena arena;
311 const std::string three("3");
312 const PleaseDontCopyMe four(4);
313 const MustBeConstructedWithOneThroughFour* new_object =
314 Arena::Create<MustBeConstructedWithOneThroughFour>(&arena, 1, "2", three,
315 &four);
316 EXPECT_TRUE(new_object != nullptr);
317 ASSERT_EQ(1, new_object->one_);
318 ASSERT_STREQ("2", new_object->two_);
319 ASSERT_EQ("3", new_object->three_);
320 ASSERT_EQ(4, new_object->four_->value());
321 }
322
TEST(ArenaTest,CreateWithEightConstructorArguments)323 TEST(ArenaTest, CreateWithEightConstructorArguments) {
324 Arena arena;
325 const std::string three("3");
326 const PleaseDontCopyMe four(4);
327 const std::string seven("7");
328 const std::string eight("8");
329 const MustBeConstructedWithOneThroughEight* new_object =
330 Arena::Create<MustBeConstructedWithOneThroughEight>(
331 &arena, 1, "2", three, &four, 5, "6", seven, eight);
332 EXPECT_TRUE(new_object != nullptr);
333 ASSERT_EQ(1, new_object->one_);
334 ASSERT_STREQ("2", new_object->two_);
335 ASSERT_EQ("3", new_object->three_);
336 ASSERT_EQ(4, new_object->four_->value());
337 ASSERT_EQ(5, new_object->five_);
338 ASSERT_STREQ("6", new_object->six_);
339 ASSERT_EQ("7", new_object->seven_);
340 ASSERT_EQ("8", new_object->eight_);
341 }
342
343 class PleaseMoveMe {
344 public:
PleaseMoveMe(const std::string & value)345 explicit PleaseMoveMe(const std::string& value) : value_(value) {}
346 PleaseMoveMe(PleaseMoveMe&&) = default;
347 PleaseMoveMe(const PleaseMoveMe&) = delete;
348
value() const349 const std::string& value() const { return value_; }
350
351 private:
352 std::string value_;
353 };
354
TEST(ArenaTest,CreateWithMoveArguments)355 TEST(ArenaTest, CreateWithMoveArguments) {
356 Arena arena;
357 PleaseMoveMe one("1");
358 const PleaseMoveMe* new_object =
359 Arena::Create<PleaseMoveMe>(&arena, std::move(one));
360 EXPECT_TRUE(new_object);
361 ASSERT_EQ("1", new_object->value());
362 }
363
TEST(ArenaTest,InitialBlockTooSmall)364 TEST(ArenaTest, InitialBlockTooSmall) {
365 // Construct a small blocks of memory to be used by the arena allocator; then,
366 // allocate an object which will not fit in the initial block.
367 for (uint32_t size = 0; size <= internal::SerialArena::kBlockHeaderSize + 32;
368 size++) {
369 std::vector<char> arena_block(size);
370 ArenaOptions options;
371 options.initial_block = arena_block.data();
372 options.initial_block_size = arena_block.size();
373
374 // Try sometimes with non-default block sizes so that we exercise paths
375 // with and without ArenaImpl::Options.
376 if ((size % 2) != 0) {
377 options.start_block_size += 8;
378 }
379
380 Arena arena(options);
381
382 char* p = Arena::CreateArray<char>(&arena, 96);
383 uintptr_t allocation = reinterpret_cast<uintptr_t>(p);
384
385 // Ensure that the arena allocator did not return memory pointing into the
386 // initial block of memory.
387 uintptr_t arena_start = reinterpret_cast<uintptr_t>(arena_block.data());
388 uintptr_t arena_end = arena_start + arena_block.size();
389 EXPECT_FALSE(allocation >= arena_start && allocation < arena_end);
390
391 // Write to the memory we allocated; this should (but is not guaranteed to)
392 // trigger a check for heap corruption if the object was allocated from the
393 // initially-provided block.
394 memset(p, '\0', 96);
395 }
396 }
397
TEST(ArenaTest,CreateDestroy)398 TEST(ArenaTest, CreateDestroy) {
399 TestAllTypes original;
400 TestUtil::SetAllFields(&original);
401
402 // Test memory leak.
403 Arena arena;
404 TestAllTypes* heap_message = Arena::Create<TestAllTypes>(nullptr);
405 TestAllTypes* arena_message = Arena::Create<TestAllTypes>(&arena);
406
407 *heap_message = original;
408 *arena_message = original;
409
410 Arena::Destroy(heap_message);
411 Arena::Destroy(arena_message);
412
413 // The arena message should still exist.
414 EXPECT_EQ(strlen(original.optional_string().c_str()),
415 strlen(arena_message->optional_string().c_str()));
416 }
417
TEST(ArenaTest,MoveCtorOnArena)418 TEST(ArenaTest, MoveCtorOnArena) {
419 Arena arena;
420
421 ASSERT_EQ(arena.SpaceUsed(), 0);
422
423 auto* original = Arena::Create<NestedTestAllTypes>(&arena);
424 TestUtil::SetAllFields(original->mutable_payload());
425 TestUtil::ExpectAllFieldsSet(original->payload());
426
427 auto usage_original = arena.SpaceUsed();
428 auto* moved = Arena::Create<NestedTestAllTypes>(&arena, std::move(*original));
429 auto usage_by_move = arena.SpaceUsed() - usage_original;
430
431 TestUtil::ExpectAllFieldsSet(moved->payload());
432
433 // The only extra allocation with moves is sizeof(NestedTestAllTypes).
434 EXPECT_EQ(usage_by_move, sizeof(NestedTestAllTypes));
435 EXPECT_LT(usage_by_move + sizeof(TestAllTypes), usage_original);
436
437 // Status after move is unspecified and must not be assumed. It's merely
438 // checking current implementation specifics for protobuf internal.
439 TestUtil::ExpectClear(original->payload());
440 }
441
TEST(ArenaTest,RepeatedFieldMoveCtorOnArena)442 TEST(ArenaTest, RepeatedFieldMoveCtorOnArena) {
443 Arena arena;
444
445 auto* original = Arena::Create<RepeatedField<int32_t>>(&arena);
446 original->Add(1);
447 original->Add(2);
448 ASSERT_EQ(original->size(), 2);
449 ASSERT_EQ(original->Get(0), 1);
450 ASSERT_EQ(original->Get(1), 2);
451
452 auto* moved =
453 Arena::Create<RepeatedField<int32_t>>(&arena, std::move(*original));
454
455 EXPECT_EQ(moved->size(), 2);
456 EXPECT_EQ(moved->Get(0), 1);
457 EXPECT_EQ(moved->Get(1), 2);
458
459 // Status after move is unspecified and must not be assumed. It's merely
460 // checking current implementation specifics for protobuf internal.
461 EXPECT_EQ(original->size(), 0);
462 }
463
TEST(ArenaTest,RepeatedPtrFieldMoveCtorOnArena)464 TEST(ArenaTest, RepeatedPtrFieldMoveCtorOnArena) {
465 Arena arena;
466
467 ASSERT_EQ(arena.SpaceUsed(), 0);
468
469 auto* original = Arena::Create<RepeatedPtrField<TestAllTypes>>(&arena);
470 auto* msg = original->Add();
471 TestUtil::SetAllFields(msg);
472 TestUtil::ExpectAllFieldsSet(*msg);
473
474 auto usage_original = arena.SpaceUsed();
475 auto* moved = Arena::Create<RepeatedPtrField<TestAllTypes>>(
476 &arena, std::move(*original));
477 auto usage_by_move = arena.SpaceUsed() - usage_original;
478
479 EXPECT_EQ(moved->size(), 1);
480 TestUtil::ExpectAllFieldsSet(moved->Get(0));
481
482 // The only extra allocation with moves is sizeof(RepeatedPtrField).
483 EXPECT_EQ(usage_by_move, sizeof(internal::RepeatedPtrFieldBase));
484 EXPECT_LT(usage_by_move + sizeof(TestAllTypes), usage_original);
485
486 // Status after move is unspecified and must not be assumed. It's merely
487 // checking current implementation specifics for protobuf internal.
488 EXPECT_EQ(original->size(), 0);
489 }
490
491 struct OnlyArenaConstructible {
492 using InternalArenaConstructable_ = void;
OnlyArenaConstructiblegoogle::protobuf::OnlyArenaConstructible493 explicit OnlyArenaConstructible(Arena* arena) {}
494 };
495
TEST(ArenaTest,ArenaOnlyTypesCanBeConstructed)496 TEST(ArenaTest, ArenaOnlyTypesCanBeConstructed) {
497 Arena arena;
498 Arena::Create<OnlyArenaConstructible>(&arena);
499 }
500
TEST(ArenaTest,GetConstructTypeWorks)501 TEST(ArenaTest, GetConstructTypeWorks) {
502 using T = TestAllTypes;
503 using Peer = internal::ArenaTestPeer;
504 using CT = typename Peer::ConstructType;
505 EXPECT_EQ(CT::kDefault, (Peer::GetConstructType<T>()));
506 EXPECT_EQ(CT::kCopy, (Peer::GetConstructType<T, const T&>()));
507 EXPECT_EQ(CT::kCopy, (Peer::GetConstructType<T, T&>()));
508 EXPECT_EQ(CT::kCopy, (Peer::GetConstructType<T, const T&&>()));
509 EXPECT_EQ(CT::kMove, (Peer::GetConstructType<T, T&&>()));
510 EXPECT_EQ(CT::kUnknown, (Peer::GetConstructType<T, double&>()));
511 EXPECT_EQ(CT::kUnknown, (Peer::GetConstructType<T, T&, T&>()));
512
513 // For non-protos, it's always unknown
514 EXPECT_EQ(CT::kUnknown, (Peer::GetConstructType<int, const int&>()));
515 }
516
517 #ifdef __cpp_if_constexpr
518 class DispatcherTestProto : public Message {
519 public:
520 using InternalArenaConstructable_ = void;
521 using DestructorSkippable_ = void;
522 // For the test below to construct.
DispatcherTestProto(absl::in_place_t)523 explicit DispatcherTestProto(absl::in_place_t) : Message(nullptr, nullptr) {}
DispatcherTestProto(Arena *)524 explicit DispatcherTestProto(Arena*) : Message(nullptr, nullptr) {
525 ABSL_LOG(FATAL);
526 }
DispatcherTestProto(Arena *,const DispatcherTestProto &)527 DispatcherTestProto(Arena*, const DispatcherTestProto&)
528 : Message(nullptr, nullptr) {
529 ABSL_LOG(FATAL);
530 }
GetClassData() const531 const internal::ClassData* GetClassData() const PROTOBUF_FINAL {
532 ABSL_LOG(FATAL);
533 }
534 };
535 // We use a specialization to inject behavior for the test.
536 // This test is very intrusive and will have to be fixed if we change the
537 // implementation of CreateMessage.
538 absl::string_view hook_called;
539 template <>
DefaultConstruct(Arena *)540 void* Arena::DefaultConstruct<DispatcherTestProto>(Arena*) {
541 hook_called = "default";
542 return nullptr;
543 }
544 template <>
CopyConstruct(Arena *,const void *)545 void* Arena::CopyConstruct<DispatcherTestProto>(Arena*, const void*) {
546 hook_called = "copy";
547 return nullptr;
548 }
549 template <>
CreateArenaCompatible(Arena *,int &&)550 DispatcherTestProto* Arena::CreateArenaCompatible<DispatcherTestProto, int>(
551 Arena*, int&&) {
552 hook_called = "fallback";
553 return nullptr;
554 }
555
TEST(ArenaTest,CreateArenaConstructable)556 TEST(ArenaTest, CreateArenaConstructable) {
557 TestAllTypes original;
558 TestUtil::SetAllFields(&original);
559
560 Arena arena;
561 auto copied = Arena::Create<TestAllTypes>(&arena, original);
562
563 TestUtil::ExpectAllFieldsSet(*copied);
564 EXPECT_EQ(copied->GetArena(), &arena);
565 EXPECT_EQ(copied->optional_nested_message().GetArena(), &arena);
566 }
567
TEST(ArenaTest,CreateRepeatedPtrField)568 TEST(ArenaTest, CreateRepeatedPtrField) {
569 Arena arena;
570 auto repeated = Arena::Create<RepeatedPtrField<TestAllTypes>>(&arena);
571 TestUtil::SetAllFields(repeated->Add());
572
573 TestUtil::ExpectAllFieldsSet(repeated->Get(0));
574 EXPECT_EQ(repeated->GetArena(), &arena);
575 EXPECT_EQ(repeated->Get(0).GetArena(), &arena);
576 EXPECT_EQ(repeated->Get(0).optional_nested_message().GetArena(), &arena);
577 }
578
TEST(ArenaTest,CreateMessageDispatchesToSpecialFunctions)579 TEST(ArenaTest, CreateMessageDispatchesToSpecialFunctions) {
580 hook_called = "";
581 Arena::Create<DispatcherTestProto>(nullptr);
582 EXPECT_EQ(hook_called, "default");
583
584 DispatcherTestProto ref(absl::in_place);
585 const DispatcherTestProto& cref = ref;
586
587 hook_called = "";
588 Arena::Create<DispatcherTestProto>(nullptr);
589 EXPECT_EQ(hook_called, "default");
590
591 hook_called = "";
592 Arena::Create<DispatcherTestProto>(nullptr, ref);
593 EXPECT_EQ(hook_called, "copy");
594
595 hook_called = "";
596 Arena::Create<DispatcherTestProto>(nullptr, cref);
597 EXPECT_EQ(hook_called, "copy");
598
599 hook_called = "";
600 Arena::Create<DispatcherTestProto>(nullptr, 1);
601 EXPECT_EQ(hook_called, "fallback");
602 }
603 #endif // __cpp_if_constexpr
604
TEST(ArenaTest,Parsing)605 TEST(ArenaTest, Parsing) {
606 TestAllTypes original;
607 TestUtil::SetAllFields(&original);
608
609 // Test memory leak.
610 Arena arena;
611 TestAllTypes* arena_message = Arena::Create<TestAllTypes>(&arena);
612 arena_message->ParseFromString(original.SerializeAsString());
613 TestUtil::ExpectAllFieldsSet(*arena_message);
614
615 // Test that string fields have nul terminator bytes (earlier bug).
616 EXPECT_EQ(strlen(original.optional_string().c_str()),
617 strlen(arena_message->optional_string().c_str()));
618 }
619
TEST(ArenaTest,UnknownFields)620 TEST(ArenaTest, UnknownFields) {
621 TestAllTypes original;
622 TestUtil::SetAllFields(&original);
623
624 // Test basic parsing into (populating) and reading out of unknown fields on
625 // an arena.
626 Arena arena;
627 TestEmptyMessage* arena_message = Arena::Create<TestEmptyMessage>(&arena);
628 arena_message->ParseFromString(original.SerializeAsString());
629
630 TestAllTypes copied;
631 copied.ParseFromString(arena_message->SerializeAsString());
632 TestUtil::ExpectAllFieldsSet(copied);
633
634 // Exercise UFS manual manipulation (setters).
635 arena_message = Arena::Create<TestEmptyMessage>(&arena);
636 arena_message->mutable_unknown_fields()->AddVarint(
637 TestAllTypes::kOptionalInt32FieldNumber, 42);
638 copied.Clear();
639 copied.ParseFromString(arena_message->SerializeAsString());
640 EXPECT_TRUE(copied.has_optional_int32());
641 EXPECT_EQ(42, copied.optional_int32());
642
643 // Exercise UFS swap path.
644 TestEmptyMessage* arena_message_2 = Arena::Create<TestEmptyMessage>(&arena);
645 arena_message_2->Swap(arena_message);
646 copied.Clear();
647 copied.ParseFromString(arena_message_2->SerializeAsString());
648 EXPECT_TRUE(copied.has_optional_int32());
649 EXPECT_EQ(42, copied.optional_int32());
650
651 // Test field manipulation.
652 TestEmptyMessage* arena_message_3 = Arena::Create<TestEmptyMessage>(&arena);
653 arena_message_3->mutable_unknown_fields()->AddVarint(1000, 42);
654 arena_message_3->mutable_unknown_fields()->AddFixed32(1001, 42);
655 arena_message_3->mutable_unknown_fields()->AddFixed64(1002, 42);
656 arena_message_3->mutable_unknown_fields()->AddLengthDelimited(1003, "");
657 arena_message_3->mutable_unknown_fields()->DeleteSubrange(0, 2);
658 arena_message_3->mutable_unknown_fields()->DeleteByNumber(1002);
659 arena_message_3->mutable_unknown_fields()->DeleteByNumber(1003);
660 EXPECT_TRUE(arena_message_3->unknown_fields().empty());
661 }
662
TEST(ArenaTest,Swap)663 TEST(ArenaTest, Swap) {
664 Arena arena1;
665 Arena arena2;
666 TestAllTypes* arena1_message;
667 TestAllTypes* arena2_message;
668
669 // Case 1: Swap(), no UFS on either message, both messages on different
670 // arenas. Arena pointers should remain the same after swap.
671 arena1_message = Arena::Create<TestAllTypes>(&arena1);
672 arena2_message = Arena::Create<TestAllTypes>(&arena2);
673 arena1_message->Swap(arena2_message);
674 EXPECT_EQ(&arena1, arena1_message->GetArena());
675 EXPECT_EQ(&arena2, arena2_message->GetArena());
676
677 // Case 2: Swap(), UFS on one message, both messages on different arenas.
678 arena1_message = Arena::Create<TestAllTypes>(&arena1);
679 arena2_message = Arena::Create<TestAllTypes>(&arena2);
680 arena1_message->mutable_unknown_fields()->AddVarint(1, 42);
681 arena1_message->Swap(arena2_message);
682 EXPECT_EQ(&arena1, arena1_message->GetArena());
683 EXPECT_EQ(&arena2, arena2_message->GetArena());
684 EXPECT_EQ(0, arena1_message->unknown_fields().field_count());
685 EXPECT_EQ(1, arena2_message->unknown_fields().field_count());
686 EXPECT_EQ(42, arena2_message->unknown_fields().field(0).varint());
687
688 // Case 3: Swap(), UFS on both messages, both messages on different arenas.
689 arena1_message = Arena::Create<TestAllTypes>(&arena1);
690 arena2_message = Arena::Create<TestAllTypes>(&arena2);
691 arena1_message->mutable_unknown_fields()->AddVarint(1, 42);
692 arena2_message->mutable_unknown_fields()->AddVarint(2, 84);
693 arena1_message->Swap(arena2_message);
694 EXPECT_EQ(&arena1, arena1_message->GetArena());
695 EXPECT_EQ(&arena2, arena2_message->GetArena());
696 EXPECT_EQ(1, arena1_message->unknown_fields().field_count());
697 EXPECT_EQ(1, arena2_message->unknown_fields().field_count());
698 EXPECT_EQ(84, arena1_message->unknown_fields().field(0).varint());
699 EXPECT_EQ(42, arena2_message->unknown_fields().field(0).varint());
700 }
701
TEST(ArenaTest,ReflectionSwapFields)702 TEST(ArenaTest, ReflectionSwapFields) {
703 Arena arena1;
704 Arena arena2;
705 TestAllTypes* arena1_message;
706 TestAllTypes* arena2_message;
707
708 // Case 1: messages on different arenas, only one message is set.
709 arena1_message = Arena::Create<TestAllTypes>(&arena1);
710 arena2_message = Arena::Create<TestAllTypes>(&arena2);
711 TestUtil::SetAllFields(arena1_message);
712 const Reflection* reflection = arena1_message->GetReflection();
713 std::vector<const FieldDescriptor*> fields;
714 reflection->ListFields(*arena1_message, &fields);
715 reflection->SwapFields(arena1_message, arena2_message, fields);
716 EXPECT_EQ(&arena1, arena1_message->GetArena());
717 EXPECT_EQ(&arena2, arena2_message->GetArena());
718 std::string output;
719 arena1_message->SerializeToString(&output);
720 EXPECT_EQ(0, output.size());
721 TestUtil::ExpectAllFieldsSet(*arena2_message);
722 reflection->SwapFields(arena1_message, arena2_message, fields);
723 arena2_message->SerializeToString(&output);
724 EXPECT_EQ(0, output.size());
725 TestUtil::ExpectAllFieldsSet(*arena1_message);
726
727 // Case 2: messages on different arenas, both messages are set.
728 arena1_message = Arena::Create<TestAllTypes>(&arena1);
729 arena2_message = Arena::Create<TestAllTypes>(&arena2);
730 TestUtil::SetAllFields(arena1_message);
731 TestUtil::SetAllFields(arena2_message);
732 reflection->SwapFields(arena1_message, arena2_message, fields);
733 EXPECT_EQ(&arena1, arena1_message->GetArena());
734 EXPECT_EQ(&arena2, arena2_message->GetArena());
735 TestUtil::ExpectAllFieldsSet(*arena1_message);
736 TestUtil::ExpectAllFieldsSet(*arena2_message);
737
738 // Case 3: messages on different arenas with different lifetimes.
739 arena1_message = Arena::Create<TestAllTypes>(&arena1);
740 {
741 Arena arena3;
742 TestAllTypes* arena3_message = Arena::Create<TestAllTypes>(&arena3);
743 TestUtil::SetAllFields(arena3_message);
744 reflection->SwapFields(arena1_message, arena3_message, fields);
745 }
746 TestUtil::ExpectAllFieldsSet(*arena1_message);
747
748 // Case 4: one message on arena, the other on heap.
749 arena1_message = Arena::Create<TestAllTypes>(&arena1);
750 TestAllTypes message;
751 TestUtil::SetAllFields(arena1_message);
752 reflection->SwapFields(arena1_message, &message, fields);
753 EXPECT_EQ(&arena1, arena1_message->GetArena());
754 EXPECT_EQ(nullptr, message.GetArena());
755 arena1_message->SerializeToString(&output);
756 EXPECT_EQ(0, output.size());
757 TestUtil::ExpectAllFieldsSet(message);
758 }
759
TEST(ArenaTest,SetAllocatedMessage)760 TEST(ArenaTest, SetAllocatedMessage) {
761 Arena arena;
762 TestAllTypes* arena_message = Arena::Create<TestAllTypes>(&arena);
763 TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage;
764 nested->set_bb(118);
765 arena_message->set_allocated_optional_nested_message(nested);
766 EXPECT_EQ(118, arena_message->optional_nested_message().bb());
767 }
768
TEST(ArenaTest,ReleaseMessage)769 TEST(ArenaTest, ReleaseMessage) {
770 Arena arena;
771 TestAllTypes* arena_message = Arena::Create<TestAllTypes>(&arena);
772 arena_message->mutable_optional_nested_message()->set_bb(118);
773 std::unique_ptr<TestAllTypes::NestedMessage> nested(
774 arena_message->release_optional_nested_message());
775 EXPECT_EQ(118, nested->bb());
776
777 TestAllTypes::NestedMessage* released_null =
778 arena_message->release_optional_nested_message();
779 EXPECT_EQ(nullptr, released_null);
780 }
781
TEST(ArenaTest,SetAllocatedString)782 TEST(ArenaTest, SetAllocatedString) {
783 Arena arena;
784 TestAllTypes* arena_message = Arena::Create<TestAllTypes>(&arena);
785 std::string* allocated_str = new std::string("hello");
786 arena_message->set_allocated_optional_string(allocated_str);
787 EXPECT_EQ("hello", arena_message->optional_string());
788 }
789
TEST(ArenaTest,ReleaseString)790 TEST(ArenaTest, ReleaseString) {
791 Arena arena;
792 TestAllTypes* arena_message = Arena::Create<TestAllTypes>(&arena);
793 arena_message->set_optional_string("hello");
794 std::unique_ptr<std::string> released_str(
795 arena_message->release_optional_string());
796 EXPECT_EQ("hello", *released_str);
797
798 // Test default value.
799 }
800
801
TEST(ArenaTest,SwapBetweenArenasWithAllFieldsSet)802 TEST(ArenaTest, SwapBetweenArenasWithAllFieldsSet) {
803 Arena arena1;
804 TestAllTypes* arena1_message = Arena::Create<TestAllTypes>(&arena1);
805 {
806 Arena arena2;
807 TestAllTypes* arena2_message = Arena::Create<TestAllTypes>(&arena2);
808 TestUtil::SetAllFields(arena2_message);
809 arena2_message->Swap(arena1_message);
810 std::string output;
811 arena2_message->SerializeToString(&output);
812 EXPECT_EQ(0, output.size());
813 }
814 TestUtil::ExpectAllFieldsSet(*arena1_message);
815 }
816
TEST(ArenaTest,SwapBetweenArenaAndNonArenaWithAllFieldsSet)817 TEST(ArenaTest, SwapBetweenArenaAndNonArenaWithAllFieldsSet) {
818 TestAllTypes non_arena_message;
819 TestUtil::SetAllFields(&non_arena_message);
820 {
821 Arena arena2;
822 TestAllTypes* arena2_message = Arena::Create<TestAllTypes>(&arena2);
823 TestUtil::SetAllFields(arena2_message);
824 arena2_message->Swap(&non_arena_message);
825 TestUtil::ExpectAllFieldsSet(*arena2_message);
826 TestUtil::ExpectAllFieldsSet(non_arena_message);
827 }
828 }
829
TEST(ArenaTest,UnsafeArenaSwap)830 TEST(ArenaTest, UnsafeArenaSwap) {
831 Arena shared_arena;
832 TestAllTypes* message1 = Arena::Create<TestAllTypes>(&shared_arena);
833 TestAllTypes* message2 = Arena::Create<TestAllTypes>(&shared_arena);
834 TestUtil::SetAllFields(message1);
835 message1->UnsafeArenaSwap(message2);
836 TestUtil::ExpectAllFieldsSet(*message2);
837 }
838
TEST(ArenaTest,SwapBetweenArenasUsingReflection)839 TEST(ArenaTest, SwapBetweenArenasUsingReflection) {
840 Arena arena1;
841 TestAllTypes* arena1_message = Arena::Create<TestAllTypes>(&arena1);
842 {
843 Arena arena2;
844 TestAllTypes* arena2_message = Arena::Create<TestAllTypes>(&arena2);
845 TestUtil::SetAllFields(arena2_message);
846 const Reflection* r = arena2_message->GetReflection();
847 r->Swap(arena1_message, arena2_message);
848 std::string output;
849 arena2_message->SerializeToString(&output);
850 EXPECT_EQ(0, output.size());
851 }
852 TestUtil::ExpectAllFieldsSet(*arena1_message);
853 }
854
TEST(ArenaTest,SwapBetweenArenaAndNonArenaUsingReflection)855 TEST(ArenaTest, SwapBetweenArenaAndNonArenaUsingReflection) {
856 TestAllTypes non_arena_message;
857 TestUtil::SetAllFields(&non_arena_message);
858 {
859 Arena arena2;
860 TestAllTypes* arena2_message = Arena::Create<TestAllTypes>(&arena2);
861 TestUtil::SetAllFields(arena2_message);
862 const Reflection* r = arena2_message->GetReflection();
863 r->Swap(&non_arena_message, arena2_message);
864 TestUtil::ExpectAllFieldsSet(*arena2_message);
865 TestUtil::ExpectAllFieldsSet(non_arena_message);
866 }
867 }
868
TEST(ArenaTest,ReleaseFromArenaMessageMakesCopy)869 TEST(ArenaTest, ReleaseFromArenaMessageMakesCopy) {
870 TestAllTypes::NestedMessage* nested_msg = nullptr;
871 std::string* nested_string = nullptr;
872 {
873 Arena arena;
874 TestAllTypes* arena_message = Arena::Create<TestAllTypes>(&arena);
875 arena_message->mutable_optional_nested_message()->set_bb(42);
876 *arena_message->mutable_optional_string() = "Hello";
877 nested_msg = arena_message->release_optional_nested_message();
878 nested_string = arena_message->release_optional_string();
879 }
880 EXPECT_EQ(42, nested_msg->bb());
881 EXPECT_EQ("Hello", *nested_string);
882 delete nested_msg;
883 delete nested_string;
884 }
885
886 #if PROTOBUF_RTTI
TEST(ArenaTest,ReleaseFromArenaMessageUsingReflectionMakesCopy)887 TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) {
888 TestAllTypes::NestedMessage* nested_msg = nullptr;
889 // Note: no string: reflection API only supports releasing submessages.
890 {
891 Arena arena;
892 TestAllTypes* arena_message = Arena::Create<TestAllTypes>(&arena);
893 arena_message->mutable_optional_nested_message()->set_bb(42);
894 const Reflection* r = arena_message->GetReflection();
895 const FieldDescriptor* f = arena_message->GetDescriptor()->FindFieldByName(
896 "optional_nested_message");
897 nested_msg = DownCastMessage<TestAllTypes::NestedMessage>(
898 r->ReleaseMessage(arena_message, f));
899 }
900 EXPECT_EQ(42, nested_msg->bb());
901 delete nested_msg;
902 }
903 #endif // PROTOBUF_RTTI
904
TEST(ArenaTest,SetAllocatedAcrossArenas)905 TEST(ArenaTest, SetAllocatedAcrossArenas) {
906 Arena arena1;
907 TestAllTypes* arena1_message = Arena::Create<TestAllTypes>(&arena1);
908 TestAllTypes::NestedMessage* heap_submessage =
909 new TestAllTypes::NestedMessage();
910 heap_submessage->set_bb(42);
911 arena1_message->set_allocated_optional_nested_message(heap_submessage);
912 // Should keep same object and add to arena's Own()-list.
913 EXPECT_EQ(heap_submessage, arena1_message->mutable_optional_nested_message());
914 {
915 Arena arena2;
916 TestAllTypes::NestedMessage* arena2_submessage =
917 Arena::Create<TestAllTypes::NestedMessage>(&arena2);
918 arena2_submessage->set_bb(42);
919 #if GTEST_HAS_DEATH_TEST
920 EXPECT_DEBUG_DEATH(arena1_message->set_allocated_optional_nested_message(
921 arena2_submessage),
922 "submessage_arena");
923 #endif
924 EXPECT_NE(arena2_submessage,
925 arena1_message->mutable_optional_nested_message());
926 }
927
928 TestAllTypes::NestedMessage* arena1_submessage =
929 Arena::Create<TestAllTypes::NestedMessage>(&arena1);
930 arena1_submessage->set_bb(42);
931 TestAllTypes* heap_message = new TestAllTypes;
932 #if GTEST_HAS_DEATH_TEST
933 EXPECT_DEBUG_DEATH(
934 heap_message->set_allocated_optional_nested_message(arena1_submessage),
935 "submessage_arena");
936 #endif
937 EXPECT_NE(arena1_submessage, heap_message->mutable_optional_nested_message());
938 delete heap_message;
939 }
940
TEST(ArenaTest,UnsafeArenaSetAllocatedAcrossArenas)941 TEST(ArenaTest, UnsafeArenaSetAllocatedAcrossArenas) {
942 Arena arena1;
943 TestAllTypes* arena1_message = Arena::Create<TestAllTypes>(&arena1);
944 {
945 Arena arena2;
946 TestAllTypes::NestedMessage* arena2_submessage =
947 Arena::Create<TestAllTypes::NestedMessage>(&arena2);
948 arena2_submessage->set_bb(42);
949 arena1_message->unsafe_arena_set_allocated_optional_nested_message(
950 arena2_submessage);
951 EXPECT_EQ(arena2_submessage,
952 arena1_message->mutable_optional_nested_message());
953 EXPECT_EQ(arena2_submessage,
954 arena1_message->unsafe_arena_release_optional_nested_message());
955 }
956
957 TestAllTypes::NestedMessage* arena1_submessage =
958 Arena::Create<TestAllTypes::NestedMessage>(&arena1);
959 arena1_submessage->set_bb(42);
960 TestAllTypes* heap_message = new TestAllTypes;
961 heap_message->unsafe_arena_set_allocated_optional_nested_message(
962 arena1_submessage);
963 EXPECT_EQ(arena1_submessage, heap_message->mutable_optional_nested_message());
964 EXPECT_EQ(arena1_submessage,
965 heap_message->unsafe_arena_release_optional_nested_message());
966 delete heap_message;
967 }
968
TEST(ArenaTest,SetAllocatedAcrossArenasWithReflection)969 TEST(ArenaTest, SetAllocatedAcrossArenasWithReflection) {
970 // Same as above, with reflection.
971 Arena arena1;
972 TestAllTypes* arena1_message = Arena::Create<TestAllTypes>(&arena1);
973 const Reflection* r = arena1_message->GetReflection();
974 const Descriptor* d = arena1_message->GetDescriptor();
975 const FieldDescriptor* msg_field =
976 d->FindFieldByName("optional_nested_message");
977 TestAllTypes::NestedMessage* heap_submessage =
978 new TestAllTypes::NestedMessage();
979 heap_submessage->set_bb(42);
980 r->SetAllocatedMessage(arena1_message, heap_submessage, msg_field);
981 // Should keep same object and add to arena's Own()-list.
982 EXPECT_EQ(heap_submessage, arena1_message->mutable_optional_nested_message());
983 {
984 Arena arena2;
985 TestAllTypes::NestedMessage* arena2_submessage =
986 Arena::Create<TestAllTypes::NestedMessage>(&arena2);
987 arena2_submessage->set_bb(42);
988 #if GTEST_HAS_DEATH_TEST
989 EXPECT_DEBUG_DEATH(
990 r->SetAllocatedMessage(arena1_message, arena2_submessage, msg_field),
991 "GetArena");
992 #endif
993 EXPECT_NE(arena2_submessage,
994 arena1_message->mutable_optional_nested_message());
995 }
996
997 TestAllTypes::NestedMessage* arena1_submessage =
998 Arena::Create<TestAllTypes::NestedMessage>(&arena1);
999 arena1_submessage->set_bb(42);
1000 TestAllTypes* heap_message = new TestAllTypes;
1001 #if GTEST_HAS_DEATH_TEST
1002 EXPECT_DEBUG_DEATH(
1003 r->SetAllocatedMessage(heap_message, arena1_submessage, msg_field),
1004 "GetArena");
1005 #endif
1006 EXPECT_NE(arena1_submessage, heap_message->mutable_optional_nested_message());
1007 delete heap_message;
1008 }
1009
TEST(ArenaTest,UnsafeArenaSetAllocatedAcrossArenasWithReflection)1010 TEST(ArenaTest, UnsafeArenaSetAllocatedAcrossArenasWithReflection) {
1011 // Same as above, with reflection.
1012 Arena arena1;
1013 TestAllTypes* arena1_message = Arena::Create<TestAllTypes>(&arena1);
1014 const Reflection* r = arena1_message->GetReflection();
1015 const Descriptor* d = arena1_message->GetDescriptor();
1016 const FieldDescriptor* msg_field =
1017 d->FindFieldByName("optional_nested_message");
1018 {
1019 Arena arena2;
1020 TestAllTypes::NestedMessage* arena2_submessage =
1021 Arena::Create<TestAllTypes::NestedMessage>(&arena2);
1022 arena2_submessage->set_bb(42);
1023 r->UnsafeArenaSetAllocatedMessage(arena1_message, arena2_submessage,
1024 msg_field);
1025 EXPECT_EQ(arena2_submessage,
1026 arena1_message->mutable_optional_nested_message());
1027 EXPECT_EQ(arena2_submessage,
1028 arena1_message->unsafe_arena_release_optional_nested_message());
1029 }
1030
1031 TestAllTypes::NestedMessage* arena1_submessage =
1032 Arena::Create<TestAllTypes::NestedMessage>(&arena1);
1033 arena1_submessage->set_bb(42);
1034 TestAllTypes* heap_message = new TestAllTypes;
1035 r->UnsafeArenaSetAllocatedMessage(heap_message, arena1_submessage, msg_field);
1036 EXPECT_EQ(arena1_submessage, heap_message->mutable_optional_nested_message());
1037 EXPECT_EQ(arena1_submessage,
1038 heap_message->unsafe_arena_release_optional_nested_message());
1039 delete heap_message;
1040 }
1041
TEST(ArenaTest,AddAllocatedWithReflection)1042 TEST(ArenaTest, AddAllocatedWithReflection) {
1043 Arena arena1;
1044 ArenaMessage* arena1_message = Arena::Create<ArenaMessage>(&arena1);
1045 const Reflection* r = arena1_message->GetReflection();
1046 const Descriptor* d = arena1_message->GetDescriptor();
1047 // Message with cc_enable_arenas = true;
1048 const FieldDescriptor* fd = d->FindFieldByName("repeated_nested_message");
1049 r->AddMessage(arena1_message, fd);
1050 r->AddMessage(arena1_message, fd);
1051 r->AddMessage(arena1_message, fd);
1052 EXPECT_EQ(3, r->FieldSize(*arena1_message, fd));
1053 }
1054
TEST(ArenaTest,RepeatedPtrFieldAddClearedTest)1055 TEST(ArenaTest, RepeatedPtrFieldAddClearedTest) {
1056 {
1057 RepeatedPtrField<TestAllTypes> repeated_field;
1058 EXPECT_TRUE(repeated_field.empty());
1059 EXPECT_EQ(0, repeated_field.size());
1060 // Ownership is passed to repeated_field.
1061 TestAllTypes* cleared = new TestAllTypes();
1062 repeated_field.AddAllocated(cleared);
1063 EXPECT_FALSE(repeated_field.empty());
1064 EXPECT_EQ(1, repeated_field.size());
1065 }
1066 }
1067
TEST(ArenaTest,AddAllocatedToRepeatedField)1068 TEST(ArenaTest, AddAllocatedToRepeatedField) {
1069 // Heap->arena case.
1070 Arena arena1;
1071 TestAllTypes* arena1_message = Arena::Create<TestAllTypes>(&arena1);
1072 for (int i = 0; i < 10; i++) {
1073 TestAllTypes::NestedMessage* heap_submessage =
1074 new TestAllTypes::NestedMessage();
1075 heap_submessage->set_bb(42);
1076 arena1_message->mutable_repeated_nested_message()->AddAllocated(
1077 heap_submessage);
1078 // Should not copy object -- will use arena_->Own().
1079 EXPECT_EQ(heap_submessage, &arena1_message->repeated_nested_message(i));
1080 EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
1081 }
1082
1083 // Arena1->Arena2 case.
1084 arena1_message->Clear();
1085 for (int i = 0; i < 10; i++) {
1086 Arena arena2;
1087 TestAllTypes::NestedMessage* arena2_submessage =
1088 Arena::Create<TestAllTypes::NestedMessage>(&arena2);
1089 arena2_submessage->set_bb(42);
1090 arena1_message->mutable_repeated_nested_message()->AddAllocated(
1091 arena2_submessage);
1092 ASSERT_THAT(arena1_message->repeated_nested_message(), testing::SizeIs(1));
1093 EXPECT_EQ(
1094 arena1_message->mutable_repeated_nested_message()->at(0).GetArena(),
1095 &arena1);
1096 arena1_message->clear_repeated_nested_message();
1097 }
1098
1099 // Arena->heap case.
1100 TestAllTypes* heap_message = new TestAllTypes;
1101 for (int i = 0; i < 10; i++) {
1102 Arena arena2;
1103 TestAllTypes::NestedMessage* arena2_submessage =
1104 Arena::Create<TestAllTypes::NestedMessage>(&arena2);
1105 arena2_submessage->set_bb(42);
1106 heap_message->mutable_repeated_nested_message()->AddAllocated(
1107 arena2_submessage);
1108 ASSERT_THAT(heap_message->repeated_nested_message(), testing::SizeIs(1));
1109 EXPECT_EQ(heap_message->mutable_repeated_nested_message()->at(0).GetArena(),
1110 nullptr);
1111 heap_message->clear_repeated_nested_message();
1112 }
1113 delete heap_message;
1114
1115 // Heap->arena case for strings (which are not arena-allocated).
1116 arena1_message->Clear();
1117 for (int i = 0; i < 10; i++) {
1118 std::string* s = new std::string("Test");
1119 arena1_message->mutable_repeated_string()->AddAllocated(s);
1120 // Should not copy.
1121 EXPECT_EQ(s, &arena1_message->repeated_string(i));
1122 EXPECT_EQ("Test", arena1_message->repeated_string(i));
1123 }
1124 }
1125
TEST(ArenaTest,UnsafeArenaAddAllocatedToRepeatedField)1126 TEST(ArenaTest, UnsafeArenaAddAllocatedToRepeatedField) {
1127 // Heap->arena case.
1128 Arena arena1;
1129 TestAllTypes* arena1_message = Arena::Create<TestAllTypes>(&arena1);
1130 {
1131 auto* heap_submessage = new TestAllTypes::NestedMessage;
1132 arena1_message->mutable_repeated_nested_message()->UnsafeArenaAddAllocated(
1133 heap_submessage);
1134 // Should not copy object.
1135 EXPECT_EQ(heap_submessage, &arena1_message->repeated_nested_message(0));
1136 EXPECT_EQ(heap_submessage, arena1_message->mutable_repeated_nested_message()
1137 ->UnsafeArenaReleaseLast());
1138 delete heap_submessage;
1139 }
1140
1141 // Arena1->Arena2 case.
1142 arena1_message->Clear();
1143 {
1144 Arena arena2;
1145 TestAllTypes::NestedMessage* arena2_submessage =
1146 Arena::Create<TestAllTypes::NestedMessage>(&arena2);
1147 arena2_submessage->set_bb(42);
1148 arena1_message->mutable_repeated_nested_message()->UnsafeArenaAddAllocated(
1149 arena2_submessage);
1150 // Should own object.
1151 EXPECT_EQ(arena2_submessage, &arena1_message->repeated_nested_message(0));
1152 EXPECT_EQ(arena2_submessage,
1153 arena1_message->mutable_repeated_nested_message()
1154 ->UnsafeArenaReleaseLast());
1155 }
1156
1157 // Arena->heap case.
1158 TestAllTypes* heap_message = new TestAllTypes;
1159 {
1160 Arena arena2;
1161 TestAllTypes::NestedMessage* arena2_submessage =
1162 Arena::Create<TestAllTypes::NestedMessage>(&arena2);
1163 arena2_submessage->set_bb(42);
1164 heap_message->mutable_repeated_nested_message()->UnsafeArenaAddAllocated(
1165 arena2_submessage);
1166 // Should own object.
1167 EXPECT_EQ(arena2_submessage, &heap_message->repeated_nested_message(0));
1168 EXPECT_EQ(arena2_submessage, heap_message->mutable_repeated_nested_message()
1169 ->UnsafeArenaReleaseLast());
1170 }
1171 delete heap_message;
1172
1173 // Heap->arena case for strings (which are not arena-allocated).
1174 arena1_message->Clear();
1175 {
1176 std::string* s = new std::string("Test");
1177 arena1_message->mutable_repeated_string()->UnsafeArenaAddAllocated(s);
1178 // Should not copy.
1179 EXPECT_EQ(s, &arena1_message->repeated_string(0));
1180 EXPECT_EQ("Test", arena1_message->repeated_string(0));
1181 delete arena1_message->mutable_repeated_string()->UnsafeArenaReleaseLast();
1182 }
1183 }
1184
TEST(ArenaTest,AddAllocatedToRepeatedFieldViaReflection)1185 TEST(ArenaTest, AddAllocatedToRepeatedFieldViaReflection) {
1186 // Heap->arena case.
1187 Arena arena1;
1188 TestAllTypes* arena1_message = Arena::Create<TestAllTypes>(&arena1);
1189 const Reflection* r = arena1_message->GetReflection();
1190 const Descriptor* d = arena1_message->GetDescriptor();
1191 const FieldDescriptor* fd = d->FindFieldByName("repeated_nested_message");
1192 for (int i = 0; i < 10; i++) {
1193 TestAllTypes::NestedMessage* heap_submessage =
1194 new TestAllTypes::NestedMessage;
1195 heap_submessage->set_bb(42);
1196 r->AddAllocatedMessage(arena1_message, fd, heap_submessage);
1197 // Should not copy object -- will use arena_->Own().
1198 EXPECT_EQ(heap_submessage, &arena1_message->repeated_nested_message(i));
1199 EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
1200 }
1201
1202 // Arena1->Arena2 case.
1203 arena1_message->Clear();
1204 for (int i = 0; i < 10; i++) {
1205 Arena arena2;
1206 TestAllTypes::NestedMessage* arena2_submessage =
1207 Arena::Create<TestAllTypes::NestedMessage>(&arena2);
1208 arena2_submessage->set_bb(42);
1209 r->AddAllocatedMessage(arena1_message, fd, arena2_submessage);
1210 ASSERT_THAT(arena1_message->repeated_nested_message(), testing::SizeIs(1));
1211 EXPECT_EQ(
1212 arena1_message->mutable_repeated_nested_message()->at(0).GetArena(),
1213 &arena1);
1214 arena1_message->clear_repeated_nested_message();
1215 }
1216
1217 // Arena->heap case.
1218 TestAllTypes* heap_message = new TestAllTypes;
1219 for (int i = 0; i < 10; i++) {
1220 Arena arena2;
1221 TestAllTypes::NestedMessage* arena2_submessage =
1222 Arena::Create<TestAllTypes::NestedMessage>(&arena2);
1223 arena2_submessage->set_bb(42);
1224 r->AddAllocatedMessage(heap_message, fd, arena2_submessage);
1225 ASSERT_THAT(heap_message->repeated_nested_message(), testing::SizeIs(1));
1226 EXPECT_EQ(heap_message->mutable_repeated_nested_message()->at(0).GetArena(),
1227 nullptr);
1228 heap_message->clear_repeated_nested_message();
1229 }
1230 delete heap_message;
1231 }
1232
TEST(ArenaTest,ReleaseLastRepeatedField)1233 TEST(ArenaTest, ReleaseLastRepeatedField) {
1234 // Release from arena-allocated repeated field and ensure that returned object
1235 // is heap-allocated.
1236 Arena arena;
1237 TestAllTypes* arena_message = Arena::Create<TestAllTypes>(&arena);
1238 for (int i = 0; i < 10; i++) {
1239 TestAllTypes::NestedMessage* nested =
1240 Arena::Create<TestAllTypes::NestedMessage>(&arena);
1241 nested->set_bb(42);
1242 arena_message->mutable_repeated_nested_message()->AddAllocated(nested);
1243 }
1244
1245 for (int i = 0; i < 10; i++) {
1246 const TestAllTypes::NestedMessage* orig_submessage =
1247 &arena_message->repeated_nested_message(10 - 1 - i); // last element
1248 TestAllTypes::NestedMessage* released =
1249 arena_message->mutable_repeated_nested_message()->ReleaseLast();
1250 EXPECT_NE(released, orig_submessage);
1251 EXPECT_EQ(42, released->bb());
1252 delete released;
1253 }
1254
1255 // Test UnsafeArenaReleaseLast().
1256 for (int i = 0; i < 10; i++) {
1257 TestAllTypes::NestedMessage* nested =
1258 Arena::Create<TestAllTypes::NestedMessage>(&arena);
1259 nested->set_bb(42);
1260 arena_message->mutable_repeated_nested_message()->AddAllocated(nested);
1261 }
1262
1263 for (int i = 0; i < 10; i++) {
1264 const TestAllTypes::NestedMessage* orig_submessage =
1265 &arena_message->repeated_nested_message(10 - 1 - i); // last element
1266 TestAllTypes::NestedMessage* released =
1267 arena_message->mutable_repeated_nested_message()
1268 ->UnsafeArenaReleaseLast();
1269 EXPECT_EQ(released, orig_submessage);
1270 EXPECT_EQ(42, released->bb());
1271 // no delete -- |released| is on the arena.
1272 }
1273
1274 // Test string case as well. ReleaseLast() in this case must copy the
1275 // string, even though it was originally heap-allocated and its pointer
1276 // was simply appended to the repeated field's internal vector, because the
1277 // string was placed on the arena's destructor list and cannot be removed
1278 // from that list (so the arena permanently owns the original instance).
1279 arena_message->Clear();
1280 for (int i = 0; i < 10; i++) {
1281 std::string* s = new std::string("Test");
1282 arena_message->mutable_repeated_string()->AddAllocated(s);
1283 }
1284 for (int i = 0; i < 10; i++) {
1285 const std::string* orig_element =
1286 &arena_message->repeated_string(10 - 1 - i);
1287 std::string* released =
1288 arena_message->mutable_repeated_string()->ReleaseLast();
1289 EXPECT_NE(released, orig_element);
1290 EXPECT_EQ("Test", *released);
1291 delete released;
1292 }
1293 }
1294
TEST(ArenaTest,UnsafeArenaAddAllocated)1295 TEST(ArenaTest, UnsafeArenaAddAllocated) {
1296 Arena arena;
1297 TestAllTypes* message = Arena::Create<TestAllTypes>(&arena);
1298 for (int i = 0; i < 10; i++) {
1299 std::string* arena_string = Arena::Create<std::string>(&arena);
1300 message->mutable_repeated_string()->UnsafeArenaAddAllocated(arena_string);
1301 EXPECT_EQ(arena_string, message->mutable_repeated_string(i));
1302 }
1303 }
1304
TEST(ArenaTest,OneofMerge)1305 TEST(ArenaTest, OneofMerge) {
1306 Arena arena;
1307 TestAllTypes* message0 = Arena::Create<TestAllTypes>(&arena);
1308 TestAllTypes* message1 = Arena::Create<TestAllTypes>(&arena);
1309
1310 message0->set_oneof_string("x");
1311 ASSERT_TRUE(message0->has_oneof_string());
1312 message1->set_oneof_string("y");
1313 ASSERT_TRUE(message1->has_oneof_string());
1314 EXPECT_EQ("x", message0->oneof_string());
1315 EXPECT_EQ("y", message1->oneof_string());
1316 message0->MergeFrom(*message1);
1317 EXPECT_EQ("y", message0->oneof_string());
1318 EXPECT_EQ("y", message1->oneof_string());
1319 }
1320
TEST(ArenaTest,ArenaOneofReflection)1321 TEST(ArenaTest, ArenaOneofReflection) {
1322 Arena arena;
1323 TestAllTypes* message = Arena::Create<TestAllTypes>(&arena);
1324 const Descriptor* desc = message->GetDescriptor();
1325 const Reflection* refl = message->GetReflection();
1326
1327 const FieldDescriptor* string_field = desc->FindFieldByName("oneof_string");
1328 const FieldDescriptor* msg_field =
1329 desc->FindFieldByName("oneof_nested_message");
1330 const OneofDescriptor* oneof = desc->FindOneofByName("oneof_field");
1331
1332 refl->SetString(message, string_field, "Test value");
1333 EXPECT_TRUE(refl->HasOneof(*message, oneof));
1334 refl->ClearOneof(message, oneof);
1335 EXPECT_FALSE(refl->HasOneof(*message, oneof));
1336
1337 Message* submsg = refl->MutableMessage(message, msg_field);
1338 EXPECT_TRUE(refl->HasOneof(*message, oneof));
1339 refl->ClearOneof(message, oneof);
1340 EXPECT_FALSE(refl->HasOneof(*message, oneof));
1341 refl->MutableMessage(message, msg_field);
1342 EXPECT_TRUE(refl->HasOneof(*message, oneof));
1343 submsg = refl->ReleaseMessage(message, msg_field);
1344 EXPECT_FALSE(refl->HasOneof(*message, oneof));
1345 EXPECT_TRUE(submsg->GetArena() == nullptr);
1346 delete submsg;
1347 }
1348
TestSwapRepeatedField(Arena * arena1,Arena * arena2)1349 void TestSwapRepeatedField(Arena* arena1, Arena* arena2) {
1350 // Test "safe" (copying) semantics for direct Swap() on RepeatedPtrField
1351 // between arenas.
1352 RepeatedPtrField<TestAllTypes> field1(arena1);
1353 RepeatedPtrField<TestAllTypes> field2(arena2);
1354 for (int i = 0; i < 10; i++) {
1355 TestAllTypes* t = Arena::Create<TestAllTypes>(arena1);
1356 t->set_optional_string("field1");
1357 t->set_optional_int32(i);
1358 if (arena1 != nullptr) {
1359 field1.UnsafeArenaAddAllocated(t);
1360 } else {
1361 field1.AddAllocated(t);
1362 }
1363 }
1364 for (int i = 0; i < 5; i++) {
1365 TestAllTypes* t = Arena::Create<TestAllTypes>(arena2);
1366 t->set_optional_string("field2");
1367 t->set_optional_int32(i);
1368 if (arena2 != nullptr) {
1369 field2.UnsafeArenaAddAllocated(t);
1370 } else {
1371 field2.AddAllocated(t);
1372 }
1373 }
1374 field1.Swap(&field2);
1375 EXPECT_EQ(5, field1.size());
1376 EXPECT_EQ(10, field2.size());
1377 EXPECT_TRUE(std::string("field1") == field2.Get(0).optional_string());
1378 EXPECT_TRUE(std::string("field2") == field1.Get(0).optional_string());
1379 // Ensure that fields retained their original order:
1380 for (int i = 0; i < field1.size(); i++) {
1381 EXPECT_EQ(i, field1.Get(i).optional_int32());
1382 }
1383 for (int i = 0; i < field2.size(); i++) {
1384 EXPECT_EQ(i, field2.Get(i).optional_int32());
1385 }
1386 }
1387
TEST(ArenaTest,SwapRepeatedField)1388 TEST(ArenaTest, SwapRepeatedField) {
1389 Arena arena;
1390 TestSwapRepeatedField(&arena, &arena);
1391 }
1392
TEST(ArenaTest,SwapRepeatedFieldWithDifferentArenas)1393 TEST(ArenaTest, SwapRepeatedFieldWithDifferentArenas) {
1394 Arena arena1;
1395 Arena arena2;
1396 TestSwapRepeatedField(&arena1, &arena2);
1397 }
1398
TEST(ArenaTest,SwapRepeatedFieldWithNoArenaOnRightHandSide)1399 TEST(ArenaTest, SwapRepeatedFieldWithNoArenaOnRightHandSide) {
1400 Arena arena;
1401 TestSwapRepeatedField(&arena, nullptr);
1402 }
1403
TEST(ArenaTest,SwapRepeatedFieldWithNoArenaOnLeftHandSide)1404 TEST(ArenaTest, SwapRepeatedFieldWithNoArenaOnLeftHandSide) {
1405 Arena arena;
1406 TestSwapRepeatedField(nullptr, &arena);
1407 }
1408
TEST(ArenaTest,ExtensionsOnArena)1409 TEST(ArenaTest, ExtensionsOnArena) {
1410 Arena arena;
1411 // Ensure no leaks.
1412 TestAllExtensions* message_ext = Arena::Create<TestAllExtensions>(&arena);
1413 message_ext->SetExtension(protobuf_unittest::optional_int32_extension, 42);
1414 message_ext->SetExtension(protobuf_unittest::optional_string_extension,
1415 std::string("test"));
1416 message_ext
1417 ->MutableExtension(protobuf_unittest::optional_nested_message_extension)
1418 ->set_bb(42);
1419 }
1420
TEST(ArenaTest,RepeatedFieldOnArena)1421 TEST(ArenaTest, RepeatedFieldOnArena) {
1422 // Preallocate an initial arena block to avoid mallocs during hooked region.
1423 std::vector<char> arena_block(1024 * 1024);
1424 Arena arena(arena_block.data(), arena_block.size());
1425 const size_t initial_allocated_size = arena.SpaceAllocated();
1426
1427 {
1428 // Fill some repeated fields on the arena to test for leaks. Also that the
1429 // newly allocated memory is approximately the size of the cleanups for the
1430 // repeated messages.
1431 RepeatedField<int32_t> repeated_int32(&arena);
1432 RepeatedPtrField<TestAllTypes> repeated_message(&arena);
1433 for (int i = 0; i < 100; i++) {
1434 repeated_int32.Add(42);
1435 repeated_message.Add()->set_optional_int32(42);
1436 EXPECT_EQ(&arena, repeated_message.Get(0).GetArena());
1437 const TestAllTypes* msg_in_repeated_field = &repeated_message.Get(0);
1438 TestAllTypes* msg = repeated_message.UnsafeArenaReleaseLast();
1439 EXPECT_EQ(msg_in_repeated_field, msg);
1440 }
1441
1442 // UnsafeArenaExtractSubrange (i) should not leak and (ii) should return
1443 // on-arena pointers.
1444 for (int i = 0; i < 10; i++) {
1445 repeated_message.Add()->set_optional_int32(42);
1446 }
1447 TestAllTypes* extracted_messages[5];
1448 repeated_message.UnsafeArenaExtractSubrange(0, 5, extracted_messages);
1449 EXPECT_EQ(&arena, repeated_message.Get(0).GetArena());
1450 EXPECT_EQ(5, repeated_message.size());
1451 // Upper bound of the size of the cleanups of new repeated messages.
1452 const size_t upperbound_cleanup_size =
1453 2 * 110 * sizeof(internal::cleanup::CleanupNode);
1454 EXPECT_GT(initial_allocated_size + upperbound_cleanup_size,
1455 arena.SpaceAllocated());
1456 }
1457
1458 // Now test ExtractSubrange's copying semantics.
1459 {
1460 RepeatedPtrField<TestAllTypes> repeated_message(&arena);
1461 for (int i = 0; i < 100; i++) {
1462 repeated_message.Add()->set_optional_int32(42);
1463 }
1464
1465 TestAllTypes* extracted_messages[5];
1466 // ExtractSubrange should copy to the heap.
1467 repeated_message.ExtractSubrange(0, 5, extracted_messages);
1468 EXPECT_EQ(nullptr, extracted_messages[0]->GetArena());
1469 // We need to free the heap-allocated messages to prevent a leak.
1470 for (int i = 0; i < 5; i++) {
1471 delete extracted_messages[i];
1472 extracted_messages[i] = nullptr;
1473 }
1474 }
1475
1476 // Now check that we can create RepeatedFields/RepeatedPtrFields themselves on
1477 // the arena. They have the necessary type traits so that they can behave like
1478 // messages in this way. This is useful for higher-level generic templated
1479 // code that may allocate messages or repeated fields of messages on an arena.
1480 {
1481 RepeatedPtrField<TestAllTypes>* repeated_ptr_on_arena =
1482 Arena::Create<RepeatedPtrField<TestAllTypes>>(&arena);
1483 for (int i = 0; i < 10; i++) {
1484 // Add some elements and let the leak-checker ensure that everything is
1485 // freed.
1486 repeated_ptr_on_arena->Add();
1487 }
1488
1489 RepeatedField<int>* repeated_int_on_arena =
1490 Arena::Create<RepeatedField<int>>(&arena);
1491 for (int i = 0; i < 100; i++) {
1492 repeated_int_on_arena->Add(i);
1493 }
1494
1495 }
1496
1497 arena.Reset();
1498 }
1499
1500
1501 #if PROTOBUF_RTTI
TEST(ArenaTest,MutableMessageReflection)1502 TEST(ArenaTest, MutableMessageReflection) {
1503 Arena arena;
1504 TestAllTypes* message = Arena::Create<TestAllTypes>(&arena);
1505 const Reflection* r = message->GetReflection();
1506 const Descriptor* d = message->GetDescriptor();
1507 const FieldDescriptor* field = d->FindFieldByName("optional_nested_message");
1508 TestAllTypes::NestedMessage* submessage =
1509 DownCastMessage<TestAllTypes::NestedMessage>(
1510 r->MutableMessage(message, field));
1511 TestAllTypes::NestedMessage* submessage_expected =
1512 message->mutable_optional_nested_message();
1513
1514 EXPECT_EQ(submessage_expected, submessage);
1515 EXPECT_EQ(&arena, submessage->GetArena());
1516
1517 const FieldDescriptor* oneof_field =
1518 d->FindFieldByName("oneof_nested_message");
1519 submessage = DownCastMessage<TestAllTypes::NestedMessage>(
1520 r->MutableMessage(message, oneof_field));
1521 submessage_expected = message->mutable_oneof_nested_message();
1522
1523 EXPECT_EQ(submessage_expected, submessage);
1524 EXPECT_EQ(&arena, submessage->GetArena());
1525 }
1526 #endif // PROTOBUF_RTTI
1527
1528
TEST(ArenaTest,ClearOneofMessageOnArena)1529 TEST(ArenaTest, ClearOneofMessageOnArena) {
1530 if (!internal::DebugHardenClearOneofMessageOnArena()) {
1531 GTEST_SKIP() << "arena allocated oneof message fields are not hardened.";
1532 }
1533
1534 Arena arena;
1535 auto* message = Arena::Create<unittest::TestOneof2>(&arena);
1536 // Intentionally nested to force poisoning recursively to catch the access.
1537 auto* child =
1538 message->mutable_foo_message()->mutable_child()->mutable_child();
1539 child->set_moo_int(100);
1540 message->clear_foo_message();
1541
1542 #ifndef PROTOBUF_ASAN
1543 EXPECT_NE(child->moo_int(), 100);
1544 #else
1545 #if GTEST_HAS_DEATH_TEST && defined(__cpp_if_constexpr)
1546 EXPECT_DEATH(EXPECT_EQ(child->moo_int(), 0), "use-after-poison");
1547 #endif
1548 #endif
1549 }
1550
TEST(ArenaTest,CopyValuesWithinOneof)1551 TEST(ArenaTest, CopyValuesWithinOneof) {
1552 if (!internal::DebugHardenClearOneofMessageOnArena()) {
1553 GTEST_SKIP() << "arena allocated oneof message fields are not hardened.";
1554 }
1555
1556 Arena arena;
1557 auto* message = Arena::Create<unittest::TestOneof>(&arena);
1558 auto* foo = message->mutable_foogroup();
1559 foo->set_a(100);
1560 foo->set_b("hello world");
1561 message->set_foo_string(message->foogroup().b());
1562
1563 // As a debug hardening measure, `set_foo_string` would clear `foo` in
1564 // (!NDEBUG && !ASAN) and the copy wouldn't work.
1565 EXPECT_TRUE(message->foo_string().empty()) << message->foo_string();
1566 }
1567
FillArenaAwareFields(TestAllTypes * message)1568 void FillArenaAwareFields(TestAllTypes* message) {
1569 std::string test_string = "hello world";
1570 message->set_optional_int32(42);
1571 message->set_optional_string(test_string);
1572 message->set_optional_bytes(test_string);
1573 message->mutable_optional_nested_message()->set_bb(42);
1574
1575 message->set_oneof_uint32(42);
1576 message->mutable_oneof_nested_message()->set_bb(42);
1577 message->set_oneof_string(test_string);
1578 message->set_oneof_bytes(test_string);
1579
1580 message->add_repeated_int32(42);
1581 // No repeated string: not yet arena-aware.
1582 message->add_repeated_nested_message()->set_bb(42);
1583 message->mutable_optional_lazy_message()->set_bb(42);
1584 }
1585
1586 // Test: no allocations occur on heap while touching all supported field types.
TEST(ArenaTest,NoHeapAllocationsTest)1587 TEST(ArenaTest, NoHeapAllocationsTest) {
1588 if (internal::DebugHardenClearOneofMessageOnArena()) {
1589 GTEST_SKIP() << "debug hardening may cause heap allocation.";
1590 }
1591
1592 // Allocate a large initial block to avoid mallocs during hooked test.
1593 std::vector<char> arena_block(128 * 1024);
1594 ArenaOptions options;
1595 options.initial_block = &arena_block[0];
1596 options.initial_block_size = arena_block.size();
1597 Arena arena(options);
1598
1599 {
1600 // We need to call Arena::Create before NoHeapChecker because the ArenaDtor
1601 // allocates a new cleanup chunk.
1602 TestAllTypes* message = Arena::Create<TestAllTypes>(&arena);
1603
1604
1605 FillArenaAwareFields(message);
1606 }
1607
1608 arena.Reset();
1609 }
1610
1611 #if PROTOBUF_RTTI
1612 // Test construction on an arena via generic MessageLite interface. We should be
1613 // able to successfully deserialize on the arena without incurring heap
1614 // allocations, i.e., everything should still be arena-allocation-aware.
TEST(ArenaTest,MessageLiteOnArena)1615 TEST(ArenaTest, MessageLiteOnArena) {
1616 std::vector<char> arena_block(128 * 1024);
1617 ArenaOptions options;
1618 options.initial_block = &arena_block[0];
1619 options.initial_block_size = arena_block.size();
1620 Arena arena(options);
1621 const MessageLite* prototype = &TestAllTypes::default_instance();
1622
1623 TestAllTypes initial_message;
1624 FillArenaAwareFields(&initial_message);
1625 std::string serialized;
1626 initial_message.SerializeToString(&serialized);
1627
1628 {
1629 MessageLite* generic_message = prototype->New(&arena);
1630
1631
1632 EXPECT_TRUE(generic_message != nullptr);
1633 EXPECT_EQ(&arena, generic_message->GetArena());
1634 EXPECT_TRUE(generic_message->ParseFromString(serialized));
1635 TestAllTypes* deserialized = static_cast<TestAllTypes*>(generic_message);
1636 EXPECT_EQ(42, deserialized->optional_int32());
1637 }
1638
1639 arena.Reset();
1640 }
1641 #endif // PROTOBUF_RTTI
1642
1643 // Align n to next multiple of 8
Align8(uint64_t n)1644 uint64_t Align8(uint64_t n) { return (n + 7) & -8; }
1645
TEST(ArenaTest,SpaceAllocated_and_Used)1646 TEST(ArenaTest, SpaceAllocated_and_Used) {
1647 Arena arena_1;
1648 EXPECT_EQ(0, arena_1.SpaceAllocated());
1649 EXPECT_EQ(0, arena_1.SpaceUsed());
1650 EXPECT_EQ(0, arena_1.Reset());
1651 Arena::CreateArray<char>(&arena_1, 320);
1652 // Arena will allocate slightly more than 320 for the block headers.
1653 EXPECT_LE(320, arena_1.SpaceAllocated());
1654 EXPECT_EQ(Align8(320), arena_1.SpaceUsed());
1655 EXPECT_LE(320, arena_1.Reset());
1656
1657 // Test with initial block.
1658 std::vector<char> arena_block(1024);
1659 ArenaOptions options;
1660 options.start_block_size = 256;
1661 options.max_block_size = 8192;
1662 options.initial_block = &arena_block[0];
1663 options.initial_block_size = arena_block.size();
1664 Arena arena_2(options);
1665 EXPECT_EQ(1024, arena_2.SpaceAllocated());
1666 EXPECT_EQ(0, arena_2.SpaceUsed());
1667 EXPECT_EQ(1024, arena_2.Reset());
1668 Arena::CreateArray<char>(&arena_2, 55);
1669 EXPECT_EQ(1024, arena_2.SpaceAllocated());
1670 EXPECT_EQ(Align8(55), arena_2.SpaceUsed());
1671 EXPECT_EQ(1024, arena_2.Reset());
1672 }
1673
1674 namespace {
1675
VerifyArenaOverhead(Arena & arena,size_t overhead)1676 void VerifyArenaOverhead(Arena& arena, size_t overhead) {
1677 EXPECT_EQ(0, arena.SpaceAllocated());
1678
1679 // Allocate a tiny block and record the allocation size.
1680 constexpr size_t kTinySize = 8;
1681 Arena::CreateArray<char>(&arena, kTinySize);
1682 uint64_t space_allocated = arena.SpaceAllocated();
1683
1684 // Next allocation expects to fill up the block but no new block.
1685 uint64_t next_size = space_allocated - overhead - kTinySize;
1686 Arena::CreateArray<char>(&arena, next_size);
1687
1688 EXPECT_EQ(space_allocated, arena.SpaceAllocated());
1689 }
1690
1691 } // namespace
1692
TEST(ArenaTest,FirstArenaOverhead)1693 TEST(ArenaTest, FirstArenaOverhead) {
1694 Arena arena;
1695 VerifyArenaOverhead(arena, internal::SerialArena::kBlockHeaderSize);
1696 }
1697
1698
TEST(ArenaTest,StartingBlockSize)1699 TEST(ArenaTest, StartingBlockSize) {
1700 Arena default_arena;
1701 EXPECT_EQ(0, default_arena.SpaceAllocated());
1702
1703 // Allocate something to get starting block size.
1704 Arena::CreateArray<char>(&default_arena, 1);
1705 ArenaOptions options;
1706 // First block size should be the default starting block size.
1707 EXPECT_EQ(default_arena.SpaceAllocated(), options.start_block_size);
1708
1709 // Use a custom starting block size.
1710 options.start_block_size *= 2;
1711 Arena custom_arena(options);
1712 Arena::CreateArray<char>(&custom_arena, 1);
1713 EXPECT_EQ(custom_arena.SpaceAllocated(), options.start_block_size);
1714 }
1715
TEST(ArenaTest,BlockSizeDoubling)1716 TEST(ArenaTest, BlockSizeDoubling) {
1717 Arena arena;
1718 EXPECT_EQ(0, arena.SpaceUsed());
1719 EXPECT_EQ(0, arena.SpaceAllocated());
1720
1721 // Allocate something to get initial block size.
1722 Arena::CreateArray<char>(&arena, 1);
1723 auto first_block_size = arena.SpaceAllocated();
1724
1725 // Keep allocating until space used increases.
1726 while (arena.SpaceAllocated() == first_block_size) {
1727 Arena::CreateArray<char>(&arena, 1);
1728 }
1729 ASSERT_GT(arena.SpaceAllocated(), first_block_size);
1730 auto second_block_size = (arena.SpaceAllocated() - first_block_size);
1731
1732 EXPECT_GE(second_block_size, 2*first_block_size);
1733 }
1734
TEST(ArenaTest,Alignment)1735 TEST(ArenaTest, Alignment) {
1736 Arena arena;
1737 for (int i = 0; i < 200; i++) {
1738 void* p = Arena::CreateArray<char>(&arena, i);
1739 ABSL_CHECK_EQ(reinterpret_cast<uintptr_t>(p) % 8, 0u) << i << ": " << p;
1740 }
1741 }
1742
TEST(ArenaTest,BlockSizeSmallerThanAllocation)1743 TEST(ArenaTest, BlockSizeSmallerThanAllocation) {
1744 for (size_t i = 0; i <= 8; ++i) {
1745 ArenaOptions opt;
1746 opt.start_block_size = opt.max_block_size = i;
1747 Arena arena(opt);
1748
1749 *Arena::Create<int64_t>(&arena) = 42;
1750 EXPECT_GE(arena.SpaceAllocated(), 8);
1751 EXPECT_EQ(8, arena.SpaceUsed());
1752
1753 *Arena::Create<int64_t>(&arena) = 42;
1754 EXPECT_GE(arena.SpaceAllocated(), 16);
1755 EXPECT_EQ(16, arena.SpaceUsed());
1756 }
1757 }
1758
TEST(ArenaTest,GetArenaShouldReturnTheArenaForArenaAllocatedMessages)1759 TEST(ArenaTest, GetArenaShouldReturnTheArenaForArenaAllocatedMessages) {
1760 Arena arena;
1761 ArenaMessage* message = Arena::Create<ArenaMessage>(&arena);
1762 const ArenaMessage* const_pointer_to_message = message;
1763 EXPECT_EQ(&arena, message->GetArena());
1764 EXPECT_EQ(&arena, const_pointer_to_message->GetArena());
1765
1766 // Test that the Message* / MessageLite* specialization SFINAE works.
1767 const Message* const_pointer_to_message_type = message;
1768 EXPECT_EQ(&arena, const_pointer_to_message_type->GetArena());
1769 const MessageLite* const_pointer_to_message_lite_type = message;
1770 EXPECT_EQ(&arena, const_pointer_to_message_lite_type->GetArena());
1771 }
1772
TEST(ArenaTest,GetArenaShouldReturnNullForNonArenaAllocatedMessages)1773 TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) {
1774 ArenaMessage message;
1775 const ArenaMessage* const_pointer_to_message = &message;
1776 EXPECT_EQ(nullptr, message.GetArena());
1777 EXPECT_EQ(nullptr, const_pointer_to_message->GetArena());
1778 }
1779
TEST(ArenaTest,AddCleanup)1780 TEST(ArenaTest, AddCleanup) {
1781 Arena arena;
1782 for (int i = 0; i < 100; i++) {
1783 arena.Own(new int);
1784 }
1785 }
1786
1787 struct DestroyOrderRecorder {
1788 std::vector<int>* destroy_order;
1789 int i;
1790
DestroyOrderRecordergoogle::protobuf::DestroyOrderRecorder1791 DestroyOrderRecorder(std::vector<int>* destroy_order, int i)
1792 : destroy_order(destroy_order), i(i) {}
~DestroyOrderRecordergoogle::protobuf::DestroyOrderRecorder1793 ~DestroyOrderRecorder() { destroy_order->push_back(i); }
1794 };
1795
1796 // TODO: we do not guarantee this behavior, but some users rely on
1797 // it. We need to decide whether we want to guarantee this. In the meantime,
1798 // user code should avoid adding new dependencies on this.
1799 // Tests that when using an Arena from a single thread, objects are destroyed in
1800 // reverse order from construction.
TEST(ArenaTest,CleanupDestructionOrder)1801 TEST(ArenaTest, CleanupDestructionOrder) {
1802 std::vector<int> destroy_order;
1803 {
1804 Arena arena;
1805 for (int i = 0; i < 3; i++) {
1806 Arena::Create<DestroyOrderRecorder>(&arena, &destroy_order, i);
1807 }
1808 }
1809 EXPECT_THAT(destroy_order, testing::ElementsAre(2, 1, 0));
1810 }
1811
TEST(ArenaTest,SpaceReuseForArraysSizeChecks)1812 TEST(ArenaTest, SpaceReuseForArraysSizeChecks) {
1813 // Limit to 1<<20 to avoid using too much memory on the test.
1814 for (int i = 0; i < 20; ++i) {
1815 SCOPED_TRACE(i);
1816 Arena arena;
1817 std::vector<void*> pointers;
1818
1819 const size_t size = 16 << i;
1820
1821 for (int j = 0; j < 10; ++j) {
1822 pointers.push_back(Arena::CreateArray<char>(&arena, size));
1823 }
1824
1825 for (void* p : pointers) {
1826 internal::ArenaTestPeer::ReturnArrayMemory(&arena, p, size);
1827 }
1828
1829 std::vector<void*> second_pointers;
1830 for (int j = 9; j != 0; --j) {
1831 second_pointers.push_back(Arena::CreateArray<char>(&arena, size));
1832 }
1833
1834 // The arena will give us back the pointers we returned, except the first
1835 // one. That one becomes part of the freelist data structure.
1836 ASSERT_THAT(second_pointers,
1837 testing::UnorderedElementsAreArray(
1838 std::vector<void*>(pointers.begin() + 1, pointers.end())));
1839 }
1840 }
1841
TEST(ArenaTest,SpaceReusePoisonsAndUnpoisonsMemory)1842 TEST(ArenaTest, SpaceReusePoisonsAndUnpoisonsMemory) {
1843 #ifdef PROTOBUF_ASAN
1844 char buf[1024]{};
1845 constexpr int kSize = 32;
1846 {
1847 Arena arena(buf, sizeof(buf));
1848 std::vector<void*> pointers;
1849 for (int i = 0; i < 100; ++i) {
1850 void* p = Arena::CreateArray<char>(&arena, kSize);
1851 // Simulate other ASan client managing shadow memory.
1852 ASAN_POISON_MEMORY_REGION(p, kSize);
1853 ASAN_UNPOISON_MEMORY_REGION(p, kSize - 4);
1854 pointers.push_back(p);
1855 }
1856 for (void* p : pointers) {
1857 internal::ArenaTestPeer::ReturnArrayMemory(&arena, p, kSize);
1858 // The first one is not poisoned because it becomes the freelist.
1859 if (p != pointers[0]) EXPECT_TRUE(__asan_address_is_poisoned(p));
1860 }
1861
1862 bool found_poison = false;
1863 for (char& c : buf) {
1864 if (__asan_address_is_poisoned(&c)) {
1865 found_poison = true;
1866 break;
1867 }
1868 }
1869 EXPECT_TRUE(found_poison);
1870 }
1871
1872 // Should not be poisoned after destruction.
1873 for (char& c : buf) {
1874 ASSERT_FALSE(__asan_address_is_poisoned(&c));
1875 }
1876
1877 #else // PROTOBUF_ASAN
1878 GTEST_SKIP();
1879 #endif // PROTOBUF_ASAN
1880 }
1881
1882
1883 } // namespace protobuf
1884 } // namespace google
1885
1886 #include "google/protobuf/port_undef.inc"
1887