blob: 0ea1f11887dfd7f610feb728fce75aa7fa2fc238 [file] [log] [blame]
#include <cstddef>
#include <cstdio>
#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/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<protobuf_test_messages_proto2_TestAllTypesProto2*> 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<protobuf_test_messages_proto2_TestAllTypesProto2*> 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