1
2 #include <cstddef>
3 #include <cstdio>
4 #include <string>
5 #include <vector>
6
7 #include <gtest/gtest.h>
8 #include "google/protobuf/test_messages_proto2.upb.h"
9 #include "google/protobuf/test_messages_proto2.upb_minitable.h"
10 #include "upb/base/string_view.h"
11 #include "upb/base/upcast.h"
12 #include "upb/mem/arena.h"
13 #include "upb/message/compare.h"
14 #include "upb/mini_table/message.h"
15 #include "upb/wire/decode.h"
16 #include "upb/wire/encode.h"
17
18 namespace {
19
20 static const upb_MiniTable* kTestMiniTable =
21 &protobuf_0test_0messages__proto2__TestAllTypesProto2_msg_init;
22
TestEncodeDecodeRoundTrip(upb_Arena * arena,std::vector<protobuf_test_messages_proto2_TestAllTypesProto2 * > msgs)23 static void TestEncodeDecodeRoundTrip(
24 upb_Arena* arena,
25 std::vector<protobuf_test_messages_proto2_TestAllTypesProto2*> msgs) {
26 // Encode all of the messages and put their serializations contiguously.
27 std::string s;
28 for (auto msg : msgs) {
29 char* buf;
30 size_t size;
31 ASSERT_TRUE(upb_EncodeLengthPrefixed(UPB_UPCAST(msg), kTestMiniTable, 0,
32 arena, &buf,
33 &size) == kUpb_EncodeStatus_Ok);
34 ASSERT_GT(size, 0); // Even empty messages are 1 byte in this encoding.
35 s.append(std::string(buf, size));
36 }
37
38 // Now decode all of the messages contained in the contiguous block.
39 std::vector<protobuf_test_messages_proto2_TestAllTypesProto2*> decoded;
40 while (!s.empty()) {
41 protobuf_test_messages_proto2_TestAllTypesProto2* msg =
42 protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
43 size_t num_bytes_read;
44 ASSERT_TRUE(upb_DecodeLengthPrefixed(
45 s.data(), s.length(), UPB_UPCAST(msg), &num_bytes_read,
46 kTestMiniTable, nullptr, 0, arena) == kUpb_DecodeStatus_Ok);
47 ASSERT_GT(num_bytes_read, 0);
48 decoded.push_back(msg);
49 s = s.substr(num_bytes_read);
50 }
51
52 // Make sure that the values round tripped correctly.
53 ASSERT_EQ(msgs.size(), decoded.size());
54 for (size_t i = 0; i < msgs.size(); ++i) {
55 ASSERT_TRUE(upb_Message_IsEqual(UPB_UPCAST(msgs[i]), UPB_UPCAST(decoded[i]),
56 kTestMiniTable, 0));
57 }
58 }
59
TEST(LengthPrefixedTest,OneEmptyMessage)60 TEST(LengthPrefixedTest, OneEmptyMessage) {
61 upb_Arena* arena = upb_Arena_New();
62 protobuf_test_messages_proto2_TestAllTypesProto2* msg =
63 protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
64 TestEncodeDecodeRoundTrip(arena, {msg});
65 upb_Arena_Free(arena);
66 }
67
TEST(LengthPrefixedTest,AFewMessages)68 TEST(LengthPrefixedTest, AFewMessages) {
69 upb_Arena* arena = upb_Arena_New();
70 protobuf_test_messages_proto2_TestAllTypesProto2* a =
71 protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
72 protobuf_test_messages_proto2_TestAllTypesProto2* b =
73 protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
74 protobuf_test_messages_proto2_TestAllTypesProto2* c =
75 protobuf_test_messages_proto2_TestAllTypesProto2_new(arena);
76
77 protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_bool(a, true);
78 protobuf_test_messages_proto2_TestAllTypesProto2_set_optional_int32(b, 1);
79 protobuf_test_messages_proto2_TestAllTypesProto2_set_oneof_string(
80 c, upb_StringView_FromString("string"));
81
82 TestEncodeDecodeRoundTrip(arena, {a, b, c});
83 upb_Arena_Free(arena);
84 }
85
86 } // namespace
87