• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC.  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 /* Test of mini table accessors.
9  *
10  * Messages are created and mutated using generated code, and then
11  * accessed through reflective APIs exposed through mini table accessors.
12  */
13 
14 #include "upb/message/copy.h"
15 
16 #include <cstddef>
17 #include <cstdint>
18 #include <cstring>
19 #include <string>
20 #include <vector>
21 
22 #include <gtest/gtest.h>
23 #include "google/protobuf/test_messages_proto2.upb.h"
24 #include "google/protobuf/test_messages_proto2.upb_minitable.h"
25 #include "upb/base/string_view.h"
26 #include "upb/base/upcast.h"
27 #include "upb/mem/arena.h"
28 #include "upb/message/accessors.h"
29 #include "upb/message/internal/message.h"
30 #include "upb/message/map.h"
31 #include "upb/message/message.h"
32 #include "upb/mini_table/field.h"
33 #include "upb/mini_table/message.h"
34 #include "upb/wire/encode.h"
35 
36 // Must be last.
37 #include "upb/port/def.inc"
38 
39 namespace {
40 
41 // Proto2 test messages field numbers used for reflective access.
42 const uint32_t kFieldOptionalInt32 = 1;
43 const uint32_t kFieldOptionalString = 14;
44 const uint32_t kFieldOptionalNestedMessage = 18;
45 
46 const char kTestStr1[] = "Hello1";
47 const char kTestStr2[] = "HelloWorld2";
48 const int32_t kTestInt32 = 567;
49 const int32_t kTestNestedInt32 = 123;
50 
find_proto2_field(int field_number)51 const upb_MiniTableField* find_proto2_field(int field_number) {
52   return upb_MiniTable_FindFieldByNumber(
53       &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init,
54       field_number);
55 }
56 
TEST(GeneratedCode,DeepCloneMessageScalarAndString)57 TEST(GeneratedCode, DeepCloneMessageScalarAndString) {
58   upb_Arena* source_arena = upb_Arena_New();
59   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
60       protobuf_test_messages_proto2_TestAllTypesProto2_new(source_arena);
61   const upb_MiniTableField* optional_int32_field =
62       find_proto2_field(kFieldOptionalInt32);
63   const upb_MiniTableField* optional_string_field =
64       find_proto2_field(kFieldOptionalString);
65   upb_Message_SetInt32(UPB_UPCAST(msg), optional_int32_field, kTestInt32,
66                        nullptr);
67   char* string_in_arena =
68       (char*)upb_Arena_Malloc(source_arena, sizeof(kTestStr1));
69   memcpy(string_in_arena, kTestStr1, sizeof(kTestStr1));
70   upb_Message_SetString(
71       UPB_UPCAST(msg), optional_string_field,
72       upb_StringView_FromDataAndSize(string_in_arena, sizeof(kTestStr1) - 1),
73       source_arena);
74   upb_Arena* arena = upb_Arena_New();
75   protobuf_test_messages_proto2_TestAllTypesProto2* clone =
76       (protobuf_test_messages_proto2_TestAllTypesProto2*)upb_Message_DeepClone(
77           UPB_UPCAST(msg),
78           &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init,
79           arena);
80   // After cloning overwrite values and destroy source arena for MSAN.
81   memset(string_in_arena, 0, sizeof(kTestStr1));
82   upb_Arena_Free(source_arena);
83   EXPECT_TRUE(
84       upb_Message_HasBaseField(UPB_UPCAST(clone), optional_int32_field));
85   EXPECT_EQ(upb_Message_GetInt32(UPB_UPCAST(clone), optional_int32_field, 0),
86             kTestInt32);
87   EXPECT_TRUE(
88       upb_Message_HasBaseField(UPB_UPCAST(clone), optional_string_field));
89   EXPECT_EQ(upb_Message_GetString(UPB_UPCAST(clone), optional_string_field,
90                                   upb_StringView_FromDataAndSize(nullptr, 0))
91                 .size,
92             sizeof(kTestStr1) - 1);
93   EXPECT_TRUE(upb_StringView_IsEqual(
94       upb_Message_GetString(UPB_UPCAST(clone), optional_string_field,
95                             upb_StringView_FromDataAndSize(nullptr, 0)),
96       upb_StringView_FromString(kTestStr1)));
97   upb_Arena_Free(arena);
98 }
99 
TEST(GeneratedCode,DeepCloneMessageSubMessage)100 TEST(GeneratedCode, DeepCloneMessageSubMessage) {
101   upb_Arena* source_arena = upb_Arena_New();
102   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
103       protobuf_test_messages_proto2_TestAllTypesProto2_new(source_arena);
104   const upb_MiniTableField* nested_message_field =
105       find_proto2_field(kFieldOptionalNestedMessage);
106   protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage* nested =
107       protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_new(
108           source_arena);
109   protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_set_a(
110       nested, kTestNestedInt32);
111   upb_Message_SetMessage(UPB_UPCAST(msg), nested_message_field,
112                          UPB_UPCAST(nested));
113   upb_Arena* arena = upb_Arena_New();
114   protobuf_test_messages_proto2_TestAllTypesProto2* clone =
115       (protobuf_test_messages_proto2_TestAllTypesProto2*)upb_Message_DeepClone(
116           UPB_UPCAST(msg),
117           &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init,
118           arena);
119   // After cloning overwrite values and destroy source arena for MSAN.
120   protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_set_a(nested,
121                                                                        0);
122   upb_Arena_Free(source_arena);
123   EXPECT_TRUE(
124       upb_Message_HasBaseField(UPB_UPCAST(clone), nested_message_field));
125   protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage*
126       cloned_nested =
127           (protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage*)
128               upb_Message_GetMessage(UPB_UPCAST(clone), nested_message_field);
129   EXPECT_EQ(protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_a(
130                 cloned_nested),
131             kTestNestedInt32);
132   upb_Arena_Free(arena);
133 }
134 
TEST(GeneratedCode,DeepCloneMessageArrayField)135 TEST(GeneratedCode, DeepCloneMessageArrayField) {
136   upb_Arena* source_arena = upb_Arena_New();
137   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
138       protobuf_test_messages_proto2_TestAllTypesProto2_new(source_arena);
139   std::vector<int32_t> array_test_values = {3, 4, 5};
140   for (int32_t value : array_test_values) {
141     ASSERT_TRUE(
142         protobuf_test_messages_proto2_TestAllTypesProto2_add_repeated_int32(
143             msg, value, source_arena));
144   }
145   upb_Arena* arena = upb_Arena_New();
146   protobuf_test_messages_proto2_TestAllTypesProto2* clone =
147       (protobuf_test_messages_proto2_TestAllTypesProto2*)upb_Message_DeepClone(
148           UPB_UPCAST(msg),
149           &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init,
150           arena);
151   protobuf_test_messages_proto2_TestAllTypesProto2_clear_repeated_sint32(msg);
152   upb_Arena_Free(source_arena);
153   size_t cloned_size = 0;
154   const int32_t* cloned_values =
155       protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(
156           clone, &cloned_size);
157   EXPECT_EQ(cloned_size, array_test_values.size());
158   int index = 0;
159   for (int32_t value : array_test_values) {
160     EXPECT_EQ(cloned_values[index++], value);
161   }
162   upb_Arena_Free(arena);
163 }
164 
TEST(GeneratedCode,DeepCloneMessageMapField)165 TEST(GeneratedCode, DeepCloneMessageMapField) {
166   upb_Arena* source_arena = upb_Arena_New();
167   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
168       protobuf_test_messages_proto2_TestAllTypesProto2_new(source_arena);
169   ASSERT_TRUE(
170       protobuf_test_messages_proto2_TestAllTypesProto2_map_int32_double_set(
171           msg, 12, 1200.5, source_arena));
172   ASSERT_TRUE(
173       protobuf_test_messages_proto2_TestAllTypesProto2_map_string_string_set(
174           msg, upb_StringView_FromString("key1"),
175           upb_StringView_FromString("value1"), source_arena));
176   protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage* nested =
177       protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_new(
178           source_arena);
179   protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_set_a(
180       nested, kTestNestedInt32);
181   ASSERT_TRUE(
182       protobuf_test_messages_proto2_TestAllTypesProto2_map_string_nested_message_set(
183           msg, upb_StringView_FromString("nestedkey1"), nested, source_arena));
184 
185   upb_Arena* arena = upb_Arena_New();
186   protobuf_test_messages_proto2_TestAllTypesProto2* clone =
187       (protobuf_test_messages_proto2_TestAllTypesProto2*)upb_Message_DeepClone(
188           UPB_UPCAST(msg),
189           &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init,
190           arena);
191   protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_set_a(nested,
192                                                                        0);
193   upb_Arena_Free(source_arena);
194   size_t iter = kUpb_Map_Begin;
195   // Test map<int32, int32>.
196   const protobuf_test_messages_proto2_TestAllTypesProto2_MapInt32DoubleEntry*
197       int32_double_entry =
198           protobuf_test_messages_proto2_TestAllTypesProto2_map_int32_double_next(
199               clone, &iter);
200   ASSERT_NE(int32_double_entry, nullptr);
201   EXPECT_EQ(
202       protobuf_test_messages_proto2_TestAllTypesProto2_MapInt32DoubleEntry_key(
203           int32_double_entry),
204       12);
205   EXPECT_EQ(
206       protobuf_test_messages_proto2_TestAllTypesProto2_MapInt32DoubleEntry_value(
207           int32_double_entry),
208       1200.5);
209   // Test map<string, string>.
210   iter = kUpb_Map_Begin;
211   const protobuf_test_messages_proto2_TestAllTypesProto2_MapStringStringEntry*
212       string_string_entry =
213           protobuf_test_messages_proto2_TestAllTypesProto2_map_string_string_next(
214               clone, &iter);
215   ASSERT_NE(string_string_entry, nullptr);
216   EXPECT_TRUE(upb_StringView_IsEqual(
217       protobuf_test_messages_proto2_TestAllTypesProto2_MapStringStringEntry_key(
218           string_string_entry),
219       upb_StringView_FromString("key1")));
220   EXPECT_TRUE(upb_StringView_IsEqual(
221       protobuf_test_messages_proto2_TestAllTypesProto2_MapStringStringEntry_value(
222           string_string_entry),
223       upb_StringView_FromString("value1")));
224   // Test map<string, NestedMessage>.
225   iter = kUpb_Map_Begin;
226   const protobuf_test_messages_proto2_TestAllTypesProto2_MapStringNestedMessageEntry*
227       nested_message_entry =
228           protobuf_test_messages_proto2_TestAllTypesProto2_map_string_nested_message_next(
229               clone, &iter);
230   ASSERT_NE(nested_message_entry, nullptr);
231   EXPECT_TRUE(upb_StringView_IsEqual(
232       protobuf_test_messages_proto2_TestAllTypesProto2_MapStringNestedMessageEntry_key(
233           nested_message_entry),
234       upb_StringView_FromString("nestedkey1")));
235   const protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage*
236       cloned_nested =
237           protobuf_test_messages_proto2_TestAllTypesProto2_MapStringNestedMessageEntry_value(
238               nested_message_entry);
239   ASSERT_NE(cloned_nested, nullptr);
240   EXPECT_EQ(protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_a(
241                 cloned_nested),
242             kTestNestedInt32);
243   upb_Arena_Free(arena);
244 }
245 
TEST(GeneratedCode,DeepCloneMessageExtensions)246 TEST(GeneratedCode, DeepCloneMessageExtensions) {
247   // Alloc and fill in test message with extension.
248   upb_Arena* source_arena = upb_Arena_New();
249   protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrect* msg =
250       protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrect_new(
251           source_arena);
252   protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1*
253       ext1 =
254           protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_new(
255               source_arena);
256   protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_set_str(
257       ext1, upb_StringView_FromString(kTestStr1));
258   protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_set_message_set_extension(
259       msg, ext1, source_arena);
260   // Create clone.
261   upb_Arena* arena = upb_Arena_New();
262   protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrect* clone =
263       (protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrect*)
264           upb_Message_DeepClone(
265               UPB_UPCAST(msg),
266               &protobuf_0test_0messages__proto2__TestAllTypesProto2__MessageSetCorrect_msg_init,
267               arena);
268 
269   // Mutate original extension.
270   protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_set_str(
271       ext1, upb_StringView_FromString(kTestStr2));
272   upb_Arena_Free(source_arena);
273 
274   const protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1*
275       cloned_ext =
276           protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_message_set_extension(
277               clone);
278   ASSERT_NE(cloned_ext, nullptr);
279   EXPECT_TRUE(upb_StringView_IsEqual(
280       protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_str(
281           cloned_ext),
282       upb_StringView_FromString(kTestStr1)));
283   upb_Arena_Free(arena);
284 }
285 
TEST(GeneratedCode,DeepCloneMessageWithUnknowns)286 TEST(GeneratedCode, DeepCloneMessageWithUnknowns) {
287   upb_Arena* source_arena = upb_Arena_New();
288   upb_Arena* unknown_arena = upb_Arena_New();
289   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
290       protobuf_test_messages_proto2_TestAllTypesProto2_new(source_arena);
291   ASSERT_TRUE(
292       protobuf_test_messages_proto2_TestAllTypesProto2_map_int32_double_set(
293           msg, 12, 1200.5, source_arena));
294   ASSERT_TRUE(
295       protobuf_test_messages_proto2_TestAllTypesProto2_map_string_string_set(
296           msg, upb_StringView_FromString("key1"),
297           upb_StringView_FromString("value1"), source_arena));
298   // Create unknown data.
299   protobuf_test_messages_proto2_UnknownToTestAllTypes* unknown_source =
300       protobuf_test_messages_proto2_UnknownToTestAllTypes_new(unknown_arena);
301   protobuf_test_messages_proto2_UnknownToTestAllTypes_set_optional_bool(
302       unknown_source, true);
303   protobuf_test_messages_proto2_UnknownToTestAllTypes_set_optional_int32(
304       unknown_source, 123);
305   // Encode unknown message to bytes.
306   size_t len;
307   char* data;
308   upb_Arena* encode_arena = upb_Arena_New();
309   upb_EncodeStatus status = upb_Encode(
310       UPB_UPCAST(unknown_source),
311       &protobuf_0test_0messages__proto2__UnknownToTestAllTypes_msg_init,
312       kUpb_EncodeOption_CheckRequired, encode_arena, &data, &len);
313   ASSERT_EQ(status, kUpb_EncodeStatus_Ok);
314   std::string unknown_data(data, len);
315   // Add unknown data.
316   UPB_PRIVATE(_upb_Message_AddUnknown)
317   (UPB_UPCAST(msg), data, len, source_arena);
318   // Create clone.
319   upb_Arena* clone_arena = upb_Arena_New();
320   protobuf_test_messages_proto2_TestAllTypesProto2* clone =
321       (protobuf_test_messages_proto2_TestAllTypesProto2*)upb_Message_DeepClone(
322           UPB_UPCAST(msg),
323           &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init,
324           clone_arena);
325   upb_Arena_Free(source_arena);
326   upb_Arena_Free(unknown_arena);
327   upb_Arena_Free(encode_arena);
328   // Read unknown data from clone and verify.
329   size_t cloned_length;
330   const char* cloned_unknown_data =
331       upb_Message_GetUnknown(UPB_UPCAST(clone), &cloned_length);
332   EXPECT_EQ(cloned_length, len);
333   EXPECT_EQ(memcmp(cloned_unknown_data, unknown_data.c_str(), cloned_length),
334             0);
335   upb_Arena_Free(clone_arena);
336 }
337 
338 }  // namespace
339