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