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