• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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