• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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