dynamic_message_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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. // Author: kenton@google.com (Kenton Varda)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. //
  34. // Since the reflection interface for DynamicMessage is implemented by
  35. // GenericMessageReflection, the only thing we really have to test is
  36. // that DynamicMessage correctly sets up the information that
  37. // GenericMessageReflection needs to use. So, we focus on that in this
  38. // test. Other tests, such as generic_message_reflection_unittest and
  39. // reflection_ops_unittest, cover the rest of the functionality used by
  40. // DynamicMessage.
  41. #include <memory>
  42. #include <google/protobuf/test_util.h>
  43. #include <google/protobuf/unittest.pb.h>
  44. #include <google/protobuf/unittest_no_field_presence.pb.h>
  45. #include <google/protobuf/descriptor.pb.h>
  46. #include <google/protobuf/descriptor.h>
  47. #include <google/protobuf/dynamic_message.h>
  48. #include <google/protobuf/stubs/logging.h>
  49. #include <google/protobuf/stubs/common.h>
  50. #include <google/protobuf/testing/googletest.h>
  51. #include <gtest/gtest.h>
  52. namespace google {
  53. namespace protobuf {
  54. class DynamicMessageTest : public ::testing::TestWithParam<bool> {
  55. protected:
  56. DescriptorPool pool_;
  57. DynamicMessageFactory factory_;
  58. const Descriptor* descriptor_;
  59. const Message* prototype_;
  60. const Descriptor* extensions_descriptor_;
  61. const Message* extensions_prototype_;
  62. const Descriptor* packed_descriptor_;
  63. const Message* packed_prototype_;
  64. const Descriptor* oneof_descriptor_;
  65. const Message* oneof_prototype_;
  66. const Descriptor* proto3_descriptor_;
  67. const Message* proto3_prototype_;
  68. DynamicMessageTest(): factory_(&pool_) {}
  69. virtual void SetUp() {
  70. // We want to make sure that DynamicMessage works (particularly with
  71. // extensions) even if we use descriptors that are *not* from compiled-in
  72. // types, so we make copies of the descriptors for unittest.proto and
  73. // unittest_import.proto.
  74. FileDescriptorProto unittest_file;
  75. FileDescriptorProto unittest_import_file;
  76. FileDescriptorProto unittest_import_public_file;
  77. FileDescriptorProto unittest_no_field_presence_file;
  78. unittest::TestAllTypes::descriptor()->file()->CopyTo(&unittest_file);
  79. unittest_import::ImportMessage::descriptor()->file()->CopyTo(
  80. &unittest_import_file);
  81. unittest_import::PublicImportMessage::descriptor()->file()->CopyTo(
  82. &unittest_import_public_file);
  83. proto2_nofieldpresence_unittest::TestAllTypes::descriptor()->
  84. file()->CopyTo(&unittest_no_field_presence_file);
  85. ASSERT_TRUE(pool_.BuildFile(unittest_import_public_file) != NULL);
  86. ASSERT_TRUE(pool_.BuildFile(unittest_import_file) != NULL);
  87. ASSERT_TRUE(pool_.BuildFile(unittest_file) != NULL);
  88. ASSERT_TRUE(pool_.BuildFile(unittest_no_field_presence_file) != NULL);
  89. descriptor_ = pool_.FindMessageTypeByName("protobuf_unittest.TestAllTypes");
  90. ASSERT_TRUE(descriptor_ != NULL);
  91. prototype_ = factory_.GetPrototype(descriptor_);
  92. extensions_descriptor_ =
  93. pool_.FindMessageTypeByName("protobuf_unittest.TestAllExtensions");
  94. ASSERT_TRUE(extensions_descriptor_ != NULL);
  95. extensions_prototype_ = factory_.GetPrototype(extensions_descriptor_);
  96. packed_descriptor_ =
  97. pool_.FindMessageTypeByName("protobuf_unittest.TestPackedTypes");
  98. ASSERT_TRUE(packed_descriptor_ != NULL);
  99. packed_prototype_ = factory_.GetPrototype(packed_descriptor_);
  100. oneof_descriptor_ =
  101. pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2");
  102. ASSERT_TRUE(oneof_descriptor_ != NULL);
  103. oneof_prototype_ = factory_.GetPrototype(oneof_descriptor_);
  104. proto3_descriptor_ =
  105. pool_.FindMessageTypeByName(
  106. "proto2_nofieldpresence_unittest.TestAllTypes");
  107. ASSERT_TRUE(proto3_descriptor_ != NULL);
  108. proto3_prototype_ = factory_.GetPrototype(proto3_descriptor_);
  109. }
  110. };
  111. TEST_F(DynamicMessageTest, Descriptor) {
  112. // Check that the descriptor on the DynamicMessage matches the descriptor
  113. // passed to GetPrototype().
  114. EXPECT_EQ(prototype_->GetDescriptor(), descriptor_);
  115. }
  116. TEST_F(DynamicMessageTest, OnePrototype) {
  117. // Check that requesting the same prototype twice produces the same object.
  118. EXPECT_EQ(prototype_, factory_.GetPrototype(descriptor_));
  119. }
  120. TEST_F(DynamicMessageTest, Defaults) {
  121. // Check that all default values are set correctly in the initial message.
  122. TestUtil::ReflectionTester reflection_tester(descriptor_);
  123. reflection_tester.ExpectClearViaReflection(*prototype_);
  124. }
  125. TEST_P(DynamicMessageTest, IndependentOffsets) {
  126. // Check that all fields have independent offsets by setting each
  127. // one to a unique value then checking that they all still have those
  128. // unique values (i.e. they don't stomp each other).
  129. Arena arena;
  130. Message* message = prototype_->New(GetParam()? &arena : NULL);
  131. TestUtil::ReflectionTester reflection_tester(descriptor_);
  132. reflection_tester.SetAllFieldsViaReflection(message);
  133. reflection_tester.ExpectAllFieldsSetViaReflection(*message);
  134. if (!GetParam()) {
  135. delete message;
  136. }
  137. }
  138. TEST_P(DynamicMessageTest, Extensions) {
  139. // Check that extensions work.
  140. Arena arena;
  141. Message* message = extensions_prototype_->New(GetParam()? &arena : NULL);
  142. TestUtil::ReflectionTester reflection_tester(extensions_descriptor_);
  143. reflection_tester.SetAllFieldsViaReflection(message);
  144. reflection_tester.ExpectAllFieldsSetViaReflection(*message);
  145. if (!GetParam()) {
  146. delete message;
  147. }
  148. }
  149. TEST_P(DynamicMessageTest, PackedFields) {
  150. // Check that packed fields work properly.
  151. Arena arena;
  152. Message* message = packed_prototype_->New(GetParam()? &arena : NULL);
  153. TestUtil::ReflectionTester reflection_tester(packed_descriptor_);
  154. reflection_tester.SetPackedFieldsViaReflection(message);
  155. reflection_tester.ExpectPackedFieldsSetViaReflection(*message);
  156. if (!GetParam()) {
  157. delete message;
  158. }
  159. }
  160. TEST_P(DynamicMessageTest, Oneof) {
  161. // Check that oneof fields work properly.
  162. Arena arena;
  163. Message* message = oneof_prototype_->New(GetParam()? &arena : NULL);
  164. // Check default values.
  165. const Descriptor* descriptor = message->GetDescriptor();
  166. const Reflection* reflection = message->GetReflection();
  167. EXPECT_EQ(0, reflection->GetInt32(
  168. *message, descriptor->FindFieldByName("foo_int")));
  169. EXPECT_EQ("", reflection->GetString(
  170. *message, descriptor->FindFieldByName("foo_string")));
  171. EXPECT_EQ("", reflection->GetString(
  172. *message, descriptor->FindFieldByName("foo_cord")));
  173. EXPECT_EQ("", reflection->GetString(
  174. *message, descriptor->FindFieldByName("foo_string_piece")));
  175. EXPECT_EQ("", reflection->GetString(
  176. *message, descriptor->FindFieldByName("foo_bytes")));
  177. EXPECT_EQ(unittest::TestOneof2::FOO, reflection->GetEnum(
  178. *message, descriptor->FindFieldByName("foo_enum"))->number());
  179. const Descriptor* nested_descriptor;
  180. const Message* nested_prototype;
  181. nested_descriptor =
  182. pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.NestedMessage");
  183. nested_prototype = factory_.GetPrototype(nested_descriptor);
  184. EXPECT_EQ(nested_prototype,
  185. &reflection->GetMessage(
  186. *message, descriptor->FindFieldByName("foo_message")));
  187. const Descriptor* foogroup_descriptor;
  188. const Message* foogroup_prototype;
  189. foogroup_descriptor =
  190. pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.FooGroup");
  191. foogroup_prototype = factory_.GetPrototype(foogroup_descriptor);
  192. EXPECT_EQ(foogroup_prototype,
  193. &reflection->GetMessage(
  194. *message, descriptor->FindFieldByName("foogroup")));
  195. EXPECT_NE(foogroup_prototype,
  196. &reflection->GetMessage(
  197. *message, descriptor->FindFieldByName("foo_lazy_message")));
  198. EXPECT_EQ(5, reflection->GetInt32(
  199. *message, descriptor->FindFieldByName("bar_int")));
  200. EXPECT_EQ("STRING", reflection->GetString(
  201. *message, descriptor->FindFieldByName("bar_string")));
  202. EXPECT_EQ("CORD", reflection->GetString(
  203. *message, descriptor->FindFieldByName("bar_cord")));
  204. EXPECT_EQ("SPIECE", reflection->GetString(
  205. *message, descriptor->FindFieldByName("bar_string_piece")));
  206. EXPECT_EQ("BYTES", reflection->GetString(
  207. *message, descriptor->FindFieldByName("bar_bytes")));
  208. EXPECT_EQ(unittest::TestOneof2::BAR, reflection->GetEnum(
  209. *message, descriptor->FindFieldByName("bar_enum"))->number());
  210. // Check set functions.
  211. TestUtil::ReflectionTester reflection_tester(oneof_descriptor_);
  212. reflection_tester.SetOneofViaReflection(message);
  213. reflection_tester.ExpectOneofSetViaReflection(*message);
  214. if (!GetParam()) {
  215. delete message;
  216. }
  217. }
  218. TEST_P(DynamicMessageTest, SpaceUsed) {
  219. // Test that SpaceUsed() works properly
  220. // Since we share the implementation with generated messages, we don't need
  221. // to test very much here. Just make sure it appears to be working.
  222. Arena arena;
  223. Message* message = prototype_->New(GetParam()? &arena : NULL);
  224. TestUtil::ReflectionTester reflection_tester(descriptor_);
  225. int initial_space_used = message->SpaceUsed();
  226. reflection_tester.SetAllFieldsViaReflection(message);
  227. EXPECT_LT(initial_space_used, message->SpaceUsed());
  228. if (!GetParam()) {
  229. delete message;
  230. }
  231. }
  232. TEST_F(DynamicMessageTest, Arena) {
  233. Arena arena;
  234. Message* message = prototype_->New(&arena);
  235. Message* extension_message = extensions_prototype_->New(&arena);
  236. Message* packed_message = packed_prototype_->New(&arena);
  237. Message* oneof_message = oneof_prototype_->New(&arena);
  238. // avoid unused-variable error.
  239. (void)message;
  240. (void)extension_message;
  241. (void)packed_message;
  242. (void)oneof_message;
  243. // Return without freeing: should not leak.
  244. }
  245. TEST_F(DynamicMessageTest, Proto3) {
  246. Message* message = proto3_prototype_->New();
  247. const Reflection* refl = message->GetReflection();
  248. const Descriptor* desc = message->GetDescriptor();
  249. // Just test a single primtive and single message field here to make sure we
  250. // are getting the no-field-presence semantics elsewhere. DynamicMessage uses
  251. // GeneratedMessageReflection under the hood, so the rest should be fine as
  252. // long as GMR recognizes that we're using a proto3 message.
  253. const FieldDescriptor* optional_int32 =
  254. desc->FindFieldByName("optional_int32");
  255. const FieldDescriptor* optional_msg =
  256. desc->FindFieldByName("optional_nested_message");
  257. EXPECT_TRUE(optional_int32 != NULL);
  258. EXPECT_TRUE(optional_msg != NULL);
  259. EXPECT_EQ(false, refl->HasField(*message, optional_int32));
  260. refl->SetInt32(message, optional_int32, 42);
  261. EXPECT_EQ(true, refl->HasField(*message, optional_int32));
  262. refl->SetInt32(message, optional_int32, 0);
  263. EXPECT_EQ(false, refl->HasField(*message, optional_int32));
  264. EXPECT_EQ(false, refl->HasField(*message, optional_msg));
  265. refl->MutableMessage(message, optional_msg);
  266. EXPECT_EQ(true, refl->HasField(*message, optional_msg));
  267. delete refl->ReleaseMessage(message, optional_msg);
  268. EXPECT_EQ(false, refl->HasField(*message, optional_msg));
  269. // Also ensure that the default instance handles field presence properly.
  270. EXPECT_EQ(false, refl->HasField(*proto3_prototype_, optional_msg));
  271. delete message;
  272. }
  273. INSTANTIATE_TEST_CASE_P(UseArena, DynamicMessageTest, ::testing::Bool());
  274. } // namespace protobuf
  275. } // namespace google