• 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/accessors.h"
15 
16 #include <string.h>
17 
18 #include <cstddef>
19 #include <cstdint>
20 #include <string>
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 "google/protobuf/test_messages_proto3.upb.h"
26 #include "google/protobuf/test_messages_proto3.upb_minitable.h"
27 #include "upb/base/descriptor_constants.h"
28 #include "upb/base/status.h"
29 #include "upb/base/string_view.h"
30 #include "upb/base/upcast.h"
31 #include "upb/mem/arena.h"
32 #include "upb/message/array.h"
33 #include "upb/message/message.h"
34 #include "upb/mini_descriptor/decode.h"
35 #include "upb/mini_descriptor/internal/encode.hpp"
36 #include "upb/mini_descriptor/internal/modifiers.h"
37 #include "upb/mini_table/field.h"
38 #include "upb/mini_table/message.h"
39 
40 // Must be last
41 #include "upb/port/def.inc"
42 
43 namespace {
44 
45 // Proto2 test messages field numbers used for reflective access.
46 const uint32_t kFieldOptionalInt32 = 1;
47 const uint32_t kFieldOptionalUInt32 = 3;
48 const uint32_t kFieldOptionalBool = 13;
49 const uint32_t kFieldOptionalString = 14;
50 const uint32_t kFieldOptionalNestedMessage = 18;
51 const uint32_t kFieldOptionalRepeatedInt32 = 31;
52 const uint32_t kFieldOptionalRepeatedNestedMessage = 48;
53 const uint32_t kFieldOptionalNestedMessageA = 1;
54 const uint32_t kFieldOptionalOneOfUInt32 = 111;
55 const uint32_t kFieldOptionalOneOfString = 113;
56 
57 const uint32_t kFieldProto3OptionalInt64 = 2;
58 const uint32_t kFieldProto3OptionalUInt64 = 4;
59 
60 const char kTestStr1[] = "Hello1";
61 const char kTestStr2[] = "Hello2";
62 const int32_t kTestInt32 = 567;
63 const int32_t kTestUInt32 = 0xF1234567;
64 const uint64_t kTestUInt64 = 0xFEDCBAFF87654321;
65 
find_proto3_field(int field_number)66 const upb_MiniTableField* find_proto3_field(int field_number) {
67   return upb_MiniTable_FindFieldByNumber(
68       &protobuf_0test_0messages__proto3__TestAllTypesProto3_msg_init,
69       field_number);
70 }
71 
find_proto2_field(int field_number)72 const upb_MiniTableField* find_proto2_field(int field_number) {
73   return upb_MiniTable_FindFieldByNumber(
74       &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init,
75       field_number);
76 }
77 
TEST(GeneratedCode,HazzersProto2)78 TEST(GeneratedCode, HazzersProto2) {
79   upb_Arena* arena = upb_Arena_New();
80   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
81       protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
82 
83   // Scalar/Boolean.
84   const upb_MiniTableField* optional_bool_field =
85       find_proto2_field(kFieldOptionalBool);
86   EXPECT_EQ(false,
87             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_bool_field));
88   protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_bool(msg, true);
89   EXPECT_EQ(true,
90             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_bool_field));
91   upb_Message_ClearBaseField(UPB_UPCAST(msg), optional_bool_field);
92   EXPECT_EQ(false,
93             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_bool_field));
94   EXPECT_EQ(
95       false,
96       protobuf_test_messages_proto2_TestAllTypesProto2_optional_bool(msg));
97 
98   // String.
99   const upb_MiniTableField* optional_string_field =
100       find_proto2_field(kFieldOptionalString);
101   EXPECT_EQ(false,
102             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_string_field));
103   protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_string(
104       msg, upb_StringView_FromString(kTestStr1));
105   EXPECT_EQ(true,
106             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_string_field));
107   EXPECT_EQ(
108       strlen(kTestStr1),
109       protobuf_test_messages_proto2_TestAllTypesProto2_optional_string(msg)
110           .size);
111   upb_Message_ClearBaseField(UPB_UPCAST(msg), optional_string_field);
112   EXPECT_EQ(false,
113             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_string_field));
114   EXPECT_EQ(
115       0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_string(msg)
116              .size);
117 
118   // Message.
119   const upb_MiniTableField* optional_message_field =
120       find_proto2_field(kFieldOptionalNestedMessage);
121   EXPECT_EQ(false,
122             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_message_field));
123   protobuf_test_messages_proto2_TestAllTypesProto2_mutable_optional_nested_message(
124       msg, arena);
125   EXPECT_EQ(true,
126             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_message_field));
127   upb_Message_ClearBaseField(UPB_UPCAST(msg), optional_message_field);
128   EXPECT_EQ(false,
129             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_message_field));
130   EXPECT_EQ(
131       true,
132       protobuf_test_messages_proto2_TestAllTypesProto2_optional_nested_message(
133           msg) == nullptr);
134 
135   // One of.
136   const upb_MiniTableField* optional_oneof_uint32_field =
137       find_proto2_field(kFieldOptionalOneOfUInt32);
138   const upb_MiniTableField* optional_oneof_string_field =
139       find_proto2_field(kFieldOptionalOneOfString);
140 
141   EXPECT_EQ(false, upb_Message_HasBaseField(UPB_UPCAST(msg),
142                                             optional_oneof_uint32_field));
143   EXPECT_EQ(false, upb_Message_HasBaseField(UPB_UPCAST(msg),
144                                             optional_oneof_string_field));
145   protobuf_test_messages_proto2_TestAllTypesProto2_set_oneof_uint32(msg, 123);
146   EXPECT_EQ(true, upb_Message_HasBaseField(UPB_UPCAST(msg),
147                                            optional_oneof_uint32_field));
148   EXPECT_EQ(false, upb_Message_HasBaseField(UPB_UPCAST(msg),
149                                             optional_oneof_string_field));
150   protobuf_test_messages_proto2_TestAllTypesProto2_set_oneof_string(
151       msg, upb_StringView_FromString(kTestStr1));
152   EXPECT_EQ(false, upb_Message_HasBaseField(UPB_UPCAST(msg),
153                                             optional_oneof_uint32_field));
154   EXPECT_EQ(true, upb_Message_HasBaseField(UPB_UPCAST(msg),
155                                            optional_oneof_string_field));
156   upb_Message_ClearBaseField(UPB_UPCAST(msg), optional_oneof_uint32_field);
157   EXPECT_EQ(false, upb_Message_HasBaseField(UPB_UPCAST(msg),
158                                             optional_oneof_uint32_field));
159   EXPECT_EQ(true, upb_Message_HasBaseField(UPB_UPCAST(msg),
160                                            optional_oneof_string_field));
161   upb_Message_ClearBaseField(UPB_UPCAST(msg), optional_oneof_string_field);
162   EXPECT_EQ(false, upb_Message_HasBaseField(UPB_UPCAST(msg),
163                                             optional_oneof_uint32_field));
164   EXPECT_EQ(false, upb_Message_HasBaseField(UPB_UPCAST(msg),
165                                             optional_oneof_string_field));
166 
167   upb_Arena_Free(arena);
168 }
169 
TEST(GeneratedCode,ScalarsProto2)170 TEST(GeneratedCode, ScalarsProto2) {
171   upb_Arena* arena = upb_Arena_New();
172   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
173       protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
174 
175   const upb_MiniTableField* optional_int32_field =
176       find_proto2_field(kFieldOptionalInt32);
177 
178   EXPECT_EQ(
179       0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_int32(msg));
180 
181   EXPECT_EQ(0, upb_Message_GetInt32(UPB_UPCAST(msg), optional_int32_field, 0));
182   upb_Message_SetBaseFieldInt32(UPB_UPCAST(msg), optional_int32_field,
183                                 kTestInt32);
184   EXPECT_EQ(true,
185             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_int32_field));
186   EXPECT_EQ(kTestInt32,
187             upb_Message_GetInt32(UPB_UPCAST(msg), optional_int32_field, 0));
188   EXPECT_EQ(
189       kTestInt32,
190       protobuf_test_messages_proto2_TestAllTypesProto2_optional_int32(msg));
191 
192   const upb_MiniTableField* optional_uint32_field =
193       find_proto2_field(kFieldOptionalUInt32);
194 
195   EXPECT_EQ(
196       0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_uint32(msg));
197   EXPECT_EQ(0,
198             upb_Message_GetUInt32(UPB_UPCAST(msg), optional_uint32_field, 0));
199   upb_Message_SetBaseFieldUInt32(UPB_UPCAST(msg), optional_uint32_field,
200                                  kTestUInt32);
201   EXPECT_EQ(kTestUInt32,
202             upb_Message_GetUInt32(UPB_UPCAST(msg), optional_uint32_field, 0));
203   EXPECT_EQ(
204       kTestUInt32,
205       protobuf_test_messages_proto2_TestAllTypesProto2_optional_uint32(msg));
206 
207   upb_Arena_Free(arena);
208 }
209 
TEST(GeneratedCode,ScalarProto3)210 TEST(GeneratedCode, ScalarProto3) {
211   upb_Arena* arena = upb_Arena_New();
212   protobuf_test_messages_proto3_TestAllTypesProto3* msg =
213       protobuf_test_messages_proto3_TestAllTypesProto3_new(arena);
214 
215   const upb_MiniTableField* optional_int64_field =
216       find_proto3_field(kFieldProto3OptionalInt64);
217   const upb_MiniTableField* optional_uint64_field =
218       find_proto3_field(kFieldProto3OptionalUInt64);
219 
220   EXPECT_EQ(
221       0, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int64(msg));
222   upb_Message_SetBaseFieldInt64(UPB_UPCAST(msg), optional_int64_field, -1);
223   EXPECT_EQ(
224       -1, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int64(msg));
225   EXPECT_EQ(-1, upb_Message_GetInt64(UPB_UPCAST(msg), optional_int64_field, 0));
226 
227   EXPECT_EQ(
228       0, protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint64(msg));
229   upb_Message_SetBaseFieldUInt64(UPB_UPCAST(msg), optional_uint64_field,
230                                  kTestUInt64);
231   EXPECT_EQ(
232       kTestUInt64,
233       protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint64(msg));
234   EXPECT_EQ(kTestUInt64,
235             upb_Message_GetUInt64(UPB_UPCAST(msg), optional_uint64_field, 0));
236 
237   upb_Arena_Free(arena);
238 }
239 
TEST(GeneratedCode,Strings)240 TEST(GeneratedCode, Strings) {
241   upb_Arena* arena = upb_Arena_New();
242   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
243       protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
244 
245   const upb_MiniTableField* optional_string_field =
246       find_proto2_field(kFieldOptionalString);
247 
248   // Test default.
249   EXPECT_EQ(false,
250             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_string_field));
251   // Test read after write using C.
252   protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_string(
253       msg, upb_StringView_FromString(kTestStr1));
254   EXPECT_EQ(true,
255             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_string_field));
256   upb_StringView value = upb_Message_GetString(
257       UPB_UPCAST(msg), optional_string_field, upb_StringView{nullptr, 0});
258   std::string read_value = std::string(value.data, value.size);
259   EXPECT_EQ(kTestStr1, read_value);
260   // Clear.
261   upb_Message_ClearBaseField(UPB_UPCAST(msg), optional_string_field);
262   EXPECT_EQ(false,
263             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_string_field));
264   EXPECT_EQ(
265       false,
266       protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_string(
267           msg));
268   upb_Message_SetBaseFieldString(UPB_UPCAST(msg), optional_string_field,
269                                  upb_StringView_FromString(kTestStr2));
270   EXPECT_EQ(true,
271             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_string_field));
272   EXPECT_EQ(
273       true,
274       protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_string(
275           msg));
276   value = protobuf_test_messages_proto2_TestAllTypesProto2_optional_string(msg);
277   read_value = std::string(value.data, value.size);
278   EXPECT_EQ(kTestStr2, read_value);
279 
280   upb_Arena_Free(arena);
281 }
282 
TEST(GeneratedCode,SubMessage)283 TEST(GeneratedCode, SubMessage) {
284   upb_Arena* arena = upb_Arena_New();
285   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
286       protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
287 
288   const upb_MiniTableField* optional_message_field =
289       find_proto2_field(kFieldOptionalNestedMessage);
290 
291   const upb_Message* test_message =
292       upb_Message_GetMessage(UPB_UPCAST(msg), optional_message_field);
293   EXPECT_EQ(nullptr, test_message);
294 
295   EXPECT_EQ(false,
296             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_message_field));
297 
298   // Get mutable using C API.
299   protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage* nested_message =
300       protobuf_test_messages_proto2_TestAllTypesProto2_mutable_optional_nested_message(
301           msg, arena);
302   EXPECT_EQ(true, nested_message != nullptr);
303   EXPECT_EQ(true,
304             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_message_field));
305   protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_set_a(
306       nested_message, 5);
307 
308   // Read back using mini table API.
309   const upb_Message* sub_message =
310       upb_Message_GetMessage(UPB_UPCAST(msg), optional_message_field);
311   EXPECT_EQ(true, sub_message != nullptr);
312 
313   const upb_MiniTableField* nested_message_a_field =
314       upb_MiniTable_FindFieldByNumber(
315           &protobuf_0test_0messages__proto2__TestAllTypesProto2__NestedMessage_msg_init,
316           kFieldOptionalNestedMessageA);
317   EXPECT_EQ(5, upb_Message_GetInt32(sub_message, nested_message_a_field, 0));
318 
319   upb_Message_ClearBaseField(UPB_UPCAST(msg), optional_message_field);
320   EXPECT_EQ(
321       nullptr,
322       protobuf_test_messages_proto2_TestAllTypesProto2_optional_nested_message(
323           msg));
324   EXPECT_EQ(false,
325             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_message_field));
326 
327   upb_Message* new_nested_message = UPB_UPCAST(
328       protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_new(
329           arena));
330   upb_Message_SetBaseFieldInt32(new_nested_message, nested_message_a_field,
331                                 123);
332   upb_Message_SetMessage(UPB_UPCAST(msg), optional_message_field,
333                          new_nested_message);
334 
335   upb_Message* mutable_message = upb_Message_GetOrCreateMutableMessage(
336       UPB_UPCAST(msg),
337       &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init,
338       optional_message_field, arena);
339   EXPECT_EQ(
340       true,
341       protobuf_test_messages_proto2_TestAllTypesProto2_optional_nested_message(
342           msg) != nullptr);
343   EXPECT_EQ(true,
344             upb_Message_HasBaseField(UPB_UPCAST(msg), optional_message_field));
345   EXPECT_EQ(123,
346             upb_Message_GetInt32(mutable_message, nested_message_a_field, 0));
347 
348   upb_Arena_Free(arena);
349 }
350 
TEST(GeneratedCode,RepeatedScalar)351 TEST(GeneratedCode, RepeatedScalar) {
352   upb_Arena* arena = upb_Arena_New();
353   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
354       protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
355 
356   const upb_MiniTableField* repeated_int32_field =
357       find_proto2_field(kFieldOptionalRepeatedInt32);
358 
359   size_t len;
360   const int32_t* arr =
361       protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(msg,
362                                                                       &len);
363   // Test Get/Set Array values, validate with C API.
364   EXPECT_EQ(0, len);
365   EXPECT_EQ(nullptr, arr);
366   EXPECT_EQ(nullptr,
367             upb_Message_GetArray(UPB_UPCAST(msg), repeated_int32_field));
368   protobuf_test_messages_proto2_TestAllTypesProto2_resize_repeated_int32(
369       msg, 10, arena);
370   int32_t* mutable_values =
371       protobuf_test_messages_proto2_TestAllTypesProto2_mutable_repeated_int32(
372           msg, &len);
373   mutable_values[5] = 123;
374   const upb_Array* readonly_arr =
375       upb_Message_GetArray(UPB_UPCAST(msg), repeated_int32_field);
376   EXPECT_EQ(123, upb_Array_Get(readonly_arr, 5).int32_val);
377 
378   upb_MessageValue new_value;
379   new_value.int32_val = 567;
380   upb_Array* mutable_array =
381       upb_Message_GetMutableArray(UPB_UPCAST(msg), repeated_int32_field);
382   upb_Array_Set(mutable_array, 5, new_value);
383   EXPECT_EQ(new_value.int32_val,
384             protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(
385                 msg, &len)[5]);
386 
387   // Test resize.
388   bool result = upb_Array_Resize(mutable_array, 20, arena);
389   EXPECT_EQ(true, result);
390   upb_Array_Set(mutable_array, 19, new_value);
391   EXPECT_EQ(new_value.int32_val,
392             protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(
393                 msg, &len)[19]);
394   upb_Array_Resize(mutable_array, 0, arena);
395   const int32_t* zero_length_array =
396       protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(msg,
397                                                                       &len);
398   EXPECT_EQ(0, len);
399   EXPECT_EQ(true, zero_length_array != nullptr);
400 
401   upb_Arena_Free(arena);
402 }
403 
TEST(GeneratedCode,RepeatedMessage)404 TEST(GeneratedCode, RepeatedMessage) {
405   upb_Arena* arena = upb_Arena_New();
406   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
407       protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
408 
409   const upb_MiniTableField* repeated_nested_message_field =
410       find_proto2_field(kFieldOptionalRepeatedNestedMessage);
411   upb_Message* nested_message = (upb_Message*)
412       protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_new(arena);
413 
414   upb_Array* array = upb_Message_GetOrCreateMutableArray(
415       UPB_UPCAST(msg), repeated_nested_message_field, arena);
416   upb_MessageValue new_value;
417   new_value.msg_val = nested_message;
418   EXPECT_TRUE(upb_Array_Append(array, new_value, arena));
419 
420   EXPECT_EQ(nested_message, upb_Array_GetMutable(array, 0).msg);
421   EXPECT_EQ(nested_message, upb_Array_Get(array, 0).msg_val);
422 
423   upb_Arena_Free(arena);
424 }
425 
TEST(GeneratedCode,GetMutableMessage)426 TEST(GeneratedCode, GetMutableMessage) {
427   upb_Arena* arena = upb_Arena_New();
428   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
429       protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
430   // Message.
431   const upb_MiniTableField* optional_message_field =
432       find_proto2_field(kFieldOptionalNestedMessage);
433   upb_Message* msg1 = upb_Message_GetOrCreateMutableMessage(
434       UPB_UPCAST(msg),
435       &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init,
436       optional_message_field, arena);
437   upb_Message* msg2 = upb_Message_GetOrCreateMutableMessage(
438       UPB_UPCAST(msg),
439       &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init,
440       optional_message_field, arena);
441   // Verify that newly constructed sub message is stored in msg.
442   EXPECT_EQ(msg1, msg2);
443 
444   upb_Arena_Free(arena);
445 }
446 
TEST(GeneratedCode,EnumClosedCheck)447 TEST(GeneratedCode, EnumClosedCheck) {
448   upb_Arena* arena = upb_Arena_New();
449 
450   upb::MtDataEncoder e;
451   e.StartMessage(0);
452   e.PutField(kUpb_FieldType_Int32, 4, 0);
453   e.PutField(kUpb_FieldType_Enum, 5, 0);
454 
455   upb_Status status;
456   upb_Status_Clear(&status);
457   upb_MiniTable* table =
458       upb_MiniTable_Build(e.data().data(), e.data().size(), arena, &status);
459 
460   const upb_MiniTableField* enumField = &table->UPB_PRIVATE(fields)[1];
461   EXPECT_EQ(upb_MiniTableField_Type(enumField), kUpb_FieldType_Enum);
462   EXPECT_FALSE(upb_MiniTableField_IsClosedEnum(enumField));
463 
464   upb::MtDataEncoder e2;
465   e2.StartMessage(0);
466   e2.PutField(kUpb_FieldType_Int32, 4, 0);
467   e2.PutField(kUpb_FieldType_Enum, 6, kUpb_FieldModifier_IsClosedEnum);
468 
469   upb_Status_Clear(&status);
470   table =
471       upb_MiniTable_Build(e2.data().data(), e2.data().size(), arena, &status);
472 
473   const upb_MiniTableField* closedEnumField = &table->UPB_PRIVATE(fields)[1];
474   EXPECT_EQ(upb_MiniTableField_Type(closedEnumField), kUpb_FieldType_Enum);
475   EXPECT_TRUE(upb_MiniTableField_IsClosedEnum(closedEnumField));
476   upb_Arena_Free(arena);
477 }
478 
TEST(GeneratedCode,OneofClear)479 TEST(GeneratedCode, OneofClear) {
480   upb_Arena* arena = upb_Arena_New();
481 
482   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
483       protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
484 
485   const upb_MiniTable* table =
486       &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init;
487 
488   // oneof_uint32
489   const upb_MiniTableField* oneofField =
490       upb_MiniTable_FindFieldByNumber(table, 111);
491   EXPECT_TRUE(upb_MiniTableField_IsInOneof(oneofField));
492   protobuf_test_messages_proto2_TestAllTypesProto2_set_oneof_uint32(msg, 522);
493   EXPECT_TRUE(
494       protobuf_test_messages_proto2_TestAllTypesProto2_has_oneof_uint32(msg));
495 
496   upb_Message_ClearOneof((upb_Message*)msg, table, oneofField);
497   EXPECT_FALSE(
498       protobuf_test_messages_proto2_TestAllTypesProto2_has_oneof_uint32(msg));
499 
500   upb_Arena_Free(arena);
501 }
502 
TEST(GeneratedCode,OneofAccess)503 TEST(GeneratedCode, OneofAccess) {
504   upb_Arena* arena = upb_Arena_New();
505 
506   protobuf_test_messages_proto2_TestAllTypesProto2* msg =
507       protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
508 
509   const upb_MiniTable* table =
510       &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init;
511 
512   // oneof_uint32
513   const upb_MiniTableField* oneofField =
514       upb_MiniTable_FindFieldByNumber(table, 111);
515   EXPECT_TRUE(upb_MiniTableField_IsInOneof(oneofField));
516 
517   const upb_MiniTableField* oneOfFirstFetch =
518       upb_Message_WhichOneof((upb_Message*)msg, table, oneofField);
519   // one of not set, so should initially yield nullptr
520   EXPECT_EQ(oneOfFirstFetch, nullptr);
521 
522   protobuf_test_messages_proto2_TestAllTypesProto2_set_oneof_uint32(msg, 522);
523   const upb_MiniTableField* oneOfSecondFetch =
524       upb_Message_WhichOneof((upb_Message*)msg, table, oneofField);
525   // this oneof has now been set, so should yield the MiniTableField
526   EXPECT_EQ(oneOfSecondFetch, oneofField);
527 
528   upb_Arena_Free(arena);
529 }
530 
531 }  // namespace
532