mirror of https://github.com/grpc/grpc.git
[C++] Added a cord support to gRPC protobuf serializer (#32617)
As Protobuf is going to support Cord to reduce memory copy when [de]serializing Cord fields, gRPC is going to leverage it. This implementation is based on the internal one but it's slightly modified to use the public APIs of Cord. onlypull/32897/head
parent
9128604b03
commit
c523bdac1e
10 changed files with 445 additions and 0 deletions
@ -0,0 +1,88 @@ |
||||
//
|
||||
// Copyright 2023 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#include <gtest/gtest.h> |
||||
|
||||
#include <grpcpp/support/byte_buffer.h> |
||||
#include <grpcpp/support/proto_buffer_reader.h> |
||||
|
||||
#include "test/core/util/test_config.h" |
||||
|
||||
namespace grpc { |
||||
namespace { |
||||
|
||||
void ExpectBufferEqual(const ByteBuffer& a, const ByteBuffer& b) { |
||||
Slice a_slice; |
||||
EXPECT_TRUE(a.DumpToSingleSlice(&a_slice).ok()); |
||||
Slice b_slice; |
||||
EXPECT_TRUE(b.DumpToSingleSlice(&b_slice).ok()); |
||||
EXPECT_EQ(a_slice.size(), b_slice.size()); |
||||
EXPECT_EQ(memcmp(a_slice.begin(), b_slice.begin(), a_slice.size()), 0); |
||||
} |
||||
|
||||
TEST(ProtoBufferReaderTest, Next) { |
||||
Slice slices[] = { |
||||
Slice(std::string(128, 'a')), |
||||
Slice(std::string(256, 'b')), |
||||
}; |
||||
ByteBuffer buffer(slices, 2); |
||||
ProtoBufferReader reader(&buffer); |
||||
// read all data from buffer
|
||||
std::vector<Slice> read_slices; |
||||
int read_size = 0; |
||||
while (read_size < static_cast<int>(buffer.Length())) { |
||||
const void* data; |
||||
int size = 0; |
||||
EXPECT_TRUE(reader.Next(&data, &size)); |
||||
read_slices.emplace_back(data, size); |
||||
read_size += size; |
||||
} |
||||
EXPECT_EQ(reader.ByteCount(), read_size); |
||||
// check if read data is equal to original data
|
||||
ByteBuffer read_buffer(&*read_slices.begin(), read_slices.size()); |
||||
ExpectBufferEqual(read_buffer, buffer); |
||||
} |
||||
|
||||
#ifdef GRPC_PROTOBUF_CORD_SUPPORT_ENABLED |
||||
|
||||
TEST(ProtoBufferReaderTest, ReadCord) { |
||||
std::string str1 = std::string(128, 'a'); |
||||
std::string str2 = std::string(256, 'b'); |
||||
Slice slices[] = {Slice(str1), Slice(str2)}; |
||||
ByteBuffer buffer(slices, 2); |
||||
ProtoBufferReader reader(&buffer); |
||||
// read cords from buffer
|
||||
absl::Cord cord1; |
||||
reader.ReadCord(&cord1, str1.size()); |
||||
EXPECT_EQ(cord1.size(), str1.size()); |
||||
EXPECT_EQ(std::string(cord1), str1); |
||||
absl::Cord cord2; |
||||
reader.ReadCord(&cord2, str2.size()); |
||||
EXPECT_EQ(cord2.size(), str2.size()); |
||||
EXPECT_EQ(std::string(cord2), str2); |
||||
EXPECT_EQ(reader.ByteCount(), cord1.size() + cord2.size()); |
||||
} |
||||
|
||||
#endif // GRPC_PROTOBUF_CORD_SUPPORT_ENABLED
|
||||
|
||||
} // namespace
|
||||
} // namespace grpc
|
||||
|
||||
int main(int argc, char** argv) { |
||||
grpc::testing::TestEnvironment env(&argc, argv); |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
return RUN_ALL_TESTS(); |
||||
} |
@ -0,0 +1,80 @@ |
||||
//
|
||||
// Copyright 2023 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#include <gtest/gtest.h> |
||||
|
||||
#include <grpcpp/support/byte_buffer.h> |
||||
#include <grpcpp/support/proto_buffer_writer.h> |
||||
|
||||
#include "test/core/util/test_config.h" |
||||
|
||||
namespace grpc { |
||||
namespace { |
||||
|
||||
TEST(ProtoBufferWriterTest, Next) { |
||||
ByteBuffer buffer; |
||||
ProtoBufferWriter writer(&buffer, 16, 256); |
||||
// 1st next
|
||||
void* data1; |
||||
int size1; |
||||
EXPECT_TRUE(writer.Next(&data1, &size1)); |
||||
EXPECT_GT(size1, 0); |
||||
memset(data1, 1, size1); |
||||
// 2nd next
|
||||
void* data2; |
||||
int size2; |
||||
EXPECT_TRUE(writer.Next(&data2, &size2)); |
||||
EXPECT_GT(size2, 0); |
||||
memset(data2, 2, size2); |
||||
// Done
|
||||
EXPECT_EQ(writer.ByteCount(), size1 + size2); |
||||
EXPECT_EQ(buffer.Length(), size1 + size2); |
||||
Slice slice; |
||||
EXPECT_TRUE(buffer.DumpToSingleSlice(&slice).ok()); |
||||
EXPECT_EQ(memcmp(slice.begin(), data1, size1), 0); |
||||
EXPECT_EQ(memcmp(slice.begin() + size1, data2, size2), 0); |
||||
} |
||||
|
||||
#ifdef GRPC_PROTOBUF_CORD_SUPPORT_ENABLED |
||||
|
||||
TEST(ProtoBufferWriterTest, WriteCord) { |
||||
ByteBuffer buffer; |
||||
ProtoBufferWriter writer(&buffer, 16, 4096); |
||||
// Cord
|
||||
absl::Cord cord; |
||||
std::string str1 = std::string(1024, 'a'); |
||||
cord.Append(str1); |
||||
std::string str2 = std::string(1024, 'b'); |
||||
cord.Append(str2); |
||||
writer.WriteCord(cord); |
||||
// Done
|
||||
EXPECT_EQ(writer.ByteCount(), str1.size() + str2.size()); |
||||
EXPECT_EQ(buffer.Length(), str1.size() + str2.size()); |
||||
Slice slice; |
||||
EXPECT_TRUE(buffer.DumpToSingleSlice(&slice).ok()); |
||||
EXPECT_EQ(memcmp(slice.begin() + str1.size(), str2.c_str(), str2.size()), 0); |
||||
} |
||||
|
||||
#endif // GRPC_PROTOBUF_CORD_SUPPORT_ENABLED
|
||||
|
||||
} // namespace
|
||||
} // namespace grpc
|
||||
|
||||
int main(int argc, char** argv) { |
||||
grpc::testing::TestEnvironment env(&argc, argv); |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
return RUN_ALL_TESTS(); |
||||
} |
Loading…
Reference in new issue