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/stubs/common.h"
9 #include <gtest/gtest.h>
10 #include "google/protobuf/test_util.h"
11 #include "google/protobuf/unittest.pb.h"
12
13 #if LANG_CXX11
14 #include <type_traits>
15 #endif
16
17 namespace google {
18 namespace protobuf {
19 namespace compiler {
20 namespace cpp {
21
22 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
23 namespace cpp_unittest {
24
25 // Moves are enabled only when compiling with a C++11 compiler or newer.
26 #if LANG_CXX11
27
TEST(MovableMessageTest,MoveConstructor)28 TEST(MovableMessageTest, MoveConstructor) {
29 protobuf_unittest::TestAllTypes message1;
30 TestUtil::SetAllFields(&message1);
31 const auto* nested = &message1.optional_nested_message();
32
33 protobuf_unittest::TestAllTypes message2(std::move(message1));
34 TestUtil::ExpectAllFieldsSet(message2);
35
36 // Check if the optional_nested_message was actually moved (and not just
37 // copied).
38 EXPECT_EQ(nested, &message2.optional_nested_message());
39 EXPECT_NE(nested, &message1.optional_nested_message());
40 }
41
TEST(MovableMessageTest,MoveAssignmentOperator)42 TEST(MovableMessageTest, MoveAssignmentOperator) {
43 protobuf_unittest::TestAllTypes message1;
44 TestUtil::SetAllFields(&message1);
45 const auto* nested = &message1.optional_nested_message();
46
47 protobuf_unittest::TestAllTypes message2;
48 message2 = std::move(message1);
49 TestUtil::ExpectAllFieldsSet(message2);
50
51 // Check if the optional_nested_message was actually moved (and not just
52 // copied).
53 EXPECT_EQ(nested, &message2.optional_nested_message());
54 EXPECT_NE(nested, &message1.optional_nested_message());
55 }
56
TEST(MovableMessageTest,SelfMoveAssignment)57 TEST(MovableMessageTest, SelfMoveAssignment) {
58 // The `self` reference is necessary to defeat -Wself-move.
59 protobuf_unittest::TestAllTypes message, &self = message;
60 TestUtil::SetAllFields(&message);
61 message = std::move(self);
62 TestUtil::ExpectAllFieldsSet(message);
63 }
64
TEST(MovableMessageTest,MoveSameArena)65 TEST(MovableMessageTest, MoveSameArena) {
66 Arena arena;
67
68 auto* message1_on_arena =
69 Arena::Create<protobuf_unittest::TestAllTypes>(&arena);
70 TestUtil::SetAllFields(message1_on_arena);
71 const auto* nested = &message1_on_arena->optional_nested_message();
72
73 auto* message2_on_arena =
74 Arena::Create<protobuf_unittest::TestAllTypes>(&arena);
75
76 // Moving messages on the same arena should lead to swapped pointers.
77 *message2_on_arena = std::move(*message1_on_arena);
78 EXPECT_EQ(nested, &message2_on_arena->optional_nested_message());
79 }
80
TEST(MovableMessageTest,MoveDifferentArenas)81 TEST(MovableMessageTest, MoveDifferentArenas) {
82 Arena arena1, arena2;
83
84 auto* message1_on_arena =
85 Arena::Create<protobuf_unittest::TestAllTypes>(&arena1);
86 TestUtil::SetAllFields(message1_on_arena);
87 const auto* nested = &message1_on_arena->optional_nested_message();
88
89 auto* message2_on_arena =
90 Arena::Create<protobuf_unittest::TestAllTypes>(&arena2);
91
92 // Moving messages on two different arenas should lead to a copy.
93 *message2_on_arena = std::move(*message1_on_arena);
94 EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
95 TestUtil::ExpectAllFieldsSet(*message1_on_arena);
96 TestUtil::ExpectAllFieldsSet(*message2_on_arena);
97 }
98
TEST(MovableMessageTest,MoveFromArena)99 TEST(MovableMessageTest, MoveFromArena) {
100 Arena arena;
101
102 auto* message1_on_arena =
103 Arena::Create<protobuf_unittest::TestAllTypes>(&arena);
104 TestUtil::SetAllFields(message1_on_arena);
105 const auto* nested = &message1_on_arena->optional_nested_message();
106
107 protobuf_unittest::TestAllTypes message2;
108
109 // Moving from a message on the arena should lead to a copy.
110 message2 = std::move(*message1_on_arena);
111 EXPECT_NE(nested, &message2.optional_nested_message());
112 TestUtil::ExpectAllFieldsSet(*message1_on_arena);
113 TestUtil::ExpectAllFieldsSet(message2);
114 }
115
TEST(MovableMessageTest,MoveToArena)116 TEST(MovableMessageTest, MoveToArena) {
117 Arena arena;
118
119 protobuf_unittest::TestAllTypes message1;
120 TestUtil::SetAllFields(&message1);
121 const auto* nested = &message1.optional_nested_message();
122
123 auto* message2_on_arena =
124 Arena::Create<protobuf_unittest::TestAllTypes>(&arena);
125
126 // Moving to a message on the arena should lead to a copy.
127 *message2_on_arena = std::move(message1);
128 EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
129 TestUtil::ExpectAllFieldsSet(message1);
130 TestUtil::ExpectAllFieldsSet(*message2_on_arena);
131 }
132
TEST(MovableMessageTest,Noexcept)133 TEST(MovableMessageTest, Noexcept) {
134 EXPECT_TRUE(
135 std::is_nothrow_move_constructible<protobuf_unittest::TestAllTypes>());
136 EXPECT_TRUE(std::is_nothrow_move_assignable<protobuf_unittest::TestAllTypes>());
137 }
138
139 #endif // LANG_CXX11
140
141 } // namespace cpp_unittest
142
143 } // namespace cpp
144 } // namespace compiler
145 } // namespace protobuf
146 } // namespace google
147