#include #include #include #include #include #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/compare.h" #include "upb/mini_table/message.h" #include "upb/wire/decode.h" #include "upb/wire/encode.h" namespace { static const upb_MiniTable* kTestMiniTable = &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init; static void TestEncodeDecodeRoundTrip( upb_Arena* arena, std::vector msgs) { // Encode all of the messages and put their serializations contiguously. std::string s; for (auto msg : msgs) { char* buf; size_t size; ASSERT_TRUE(upb_EncodeLengthPrefixed(UPB_UPCAST(msg), kTestMiniTable, 0, arena, &buf, &size) == kUpb_EncodeStatus_Ok); ASSERT_GT(size, 0); // Even empty messages are 1 byte in this encoding. s.append(std::string(buf, size)); } // Now decode all of the messages contained in the contiguous block. std::vector decoded; while (!s.empty()) { protobuf_test_messages_proto2_TestAllTypesProto2* msg = protobuf_test_messages_proto2_TestAllTypesProto2_new(arena); size_t num_bytes_read; ASSERT_TRUE(upb_DecodeLengthPrefixed( s.data(), s.length(), UPB_UPCAST(msg), &num_bytes_read, kTestMiniTable, nullptr, 0, arena) == kUpb_DecodeStatus_Ok); ASSERT_GT(num_bytes_read, 0); decoded.push_back(msg); s = s.substr(num_bytes_read); } // Make sure that the values round tripped correctly. ASSERT_EQ(msgs.size(), decoded.size()); for (size_t i = 0; i < msgs.size(); ++i) { ASSERT_TRUE(upb_Message_IsEqual(UPB_UPCAST(msgs[i]), UPB_UPCAST(decoded[i]), kTestMiniTable, 0)); } } TEST(LengthPrefixedTest, OneEmptyMessage) { upb_Arena* arena = upb_Arena_New(); protobuf_test_messages_proto2_TestAllTypesProto2* msg = protobuf_test_messages_proto2_TestAllTypesProto2_new(arena); TestEncodeDecodeRoundTrip(arena, {msg}); upb_Arena_Free(arena); } TEST(LengthPrefixedTest, AFewMessages) { upb_Arena* arena = upb_Arena_New(); protobuf_test_messages_proto2_TestAllTypesProto2* a = protobuf_test_messages_proto2_TestAllTypesProto2_new(arena); protobuf_test_messages_proto2_TestAllTypesProto2* b = protobuf_test_messages_proto2_TestAllTypesProto2_new(arena); protobuf_test_messages_proto2_TestAllTypesProto2* c = protobuf_test_messages_proto2_TestAllTypesProto2_new(arena); protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_bool(a, true); protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_int32(b, 1); protobuf_test_messages_proto2_TestAllTypesProto2_set_oneof_string( c, upb_StringView_FromString("string")); TestEncodeDecodeRoundTrip(arena, {a, b, c}); upb_Arena_Free(arena); } } // namespace