Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
340 lines
14 KiB
340 lines
14 KiB
// 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 mini table accessors. |
|
* |
|
* Messages are created and mutated using generated code, and then |
|
* accessed through reflective APIs exposed through mini table accessors. |
|
*/ |
|
|
|
#include "upb/message/copy.h" |
|
|
|
#include <cstddef> |
|
#include <cstdint> |
|
#include <cstring> |
|
#include <string> |
|
#include <vector> |
|
|
|
#include <gtest/gtest.h> |
|
#include "google/protobuf/test_messages_proto2.upb.h" |
|
#include "google/protobuf/test_messages_proto2.upb_minitable.h" |
|
#include "upb/base/string_view.h" |
|
#include "upb/base/upcast.h" |
|
#include "upb/mem/arena.h" |
|
#include "upb/message/accessors.h" |
|
#include "upb/message/internal/message.h" |
|
#include "upb/message/map.h" |
|
#include "upb/message/message.h" |
|
#include "upb/mini_table/field.h" |
|
#include "upb/mini_table/message.h" |
|
#include "upb/wire/encode.h" |
|
|
|
// Must be last. |
|
#include "upb/port/def.inc" |
|
|
|
namespace { |
|
|
|
// Proto2 test messages field numbers used for reflective access. |
|
const uint32_t kFieldOptionalInt32 = 1; |
|
const uint32_t kFieldOptionalString = 14; |
|
const uint32_t kFieldOptionalNestedMessage = 18; |
|
|
|
const char kTestStr1[] = "Hello1"; |
|
const char kTestStr2[] = "HelloWorld2"; |
|
const int32_t kTestInt32 = 567; |
|
const int32_t kTestNestedInt32 = 123; |
|
|
|
const upb_MiniTableField* find_proto2_field(int field_number) { |
|
return upb_MiniTable_FindFieldByNumber( |
|
&protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init, |
|
field_number); |
|
} |
|
|
|
TEST(GeneratedCode, DeepCloneMessageScalarAndString) { |
|
upb_Arena* source_arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2* msg = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_new(source_arena); |
|
const upb_MiniTableField* optional_int32_field = |
|
find_proto2_field(kFieldOptionalInt32); |
|
const upb_MiniTableField* optional_string_field = |
|
find_proto2_field(kFieldOptionalString); |
|
upb_Message_SetInt32(UPB_UPCAST(msg), optional_int32_field, kTestInt32, |
|
nullptr); |
|
char* string_in_arena = |
|
(char*)upb_Arena_Malloc(source_arena, sizeof(kTestStr1)); |
|
memcpy(string_in_arena, kTestStr1, sizeof(kTestStr1)); |
|
upb_Message_SetString( |
|
UPB_UPCAST(msg), optional_string_field, |
|
upb_StringView_FromDataAndSize(string_in_arena, sizeof(kTestStr1) - 1), |
|
source_arena); |
|
upb_Arena* arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2* clone = |
|
(protobuf_test_messages_proto2_TestAllTypesProto2*)upb_Message_DeepClone( |
|
UPB_UPCAST(msg), |
|
&protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init, |
|
arena); |
|
// After cloning overwrite values and destroy source arena for MSAN. |
|
memset(string_in_arena, 0, sizeof(kTestStr1)); |
|
upb_Arena_Free(source_arena); |
|
EXPECT_TRUE( |
|
upb_Message_HasBaseField(UPB_UPCAST(clone), optional_int32_field)); |
|
EXPECT_EQ(upb_Message_GetInt32(UPB_UPCAST(clone), optional_int32_field, 0), |
|
kTestInt32); |
|
EXPECT_TRUE( |
|
upb_Message_HasBaseField(UPB_UPCAST(clone), optional_string_field)); |
|
EXPECT_EQ(upb_Message_GetString(UPB_UPCAST(clone), optional_string_field, |
|
upb_StringView_FromDataAndSize(nullptr, 0)) |
|
.size, |
|
sizeof(kTestStr1) - 1); |
|
EXPECT_TRUE(upb_StringView_IsEqual( |
|
upb_Message_GetString(UPB_UPCAST(clone), optional_string_field, |
|
upb_StringView_FromDataAndSize(nullptr, 0)), |
|
upb_StringView_FromString(kTestStr1))); |
|
upb_Arena_Free(arena); |
|
} |
|
|
|
TEST(GeneratedCode, DeepCloneMessageSubMessage) { |
|
upb_Arena* source_arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2* msg = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_new(source_arena); |
|
const upb_MiniTableField* nested_message_field = |
|
find_proto2_field(kFieldOptionalNestedMessage); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage* nested = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_new( |
|
source_arena); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_set_a( |
|
nested, kTestNestedInt32); |
|
upb_Message_SetMessage( |
|
UPB_UPCAST(msg), |
|
&protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init, |
|
nested_message_field, UPB_UPCAST(nested)); |
|
upb_Arena* arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2* clone = |
|
(protobuf_test_messages_proto2_TestAllTypesProto2*)upb_Message_DeepClone( |
|
UPB_UPCAST(msg), |
|
&protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init, |
|
arena); |
|
// After cloning overwrite values and destroy source arena for MSAN. |
|
protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_set_a(nested, |
|
0); |
|
upb_Arena_Free(source_arena); |
|
EXPECT_TRUE( |
|
upb_Message_HasBaseField(UPB_UPCAST(clone), nested_message_field)); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage* |
|
cloned_nested = |
|
(protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage*) |
|
upb_Message_GetMessage(UPB_UPCAST(clone), nested_message_field); |
|
EXPECT_EQ(protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_a( |
|
cloned_nested), |
|
kTestNestedInt32); |
|
upb_Arena_Free(arena); |
|
} |
|
|
|
TEST(GeneratedCode, DeepCloneMessageArrayField) { |
|
upb_Arena* source_arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2* msg = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_new(source_arena); |
|
std::vector<int32_t> array_test_values = {3, 4, 5}; |
|
for (int32_t value : array_test_values) { |
|
ASSERT_TRUE( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_add_repeated_int32( |
|
msg, value, source_arena)); |
|
} |
|
upb_Arena* arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2* clone = |
|
(protobuf_test_messages_proto2_TestAllTypesProto2*)upb_Message_DeepClone( |
|
UPB_UPCAST(msg), |
|
&protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init, |
|
arena); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_clear_repeated_sint32(msg); |
|
upb_Arena_Free(source_arena); |
|
size_t cloned_size = 0; |
|
const int32_t* cloned_values = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_repeated_int32( |
|
clone, &cloned_size); |
|
EXPECT_EQ(cloned_size, array_test_values.size()); |
|
int index = 0; |
|
for (int32_t value : array_test_values) { |
|
EXPECT_EQ(cloned_values[index++], value); |
|
} |
|
upb_Arena_Free(arena); |
|
} |
|
|
|
TEST(GeneratedCode, DeepCloneMessageMapField) { |
|
upb_Arena* source_arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2* msg = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_new(source_arena); |
|
ASSERT_TRUE( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_map_int32_double_set( |
|
msg, 12, 1200.5, source_arena)); |
|
ASSERT_TRUE( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_map_string_string_set( |
|
msg, upb_StringView_FromString("key1"), |
|
upb_StringView_FromString("value1"), source_arena)); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage* nested = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_new( |
|
source_arena); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_set_a( |
|
nested, kTestNestedInt32); |
|
ASSERT_TRUE( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_map_string_nested_message_set( |
|
msg, upb_StringView_FromString("nestedkey1"), nested, source_arena)); |
|
|
|
upb_Arena* arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2* clone = |
|
(protobuf_test_messages_proto2_TestAllTypesProto2*)upb_Message_DeepClone( |
|
UPB_UPCAST(msg), |
|
&protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init, |
|
arena); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_set_a(nested, |
|
0); |
|
upb_Arena_Free(source_arena); |
|
size_t iter = kUpb_Map_Begin; |
|
// Test map<int32, int32>. |
|
const protobuf_test_messages_proto2_TestAllTypesProto2_MapInt32DoubleEntry* |
|
int32_double_entry = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_map_int32_double_next( |
|
clone, &iter); |
|
ASSERT_NE(int32_double_entry, nullptr); |
|
EXPECT_EQ( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MapInt32DoubleEntry_key( |
|
int32_double_entry), |
|
12); |
|
EXPECT_EQ( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MapInt32DoubleEntry_value( |
|
int32_double_entry), |
|
1200.5); |
|
// Test map<string, string>. |
|
iter = kUpb_Map_Begin; |
|
const protobuf_test_messages_proto2_TestAllTypesProto2_MapStringStringEntry* |
|
string_string_entry = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_map_string_string_next( |
|
clone, &iter); |
|
ASSERT_NE(string_string_entry, nullptr); |
|
EXPECT_TRUE(upb_StringView_IsEqual( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MapStringStringEntry_key( |
|
string_string_entry), |
|
upb_StringView_FromString("key1"))); |
|
EXPECT_TRUE(upb_StringView_IsEqual( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MapStringStringEntry_value( |
|
string_string_entry), |
|
upb_StringView_FromString("value1"))); |
|
// Test map<string, NestedMessage>. |
|
iter = kUpb_Map_Begin; |
|
const protobuf_test_messages_proto2_TestAllTypesProto2_MapStringNestedMessageEntry* |
|
nested_message_entry = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_map_string_nested_message_next( |
|
clone, &iter); |
|
ASSERT_NE(nested_message_entry, nullptr); |
|
EXPECT_TRUE(upb_StringView_IsEqual( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MapStringNestedMessageEntry_key( |
|
nested_message_entry), |
|
upb_StringView_FromString("nestedkey1"))); |
|
const protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage* |
|
cloned_nested = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MapStringNestedMessageEntry_value( |
|
nested_message_entry); |
|
ASSERT_NE(cloned_nested, nullptr); |
|
EXPECT_EQ(protobuf_test_messages_proto2_TestAllTypesProto2_NestedMessage_a( |
|
cloned_nested), |
|
kTestNestedInt32); |
|
upb_Arena_Free(arena); |
|
} |
|
|
|
TEST(GeneratedCode, DeepCloneMessageExtensions) { |
|
// Alloc and fill in test message with extension. |
|
upb_Arena* source_arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrect* msg = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrect_new( |
|
source_arena); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1* |
|
ext1 = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_new( |
|
source_arena); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_set_str( |
|
ext1, upb_StringView_FromString(kTestStr1)); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_set_message_set_extension( |
|
msg, ext1, source_arena); |
|
// Create clone. |
|
upb_Arena* arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrect* clone = |
|
(protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrect*) |
|
upb_Message_DeepClone( |
|
UPB_UPCAST(msg), |
|
&protobuf_0test_0messages__proto2__TestAllTypesProto2__MessageSetCorrect_msg_init, |
|
arena); |
|
|
|
// Mutate original extension. |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_set_str( |
|
ext1, upb_StringView_FromString(kTestStr2)); |
|
upb_Arena_Free(source_arena); |
|
|
|
const protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1* |
|
cloned_ext = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_message_set_extension( |
|
clone); |
|
ASSERT_NE(cloned_ext, nullptr); |
|
EXPECT_TRUE(upb_StringView_IsEqual( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_MessageSetCorrectExtension1_str( |
|
cloned_ext), |
|
upb_StringView_FromString(kTestStr1))); |
|
upb_Arena_Free(arena); |
|
} |
|
|
|
TEST(GeneratedCode, DeepCloneMessageWithUnknowns) { |
|
upb_Arena* source_arena = upb_Arena_New(); |
|
upb_Arena* unknown_arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2* msg = |
|
protobuf_test_messages_proto2_TestAllTypesProto2_new(source_arena); |
|
ASSERT_TRUE( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_map_int32_double_set( |
|
msg, 12, 1200.5, source_arena)); |
|
ASSERT_TRUE( |
|
protobuf_test_messages_proto2_TestAllTypesProto2_map_string_string_set( |
|
msg, upb_StringView_FromString("key1"), |
|
upb_StringView_FromString("value1"), source_arena)); |
|
// Create unknown data. |
|
protobuf_test_messages_proto2_UnknownToTestAllTypes* unknown_source = |
|
protobuf_test_messages_proto2_UnknownToTestAllTypes_new(unknown_arena); |
|
protobuf_test_messages_proto2_UnknownToTestAllTypes_set_optional_bool( |
|
unknown_source, true); |
|
protobuf_test_messages_proto2_UnknownToTestAllTypes_set_optional_int32( |
|
unknown_source, 123); |
|
// Encode unknown message to bytes. |
|
size_t len; |
|
char* data; |
|
upb_Arena* encode_arena = upb_Arena_New(); |
|
upb_EncodeStatus status = upb_Encode( |
|
UPB_UPCAST(unknown_source), |
|
&protobuf_0test_0messages__proto2__UnknownToTestAllTypes_msg_init, |
|
kUpb_EncodeOption_CheckRequired, encode_arena, &data, &len); |
|
ASSERT_EQ(status, kUpb_EncodeStatus_Ok); |
|
std::string unknown_data(data, len); |
|
// Add unknown data. |
|
UPB_PRIVATE(_upb_Message_AddUnknown) |
|
(UPB_UPCAST(msg), data, len, source_arena); |
|
// Create clone. |
|
upb_Arena* clone_arena = upb_Arena_New(); |
|
protobuf_test_messages_proto2_TestAllTypesProto2* clone = |
|
(protobuf_test_messages_proto2_TestAllTypesProto2*)upb_Message_DeepClone( |
|
UPB_UPCAST(msg), |
|
&protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init, |
|
clone_arena); |
|
upb_Arena_Free(source_arena); |
|
upb_Arena_Free(unknown_arena); |
|
upb_Arena_Free(encode_arena); |
|
// Read unknown data from clone and verify. |
|
size_t cloned_length; |
|
const char* cloned_unknown_data = |
|
upb_Message_GetUnknown(UPB_UPCAST(clone), &cloned_length); |
|
EXPECT_EQ(cloned_length, len); |
|
EXPECT_EQ(memcmp(cloned_unknown_data, unknown_data.c_str(), cloned_length), |
|
0); |
|
upb_Arena_Free(clone_arena); |
|
} |
|
|
|
} // namespace
|
|
|