| // Protocol Buffers - Google's data interchange format | |
| // Copyright 2023 Google LLC. All rights reserved. | |
| // | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file or at | |
| // https://developers.google.com/open-source/licenses/bsd | |
| /* Test of generated code, with a special focus on features that are not used in | |
| * descriptor.proto or conformance.proto (since these get some testing from | |
| * upb/def.c and tests/conformance_upb.c, respectively). | |
| */ | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <cstdlib> | |
| #include <cstring> | |
| #include <gtest/gtest.h> | |
| #include "google/protobuf/test_messages_proto2.upb.h" | |
| #include "google/protobuf/test_messages_proto3.upb.h" | |
| #include "upb/base/status.h" | |
| #include "upb/base/string_view.h" | |
| #include "upb/mem/alloc.h" | |
| #include "upb/mem/arena.h" | |
| #include "upb/mem/arena.hpp" | |
| #include "upb/message/array.h" | |
| #include "upb/message/map.h" | |
| #include "upb/message/message.h" | |
| #include "upb/test/test.upb.h" | |
| #include "upb/test/test.upb_minitable.h" | |
| #include "upb/wire/decode.h" | |
| #include "upb/wire/encode.h" | |
| // Must be last. | |
| #include "upb/port/def.inc" | |
| #if !defined(MIN) | |
| #define MIN(x, y) ((x) < (y) ? (x) : (y)) | |
| #endif | |
| const char test_str[] = "abcdefg"; | |
| const char test_str2[] = "12345678910"; | |
| const char test_str3[] = "rstlnezxcvbnm"; | |
| const char test_str4[] = "just another test string"; | |
| const upb_StringView test_str_view = {test_str, sizeof(test_str) - 1}; | |
| const upb_StringView test_str_view2 = {test_str2, sizeof(test_str2) - 1}; | |
| const upb_StringView test_str_view3 = {test_str3, sizeof(test_str3) - 1}; | |
| const upb_StringView test_str_view4 = {test_str4, sizeof(test_str4) - 1}; | |
| const int32_t test_int32 = 10; | |
| const int32_t test_int32_2 = -20; | |
| const int32_t test_int32_3 = 30; | |
| const int32_t test_int32_4 = -40; | |
| TEST(GeneratedCode, ScalarsProto3) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg = | |
| protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg2; | |
| upb_StringView serialized; | |
| upb_StringView val; | |
| // Test serialization. | |
| protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_int32(msg, 10); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_int64(msg, 20); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_uint32(msg, 30); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_uint64(msg, 40); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_float(msg, | |
| 50.5); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_double(msg, | |
| 60.6); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_bool(msg, true); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_string( | |
| msg, test_str_view); | |
| serialized.data = protobuf_test_messages_proto3_TestAllTypesProto3_serialize( | |
| msg, arena, &serialized.size); | |
| msg2 = protobuf_test_messages_proto3_TestAllTypesProto3_parse( | |
| serialized.data, serialized.size, arena); | |
| EXPECT_EQ(10, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int32( | |
| msg2)); | |
| EXPECT_EQ(20, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int64( | |
| msg2)); | |
| EXPECT_EQ( | |
| 30, | |
| protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint32(msg2)); | |
| EXPECT_EQ( | |
| 40, | |
| protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint64(msg2)); | |
| EXPECT_EQ( | |
| 50.5, | |
| protobuf_test_messages_proto3_TestAllTypesProto3_optional_float(msg2)); | |
| EXPECT_EQ( | |
| 60.6, | |
| protobuf_test_messages_proto3_TestAllTypesProto3_optional_double(msg2)); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto3_TestAllTypesProto3_optional_bool(msg2)); | |
| val = protobuf_test_messages_proto3_TestAllTypesProto3_optional_string(msg2); | |
| EXPECT_TRUE(upb_StringView_IsEqual(val, test_str_view)); | |
| // Test clear. | |
| protobuf_test_messages_proto3_TestAllTypesProto3_clear_optional_int32(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int32(msg)); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_clear_optional_int64(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto3_TestAllTypesProto3_optional_int64(msg)); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_clear_optional_uint32(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint32(msg)); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_clear_optional_uint64(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint64(msg)); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_clear_optional_float(msg); | |
| EXPECT_EQ( | |
| 0.0f, | |
| protobuf_test_messages_proto3_TestAllTypesProto3_optional_float(msg)); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_clear_optional_double(msg); | |
| EXPECT_EQ( | |
| 0.0, | |
| protobuf_test_messages_proto3_TestAllTypesProto3_optional_double(msg)); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_clear_optional_bool(msg); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto3_TestAllTypesProto3_optional_bool(msg)); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_clear_optional_string(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto3_TestAllTypesProto3_optional_string(msg) | |
| .size); | |
| upb_Arena_Free(arena); | |
| } | |
| TEST(GeneratedCode, ScalarsProto2) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| protobuf_test_messages_proto2_TestAllTypesProto2* msg = | |
| protobuf_test_messages_proto2_TestAllTypesProto2_new(arena); | |
| protobuf_test_messages_proto2_TestAllTypesProto2* msg2; | |
| upb_StringView serialized; | |
| // Test hazzer and serialization. | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_int32(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_int32(msg, 10); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_int32(msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_int64(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_int64(msg, 20); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_int64(msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_uint32( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_uint32(msg, 30); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_uint32( | |
| msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_uint64( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_uint64(msg, 40); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_uint64( | |
| msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_sint32( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_sint32(msg, 50); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_sint32( | |
| msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_sint64( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_sint64(msg, 60); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_sint64( | |
| msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_fixed32( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_fixed32(msg, | |
| 70); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_fixed32( | |
| msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_fixed64( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_fixed64(msg, | |
| 80); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_fixed64( | |
| msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_sfixed32( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_sfixed32(msg, | |
| 90); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_sfixed32( | |
| msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_sfixed64( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_sfixed64(msg, | |
| 100); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_sfixed64( | |
| msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_float(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_float(msg, | |
| 50.5); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_float(msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_double( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_double(msg, | |
| 60.6); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_double( | |
| msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_bool(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_bool(msg, true); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_bool(msg)); | |
| serialized.data = protobuf_test_messages_proto2_TestAllTypesProto2_serialize( | |
| msg, arena, &serialized.size); | |
| msg2 = protobuf_test_messages_proto2_TestAllTypesProto2_parse( | |
| serialized.data, serialized.size, arena); | |
| EXPECT_EQ(10, protobuf_test_messages_proto2_TestAllTypesProto2_optional_int32( | |
| msg2)); | |
| EXPECT_EQ(20, protobuf_test_messages_proto2_TestAllTypesProto2_optional_int64( | |
| msg2)); | |
| EXPECT_EQ( | |
| 30, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_uint32(msg2)); | |
| EXPECT_EQ( | |
| 40, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_uint64(msg2)); | |
| EXPECT_EQ( | |
| 50, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_sint32(msg2)); | |
| EXPECT_EQ( | |
| 60, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_sint64(msg2)); | |
| EXPECT_EQ( | |
| 70, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_fixed32(msg2)); | |
| EXPECT_EQ( | |
| 80, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_fixed64(msg2)); | |
| EXPECT_EQ( | |
| 90, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_sfixed32(msg2)); | |
| EXPECT_EQ( | |
| 100, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_sfixed64(msg2)); | |
| EXPECT_EQ( | |
| 50.5, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_float(msg2)); | |
| EXPECT_EQ( | |
| 60.6, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_double(msg2)); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_bool(msg2)); | |
| // Test clear. | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_int32(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_int32(msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_int32(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_int64(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_int64(msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_int64(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_uint32(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_uint32(msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_uint32( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_uint64(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_uint64(msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_uint64( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_float(msg); | |
| EXPECT_EQ( | |
| 0.0f, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_float(msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_float(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_double(msg); | |
| EXPECT_EQ( | |
| 0.0, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_double(msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_double( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_bool(msg); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_bool(msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_bool(msg)); | |
| upb_Arena_Free(arena); | |
| } | |
| TEST(GeneratedCode, RepeatedClear) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| protobuf_test_messages_proto2_TestAllTypesProto2* msg = | |
| protobuf_test_messages_proto2_TestAllTypesProto2_new(arena); | |
| size_t len = 0; | |
| protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(msg, &len); | |
| EXPECT_EQ(0, len); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_add_repeated_int32(msg, 2, | |
| arena); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_add_repeated_int32(msg, 3, | |
| arena); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_add_repeated_int32(msg, 4, | |
| arena); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(msg, &len); | |
| EXPECT_EQ(3, len); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_repeated_int32(msg); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32(msg, &len); | |
| EXPECT_EQ(0, len); | |
| upb_Arena_Free(arena); | |
| } | |
| TEST(GeneratedCode, Clear) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| protobuf_test_messages_proto2_TestAllTypesProto2* msg = | |
| protobuf_test_messages_proto2_TestAllTypesProto2_new(arena); | |
| // Test clear. | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_int32(msg, 1); | |
| EXPECT_TRUE( | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_int32(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_int32(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_int32(msg)); | |
| EXPECT_FALSE( | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_int32(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_int64(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_int64(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_uint32(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_uint32(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_uint64(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_uint64(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_float(msg); | |
| EXPECT_EQ( | |
| 0.0f, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_float(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_double(msg); | |
| EXPECT_EQ( | |
| 0.0, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_double(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_bool(msg); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_bool(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_string(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_string(msg) | |
| .size); | |
| upb_Arena_Free(arena); | |
| } | |
| TEST(GeneratedCode, Bytes) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| protobuf_test_messages_proto2_TestAllTypesProto2* msg = | |
| protobuf_test_messages_proto2_TestAllTypesProto2_new(arena); | |
| protobuf_test_messages_proto2_TestAllTypesProto2* msg2; | |
| upb_StringView serialized; | |
| const char data[] = "ABCDEF"; | |
| upb_StringView bytes = upb_StringView_FromString(data); | |
| upb_StringView val; | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_bytes(msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_bytes(msg, | |
| bytes); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_bytes(msg)); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_string( | |
| msg)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_string( | |
| msg, test_str_view); | |
| EXPECT_EQ( | |
| true, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_string( | |
| msg)); | |
| serialized.data = protobuf_test_messages_proto2_TestAllTypesProto2_serialize( | |
| msg, arena, &serialized.size); | |
| msg2 = protobuf_test_messages_proto2_TestAllTypesProto2_parse( | |
| serialized.data, serialized.size, arena); | |
| EXPECT_EQ(bytes.size, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_bytes(msg) | |
| .size); | |
| EXPECT_EQ( | |
| 0, memcmp(bytes.data, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_optional_bytes( | |
| msg) | |
| .data, | |
| bytes.size)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_bytes(msg); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_bytes(msg)); | |
| val = protobuf_test_messages_proto2_TestAllTypesProto2_optional_string(msg2); | |
| EXPECT_TRUE(upb_StringView_IsEqual(val, test_str_view)); | |
| protobuf_test_messages_proto2_TestAllTypesProto2_clear_optional_string(msg); | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto2_TestAllTypesProto2_optional_string(msg) | |
| .size); | |
| EXPECT_EQ( | |
| false, | |
| protobuf_test_messages_proto2_TestAllTypesProto2_has_optional_string( | |
| msg)); | |
| upb_Arena_Free(arena); | |
| } | |
| TEST(GeneratedCode, UTF8) { | |
| const char invalid_utf8[] = "\xff"; | |
| const upb_StringView invalid_utf8_view = | |
| upb_StringView_FromDataAndSize(invalid_utf8, 1); | |
| upb_Arena* arena = upb_Arena_New(); | |
| upb_StringView serialized; | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg = | |
| protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg2; | |
| protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_string( | |
| msg, invalid_utf8_view); | |
| serialized.data = protobuf_test_messages_proto3_TestAllTypesProto3_serialize( | |
| msg, arena, &serialized.size); | |
| msg2 = protobuf_test_messages_proto3_TestAllTypesProto3_parse( | |
| serialized.data, serialized.size, arena); | |
| EXPECT_EQ(nullptr, msg2); | |
| upb_Arena_Free(arena); | |
| } | |
| static void check_string_map_empty( | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg) { | |
| size_t iter = kUpb_Map_Begin; | |
| EXPECT_EQ( | |
| 0, | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_size( | |
| msg)); | |
| upb_StringView key; | |
| upb_StringView val; | |
| EXPECT_FALSE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( | |
| msg, &key, &val, &iter)); | |
| } | |
| static void check_string_map_one_entry( | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg) { | |
| size_t iter; | |
| upb_StringView str; | |
| EXPECT_EQ( | |
| 1, | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_size( | |
| msg)); | |
| EXPECT_TRUE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_get( | |
| msg, test_str_view, &str)); | |
| EXPECT_TRUE(upb_StringView_IsEqual(str, test_str_view2)); | |
| EXPECT_FALSE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_get( | |
| msg, test_str_view3, &str)); | |
| /* Test that iteration reveals a single k/v pair in the map. */ | |
| iter = kUpb_Map_Begin; | |
| upb_StringView key; | |
| upb_StringView val; | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( | |
| msg, &key, &val, &iter); | |
| EXPECT_TRUE(upb_StringView_IsEqual(test_str_view, key)); | |
| EXPECT_TRUE(upb_StringView_IsEqual(test_str_view2, val)); | |
| EXPECT_FALSE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( | |
| msg, &key, &val, &iter)); | |
| } | |
| TEST(GeneratedCode, StringDoubleMap) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| upb_StringView serialized; | |
| upb_test_MapTest* msg = upb_test_MapTest_new(arena); | |
| upb_test_MapTest* msg2; | |
| double val; | |
| upb_test_MapTest_map_string_double_set(msg, test_str_view, 1.5, arena); | |
| ASSERT_NE(nullptr, msg); | |
| EXPECT_TRUE(upb_test_MapTest_map_string_double_get(msg, test_str_view, &val)); | |
| EXPECT_EQ(1.5, val); | |
| val = 0; | |
| serialized.data = upb_test_MapTest_serialize(msg, arena, &serialized.size); | |
| EXPECT_NE(nullptr, serialized.data); | |
| msg2 = upb_test_MapTest_parse(serialized.data, serialized.size, arena); | |
| ASSERT_NE(nullptr, msg2); | |
| EXPECT_TRUE( | |
| upb_test_MapTest_map_string_double_get(msg2, test_str_view, &val)); | |
| EXPECT_EQ(1.5, val); | |
| upb_Arena_Free(arena); | |
| } | |
| TEST(GeneratedCode, StringMap) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg = | |
| protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); | |
| size_t iter, count; | |
| check_string_map_empty(msg); | |
| /* Set map[test_str_view] = test_str_view2 */ | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_set( | |
| msg, test_str_view, test_str_view2, arena); | |
| check_string_map_one_entry(msg); | |
| /* Deleting a non-existent key does nothing. */ | |
| EXPECT_FALSE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_delete( | |
| msg, test_str_view3)); | |
| check_string_map_one_entry(msg); | |
| /* Deleting the key sets the map back to empty. */ | |
| EXPECT_TRUE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_delete( | |
| msg, test_str_view)); | |
| check_string_map_empty(msg); | |
| /* Set two keys this time: | |
| * map[test_str_view] = test_str_view2 | |
| * map[test_str_view3] = test_str_view4 | |
| */ | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_set( | |
| msg, test_str_view, test_str_view2, arena); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_set( | |
| msg, test_str_view3, test_str_view4, arena); | |
| /* Test iteration */ | |
| iter = kUpb_Map_Begin; | |
| count = 0; | |
| upb_StringView key; | |
| upb_StringView val; | |
| while ( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( | |
| msg, &key, &val, &iter)) { | |
| count++; | |
| if (upb_StringView_IsEqual(key, test_str_view)) { | |
| EXPECT_TRUE(upb_StringView_IsEqual(val, test_str_view2)); | |
| } else { | |
| EXPECT_TRUE(upb_StringView_IsEqual(key, test_str_view3)); | |
| EXPECT_TRUE(upb_StringView_IsEqual(val, test_str_view4)); | |
| } | |
| } | |
| EXPECT_EQ(2, count); | |
| /* Clearing the map goes back to empty. */ | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_clear(msg); | |
| check_string_map_empty(msg); | |
| upb_Arena_Free(arena); | |
| } | |
| static void check_int32_map_empty( | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg) { | |
| size_t iter = kUpb_Map_Begin; | |
| EXPECT_EQ( | |
| 0, protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_size( | |
| msg)); | |
| int32_t key; | |
| int32_t val; | |
| EXPECT_FALSE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( | |
| msg, &key, &val, &iter)); | |
| } | |
| static void check_int32_map_one_entry( | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg) { | |
| size_t iter; | |
| int32_t key; | |
| int32_t val; | |
| EXPECT_EQ( | |
| 1, protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_size( | |
| msg)); | |
| EXPECT_TRUE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_get( | |
| msg, test_int32, &val)); | |
| EXPECT_EQ(val, test_int32_2); | |
| EXPECT_FALSE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_get( | |
| msg, test_int32_3, &val)); | |
| /* Test that iteration reveals a single k/v pair in the map. */ | |
| iter = kUpb_Map_Begin; | |
| EXPECT_TRUE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( | |
| msg, &key, &val, &iter)); | |
| EXPECT_EQ(test_int32, key); | |
| EXPECT_EQ(test_int32_2, val); | |
| EXPECT_FALSE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( | |
| msg, &key, &val, &iter)); | |
| } | |
| TEST(GeneratedCode, Int32Map) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg = | |
| protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); | |
| size_t iter, count; | |
| check_int32_map_empty(msg); | |
| EXPECT_EQ( | |
| _protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_upb_map( | |
| msg), | |
| nullptr); | |
| upb_Map* mut_map = | |
| _protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_mutable_upb_map( | |
| msg, arena); | |
| EXPECT_NE(mut_map, nullptr); | |
| const upb_Map* const_map = | |
| _protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_upb_map( | |
| msg); | |
| EXPECT_EQ(mut_map, const_map); | |
| /* Set map[test_int32] = test_int32_2 */ | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_set( | |
| msg, test_int32, test_int32_2, arena); | |
| check_int32_map_one_entry(msg); | |
| /* Deleting a non-existent key does nothing. */ | |
| EXPECT_FALSE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_delete( | |
| msg, test_int32_3)); | |
| check_int32_map_one_entry(msg); | |
| /* Deleting the key sets the map back to empty. */ | |
| EXPECT_TRUE( | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_delete( | |
| msg, test_int32)); | |
| check_int32_map_empty(msg); | |
| /* Set two keys this time: | |
| * map[test_int32] = test_int32_2 | |
| * map[test_int32_3] = test_int32_4 | |
| */ | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_set( | |
| msg, test_int32, test_int32_2, arena); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_set( | |
| msg, test_int32_3, test_int32_4, arena); | |
| /* Test iteration */ | |
| iter = kUpb_Map_Begin; | |
| count = 0; | |
| int32_t key; | |
| int32_t val; | |
| while (protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( | |
| msg, &key, &val, &iter)) { | |
| count++; | |
| if (key == test_int32) { | |
| EXPECT_EQ(val, test_int32_2); | |
| } else { | |
| EXPECT_EQ(key, test_int32_3); | |
| EXPECT_EQ(val, test_int32_4); | |
| } | |
| } | |
| EXPECT_EQ(2, count); | |
| /* Clearing the map goes back to empty. */ | |
| protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_clear(msg); | |
| check_int32_map_empty(msg); | |
| upb_Arena_Free(arena); | |
| } | |
| TEST(GeneratedCode, TestRepeated) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg = | |
| protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); | |
| size_t size; | |
| const int* elems; | |
| EXPECT_EQ( | |
| _protobuf_test_messages_proto3_TestAllTypesProto3_repeated_int32_upb_array( | |
| msg, &size), | |
| nullptr); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_add_repeated_int32(msg, 5, | |
| arena); | |
| EXPECT_NE( | |
| _protobuf_test_messages_proto3_TestAllTypesProto3_repeated_int32_upb_array( | |
| msg, &size), | |
| nullptr); | |
| elems = protobuf_test_messages_proto3_TestAllTypesProto3_repeated_int32( | |
| msg, &size); | |
| EXPECT_EQ(size, 1); | |
| EXPECT_EQ(elems[0], 5); | |
| const upb_Array* arr = | |
| _protobuf_test_messages_proto3_TestAllTypesProto3_repeated_int32_upb_array( | |
| msg, &size); | |
| EXPECT_EQ(size, 1); | |
| upb_Array* mutable_arr = | |
| _protobuf_test_messages_proto3_TestAllTypesProto3_repeated_int32_mutable_upb_array( | |
| msg, &size, arena); | |
| EXPECT_EQ(mutable_arr, arr); | |
| EXPECT_EQ(upb_Array_Size(arr), 1); | |
| EXPECT_EQ(size, 1); | |
| upb_Arena_Free(arena); | |
| } | |
| TEST(GeneratedCode, Issue9440) { | |
| upb::Arena arena; | |
| upb_test_HelloRequest* msg = upb_test_HelloRequest_new(arena.ptr()); | |
| upb_test_HelloRequest_set_id(msg, 8); | |
| EXPECT_EQ(8, upb_test_HelloRequest_id(msg)); | |
| char str[] = "1"; | |
| upb_test_HelloRequest_set_version(msg, upb_StringView{str, strlen(str)}); | |
| EXPECT_EQ(8, upb_test_HelloRequest_id(msg)); | |
| } | |
| TEST(GeneratedCode, NullDecodeBuffer) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| protobuf_test_messages_proto3_TestAllTypesProto3* msg = | |
| protobuf_test_messages_proto3_TestAllTypesProto3_parse(nullptr, 0, arena); | |
| size_t size; | |
| ASSERT_NE(nullptr, msg); | |
| protobuf_test_messages_proto3_TestAllTypesProto3_serialize(msg, arena, &size); | |
| EXPECT_EQ(0, size); | |
| upb_Arena_Free(arena); | |
| } | |
| TEST(GeneratedCode, StatusTruncation) { | |
| int i, j; | |
| upb_Status status; | |
| upb_Status status2; | |
| for (i = 0; i < _kUpb_Status_MaxMessage + 20; i++) { | |
| char* msg = static_cast<char*>(malloc(i + 1)); | |
| int end; | |
| char ch = (i % 96) + 33; /* Cycle through printable chars. */ | |
| for (j = 0; j < i; j++) { | |
| msg[j] = ch; | |
| } | |
| msg[i] = '\0'; | |
| upb_Status_SetErrorMessage(&status, msg); | |
| upb_Status_SetErrorFormat(&status2, "%s", msg); | |
| end = MIN(i, _kUpb_Status_MaxMessage - 1); | |
| EXPECT_EQ(end, strlen(status.msg)); | |
| EXPECT_EQ(end, strlen(status2.msg)); | |
| for (j = 0; j < end; j++) { | |
| EXPECT_EQ(ch, status.msg[j]); | |
| EXPECT_EQ(ch, status2.msg[j]); | |
| } | |
| free(msg); | |
| } | |
| } | |
| TEST(GeneratedCode, ArenaUnaligned) { | |
| char buf1[1024]; | |
| // Force the pointer to be unaligned. | |
| uintptr_t low_bits = UPB_MALLOC_ALIGN - 1; | |
| char* unaligned_buf_ptr = (char*)((uintptr_t)buf1 | low_bits); | |
| upb_Arena* arena = upb_Arena_Init( | |
| unaligned_buf_ptr, &buf1[sizeof(buf1)] - unaligned_buf_ptr, nullptr); | |
| char* mem = static_cast<char*>(upb_Arena_Malloc(arena, 5)); | |
| EXPECT_EQ(0, reinterpret_cast<uintptr_t>(mem) & low_bits); | |
| upb_Arena_Free(arena); | |
| // Try the same, but with a size so small that aligning up will overflow. | |
| arena = upb_Arena_Init(unaligned_buf_ptr, 5, &upb_alloc_global); | |
| mem = static_cast<char*>(upb_Arena_Malloc(arena, 5)); | |
| EXPECT_EQ(0, reinterpret_cast<uintptr_t>(mem) & low_bits); | |
| upb_Arena_Free(arena); | |
| } | |
| TEST(GeneratedCode, Extensions) { | |
| upb::Arena arena; | |
| upb_test_ModelExtension1* extension1 = | |
| upb_test_ModelExtension1_new(arena.ptr()); | |
| upb_test_ModelExtension1_set_str(extension1, | |
| upb_StringView_FromString("Hello")); | |
| upb_test_ModelExtension2* extension2 = | |
| upb_test_ModelExtension2_new(arena.ptr()); | |
| upb_test_ModelExtension2_set_i(extension2, 5); | |
| upb_test_ModelWithExtensions* msg1 = | |
| upb_test_ModelWithExtensions_new(arena.ptr()); | |
| upb_test_ModelWithExtensions* msg2 = | |
| upb_test_ModelWithExtensions_new(arena.ptr()); | |
| // msg1: [extension1, extension2] | |
| upb_test_ModelExtension1_set_model_ext(msg1, extension1, arena.ptr()); | |
| upb_test_ModelExtension2_set_model_ext(msg1, extension2, arena.ptr()); | |
| // msg2: [extension2, extension1] | |
| upb_test_ModelExtension2_set_model_ext(msg2, extension2, arena.ptr()); | |
| upb_test_ModelExtension1_set_model_ext(msg2, extension1, arena.ptr()); | |
| size_t size1, size2; | |
| int opts = kUpb_EncodeOption_Deterministic; | |
| char* pb1 = upb_test_ModelWithExtensions_serialize_ex(msg1, opts, arena.ptr(), | |
| &size1); | |
| char* pb2 = upb_test_ModelWithExtensions_serialize_ex(msg2, opts, arena.ptr(), | |
| &size2); | |
| ASSERT_EQ(size1, size2); | |
| ASSERT_EQ(0, memcmp(pb1, pb2, size1)); | |
| } | |
| TEST(GeneratedCode, Maps) { | |
| upb::Arena arena; | |
| upb_test_ModelWithMaps* msg = upb_test_ModelWithMaps_new(arena.ptr()); | |
| auto sb = _upb_test_ModelWithMaps_map_sb_mutable_upb_map(msg, arena.ptr()); | |
| auto ss = _upb_test_ModelWithMaps_map_ss_mutable_upb_map(msg, arena.ptr()); | |
| auto ii = _upb_test_ModelWithMaps_map_ii_mutable_upb_map(msg, arena.ptr()); | |
| ASSERT_NE(sb, nullptr); | |
| ASSERT_NE(ss, nullptr); | |
| ASSERT_NE(ii, nullptr); | |
| upb_MessageValue key, val; | |
| key.str_val = test_str_view; | |
| val.str_val = test_str_view2; | |
| ASSERT_TRUE(upb_Map_Set(sb, key, val, arena.ptr())); | |
| } | |
| TEST(GeneratedCode, MapWithRequiredFields) { | |
| upb::Arena arena; | |
| upb_test_ModelWithMaps* msg = upb_test_ModelWithMaps_new(arena.ptr()); | |
| auto im_required = | |
| _upb_test_ModelWithMaps_map_im_required_mutable_upb_map(msg, arena.ptr()); | |
| ASSERT_NE(im_required, nullptr); | |
| upb_MessageValue key, val; | |
| key.int32_val = 0; | |
| val.msg_val = | |
| (const upb_Message*)upb_test_ModelWithRequiredFields_new(arena.ptr()); | |
| ASSERT_TRUE(upb_Map_Set(im_required, key, val, arena.ptr())); | |
| // Serializing fails if we are checking required fields, but succeeds if we | |
| // don't. | |
| size_t size; | |
| char* serialized = upb_test_ModelWithMaps_serialize_ex( | |
| msg, kUpb_EncodeOption_CheckRequired, arena.ptr(), &size); | |
| ASSERT_EQ(serialized, nullptr); | |
| serialized = upb_test_ModelWithMaps_serialize_ex(msg, 0, arena.ptr(), &size); | |
| ASSERT_NE(serialized, nullptr); | |
| // Likewise, parsing fails if we are checking required fields, but succeeds | |
| // if we don't. | |
| upb_test_ModelWithMaps* msg2 = upb_test_ModelWithMaps_parse_ex( | |
| serialized, size, nullptr, kUpb_DecodeOption_CheckRequired, arena.ptr()); | |
| ASSERT_EQ(msg2, nullptr); | |
| msg2 = upb_test_ModelWithMaps_parse_ex(serialized, size, nullptr, 0, | |
| arena.ptr()); | |
| ASSERT_NE(msg2, nullptr); | |
| } | |
| TEST(GeneratedCode, ReservedNames) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| upb_test_TestReserved* msg = upb_test_TestReserved_new(arena); | |
| // Check that we can call the mangled accessors. | |
| // If they weren't mangled, this would fail to compile because of | |
| // collisions with the message-level functions. | |
| upb_StringView val = upb_StringView_FromString("test"); | |
| upb_test_TestReserved_set_new_(msg, val); | |
| upb_test_TestReserved_set_parse_(msg, val); | |
| upb_test_TestReserved_set_parse_ex_(msg, val); | |
| upb_test_TestReserved_set_serialize_(msg, val); | |
| upb_test_TestReserved_set_serialize_ex_(msg, val); | |
| EXPECT_TRUE(upb_StringView_IsEqual(val, upb_test_TestReserved_new_(msg))); | |
| EXPECT_TRUE(upb_StringView_IsEqual(val, upb_test_TestReserved_parse_(msg))); | |
| EXPECT_TRUE( | |
| upb_StringView_IsEqual(val, upb_test_TestReserved_parse_ex_(msg))); | |
| EXPECT_TRUE( | |
| upb_StringView_IsEqual(val, upb_test_TestReserved_serialize_(msg))); | |
| EXPECT_TRUE( | |
| upb_StringView_IsEqual(val, upb_test_TestReserved_serialize_ex_(msg))); | |
| upb_Arena_Free(arena); | |
| } | |
| TEST(GeneratedCode, OneofMessageSwitch) { | |
| upb::Arena arena; | |
| upb_test_OneofWithMessages* msg = upb_test_OneofWithMessages_new(arena.ptr()); | |
| // Set msg1 | |
| upb_test_MessageName* msg1 = | |
| upb_test_OneofWithMessages_mutable_msg1(msg, arena.ptr()); | |
| upb_test_MessageName_set_field1(msg1, 10); | |
| // Now parse a buffer that sets msg2. | |
| upb_test_OneofWithMessages* msg_to_serialize = | |
| upb_test_OneofWithMessages_new(arena.ptr()); | |
| upb_test_MessageName* msg2_val = | |
| upb_test_OneofWithMessages_mutable_msg2(msg_to_serialize, arena.ptr()); | |
| upb_test_MessageName_set_field2(msg2_val, 20); | |
| size_t size; | |
| char* serialized = upb_test_OneofWithMessages_serialize(msg_to_serialize, | |
| arena.ptr(), &size); | |
| // Parse into the first msg. | |
| // Use a mini table to ensure we can use fasttable if enabled. | |
| upb_DecodeStatus status = upb_Decode(serialized, size, (upb_Message*)msg, | |
| &upb_0test__OneofWithMessages_msg_init, | |
| nullptr, 0, arena.ptr()); | |
| ASSERT_EQ(status, kUpb_DecodeStatus_Ok); | |
| // Now msg should have msg2 set, and msg1 should NOT be merged. | |
| EXPECT_EQ(upb_test_OneofWithMessages_oneof_field_case(msg), | |
| upb_test_OneofWithMessages_oneof_field_msg2); | |
| const upb_test_MessageName* msg2_res = upb_test_OneofWithMessages_msg2(msg); | |
| EXPECT_EQ(upb_test_MessageName_field2(msg2_res), 20); | |
| EXPECT_EQ(upb_test_MessageName_field1(msg2_res), 0); | |
| } | |
| TEST(GeneratedCode, MutablePrefix) { | |
| upb_Arena* arena = upb_Arena_New(); | |
| upb_test_TestReserved* msg = upb_test_TestReserved_new(arena); | |
| // mutable_foo should be mangled to mutable_foo_ because foo exists. | |
| upb_test_TestReserved* sub = upb_test_TestReserved_new(arena); | |
| upb_test_TestReserved_set_mutable_foo_(msg, sub); | |
| EXPECT_EQ(sub, upb_test_TestReserved_mutable_foo_(msg)); | |
| // The actual "mutable" accessor for field "foo" should still be available. | |
| upb_test_TestReserved* mutable_foo = | |
| upb_test_TestReserved_mutable_foo(msg, arena); | |
| EXPECT_NE(nullptr, mutable_foo); | |
| upb_Arena_Free(arena); | |
| } |