341 lines
9.7 KiB
C++
341 lines
9.7 KiB
C++
#include "tile/base/buffer.h"
|
|
|
|
#include "tile/base/slice.h"
|
|
#include "tile/init/override_flag.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include <string>
|
|
|
|
#define BUFFER_BLOCK_SIZE "4K"
|
|
TILE_OVERRIDE_FLAG(tile_buffer_block_size, BUFFER_BLOCK_SIZE);
|
|
|
|
namespace tile {
|
|
|
|
namespace {
|
|
|
|
PolymorphicBuffer
|
|
MakeNativeBuffer(Slice s)
|
|
{
|
|
auto buffer = MakeNativeBufferBlock();
|
|
memcpy(buffer->mutable_data(), s.data(), s.size());
|
|
return PolymorphicBuffer(buffer, 0, s.size());
|
|
}
|
|
|
|
}// namespace
|
|
|
|
TEST(CreateBufferSlow, All)
|
|
{
|
|
static const auto kData = Slice("sadfas234sadf-/+8sdaf sd f~!#");
|
|
auto nb = CreateBufferSlow(kData);
|
|
ASSERT_EQ(kData, nb.FirstContiguous().data());
|
|
ASSERT_EQ(kData, FlattenSlow(nb));
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, Cut)
|
|
{
|
|
NoncontiguousBuffer nb;
|
|
nb.Append(CreateBufferSlow("asdf"));
|
|
auto r = nb.Cut(3);
|
|
ASSERT_EQ(1, nb.ByteSize());
|
|
ASSERT_EQ("f", FlattenSlow(nb));
|
|
ASSERT_EQ(3, r.ByteSize());
|
|
ASSERT_EQ("asd", FlattenSlow(r));
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, Cut1)
|
|
{
|
|
NoncontiguousBuffer nb;
|
|
nb.Append(CreateBufferSlow("asdf"));
|
|
auto r = nb.Cut(4);
|
|
ASSERT_TRUE(nb.Empty());
|
|
ASSERT_EQ(4, r.ByteSize());
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, Cut2)
|
|
{
|
|
NoncontiguousBuffer nb;
|
|
nb.Append(MakeNativeBuffer("asdf"));
|
|
nb.Append(MakeNativeBuffer("asdf"));
|
|
auto r = nb.Cut(4);
|
|
ASSERT_EQ(4, nb.ByteSize());
|
|
ASSERT_EQ(4, r.ByteSize());
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, Cut3)
|
|
{
|
|
NoncontiguousBuffer nb;
|
|
nb.Append(MakeNativeBuffer("asdf"));
|
|
nb.Append(MakeNativeBuffer("asdf"));
|
|
auto r = nb.Cut(8);
|
|
ASSERT_TRUE(nb.Empty());
|
|
ASSERT_EQ(8, r.ByteSize());
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, Cut4)
|
|
{
|
|
auto nb = CreateBufferSlow("asdfasf2345sfsdfdf");
|
|
auto nb2 = nb;
|
|
ASSERT_EQ(FlattenSlow(nb), FlattenSlow(nb2));
|
|
NoncontiguousBuffer splited;
|
|
splited.Append(nb.Cut(1));
|
|
splited.Append(nb.Cut(2));
|
|
splited.Append(nb.Cut(3));
|
|
splited.Append(nb.Cut(4));
|
|
splited.Append(std::move(nb));
|
|
ASSERT_EQ(FlattenSlow(nb2), FlattenSlow(splited));
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, Skip)
|
|
{
|
|
NoncontiguousBuffer splited;
|
|
splited.Append(CreateBufferSlow("asdf"));
|
|
splited.Append(CreateBufferSlow("asdf"));
|
|
splited.Append(CreateBufferSlow("asdf"));
|
|
splited.Append(CreateBufferSlow("asdf"));
|
|
splited.Append(CreateBufferSlow("asdf"));
|
|
splited.Append(CreateBufferSlow("asdf"));
|
|
splited.Append(CreateBufferSlow("asdf"));
|
|
splited.Append(CreateBufferSlow("asdf"));
|
|
splited.Skip(32);
|
|
ASSERT_EQ(0, splited.ByteSize());
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, Skip2)
|
|
{
|
|
NoncontiguousBuffer buffer;
|
|
EXPECT_TRUE(buffer.Empty());
|
|
buffer.Skip(0);// Don't crash.
|
|
EXPECT_TRUE(buffer.Empty());
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, FlattenSlow)
|
|
{
|
|
NoncontiguousBuffer nb;
|
|
nb.Append(MakeNativeBuffer("asd4234"));
|
|
nb.Append(MakeNativeBuffer("aXsdfsadfasdf2342"));
|
|
ASSERT_EQ("asd4234aXs", FlattenSlow(nb, 10));
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, FlattenToSlow)
|
|
{
|
|
struct C {
|
|
std::uint64_t ll;
|
|
int i;
|
|
bool f;
|
|
};
|
|
|
|
NoncontiguousBuffer nb;
|
|
nb.Append(MakeNativeBuffer(Slice("\x12\x34\x56\x78\x9a\xbc\xde\xf0", 8)));
|
|
nb.Append(MakeNativeBuffer(Slice("\x12\x34\x56\x78", 4)));
|
|
nb.Append(MakeNativeBuffer(Slice("\x1", 1)));
|
|
nb.Append(MakeNativeBuffer(Slice("\x00\x00\x00", 3)));// Padding
|
|
C c;
|
|
FlattenToSlow(nb, &c, sizeof(C));
|
|
ASSERT_EQ(0xf0debc9a78563412, c.ll);
|
|
ASSERT_EQ(0x78563412, c.i);
|
|
ASSERT_EQ(true, c.f);
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, FlattenSlowUntil)
|
|
{
|
|
NoncontiguousBuffer nb;
|
|
nb.Append(MakeNativeBuffer("asd4234"));
|
|
nb.Append(MakeNativeBuffer("aXsdfsadfasdf2342"));
|
|
ASSERT_EQ("asd4234aX", FlattenSlowUntil(nb, "aX"));
|
|
ASSERT_EQ("asd4", FlattenSlowUntil(nb, "4"));
|
|
ASSERT_EQ("asd4234aXsdfsadfasdf2342", FlattenSlowUntil(nb, "2342"));
|
|
ASSERT_EQ("asd42", FlattenSlowUntil(nb, "z", 5));
|
|
ASSERT_EQ("asd42", FlattenSlowUntil(nb, "3", 5));
|
|
ASSERT_EQ("asd42", FlattenSlowUntil(nb, "2", 5));
|
|
ASSERT_EQ("asd4", FlattenSlowUntil(nb, "4", 5));
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, FlattenSlowUntil2)
|
|
{
|
|
auto nb = CreateBufferSlow(
|
|
"HTTP/1.1 200 OK\r\nRpc-SeqNo: 14563016719\r\nRpc-Error-Code: "
|
|
"0\r\nRpc-Error-Reason: The operation completed "
|
|
"successfully.\r\nContent-Type: "
|
|
"application/x-protobuf\r\nContent-Length: 0\r\n\r\nHTTP/1.1 200 "
|
|
"OK\r\nRpc-Seq");
|
|
ASSERT_EQ("HTTP/1.1 200 OK\r\nRpc-SeqNo: 14563016719\r\nRpc-Error-Code: "
|
|
"0\r\nRpc-Error-Reason: The operation completed "
|
|
"successfully.\r\nContent-Type: "
|
|
"application/x-protobuf\r\nContent-Length: 0\r\n\r\n",
|
|
FlattenSlowUntil(nb, "\r\n\r\n"));
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, FlattenSlowUntil3)
|
|
{
|
|
NoncontiguousBuffer nb;
|
|
nb.Append(MakeNativeBuffer("asd4234"));
|
|
nb.Append(MakeNativeBuffer("aXsdfsadfasdf2342"));
|
|
ASSERT_EQ("asd4234aX", FlattenSlowUntil(nb, "aX"));
|
|
ASSERT_EQ("asd4", FlattenSlowUntil(nb, "4"));
|
|
ASSERT_EQ("asd4234aX", FlattenSlowUntil(nb, "4aX"));
|
|
}
|
|
|
|
TEST(NoncontiguousBuffer, FlattenSlowUntil4)
|
|
{
|
|
NoncontiguousBuffer nb;
|
|
nb.Append(MakeNativeBuffer("AB"));
|
|
nb.Append(MakeNativeBuffer("CDEFGGGGHHHH"));
|
|
ASSERT_EQ("ABCDEFGGGG", FlattenSlowUntil(nb, "GGGG"));
|
|
}
|
|
|
|
TEST(NoncontiguousBufferBuilder, Append)
|
|
{
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append(MakeForeignBuffer(""));
|
|
nbb.Append(MakeForeignBuffer("small"));
|
|
nbb.Append(MakeForeignBuffer(std::string(8192, 'a')));
|
|
nbb.Append(CreateBufferSlow(""));
|
|
nbb.Append(CreateBufferSlow("small"));
|
|
nbb.Append(CreateBufferSlow(std::string(8192, 'a')));
|
|
auto nb = nbb.DestructiveGet();
|
|
EXPECT_EQ("small" + std::string(8192, 'a') + "small" + std::string(8192, 'a'), FlattenSlow(nb));
|
|
}
|
|
|
|
TEST(NoncontiguousBufferBuilder, Reserve)
|
|
{
|
|
auto temp_block = MakeNativeBufferBlock();
|
|
auto max_bytes = temp_block->size();
|
|
NoncontiguousBufferBuilder nbb;
|
|
auto ptr = nbb.data();
|
|
auto ptr2 = nbb.Reserve(10);
|
|
ASSERT_EQ(ptr, ptr2);
|
|
ASSERT_EQ(ptr + 10, nbb.data());
|
|
nbb.Append(std::string(max_bytes - 10 - 1, 'a'));
|
|
ptr = nbb.data();
|
|
ptr2 = nbb.Reserve(1);// Last byte in the block.
|
|
ASSERT_EQ(ptr, ptr2);
|
|
ASSERT_EQ(max_bytes, nbb.SizeAvailable());
|
|
|
|
nbb.Append(std::string(max_bytes - 1, 'a'));
|
|
ptr = nbb.data();
|
|
ptr2 = nbb.Reserve(2);
|
|
ASSERT_NE(ptr, ptr2);
|
|
ASSERT_EQ(ptr2 + 2, nbb.data());
|
|
}
|
|
|
|
TEST(NoncontiguousBufferBuilder, DestructiveGet1)
|
|
{
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append("asdf1234", 6);
|
|
nbb.Append("1122", 4);
|
|
ASSERT_EQ("asdf12"
|
|
"1122",
|
|
FlattenSlow(nbb.DestructiveGet()));
|
|
}
|
|
|
|
TEST(NoncontiguousBufferBuilder, DestructiveGet2)
|
|
{
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append("aabbccd");
|
|
ASSERT_EQ("aabbccd", FlattenSlow(nbb.DestructiveGet()));
|
|
}
|
|
|
|
TEST(NoncontiguousBufferBuilder, DestructiveGet3)
|
|
{
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append(std::string(1000000, 'A'));
|
|
ASSERT_EQ(std::string(1000000, 'A'), FlattenSlow(nbb.DestructiveGet()));
|
|
}
|
|
|
|
TEST(NoncontiguousBufferBuilder, DestructiveGet4)
|
|
{
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append('c');
|
|
ASSERT_EQ("c", FlattenSlow(nbb.DestructiveGet()));
|
|
}
|
|
|
|
TEST(NoncontiguousBufferBuilder, DestructiveGet5)
|
|
{
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append(CreateBufferSlow("c"));
|
|
ASSERT_EQ("c", FlattenSlow(nbb.DestructiveGet()));
|
|
}
|
|
|
|
TEST(NoncontiguousBufferBuilder, DestructiveGet6)
|
|
{
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append(Slice("11"), Slice("2"), std::string("3"), std::string("45"), Slice("6"));
|
|
nbb.Append("1122", 4);
|
|
ASSERT_EQ("11234561122", FlattenSlow(nbb.DestructiveGet()));
|
|
}
|
|
|
|
TEST(MakeReferencingBuffer, Simple)
|
|
{
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append(MakeReferencingBuffer("abcdefg", 7));
|
|
EXPECT_EQ("abcdefg", FlattenSlow(nbb.DestructiveGet()));
|
|
}
|
|
|
|
TEST(MakeReferencingBuffer, WithCallbackSmallBufferOptimized)
|
|
{
|
|
int x = 0;
|
|
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append("aaa", 3);
|
|
// Small buffers are copied by `Append` and freed immediately.
|
|
nbb.Append(MakeReferencingBuffer("abcdefg", 7, [&] { ++x; }));
|
|
// Therefore the callback should have fired on return of `Append`.
|
|
EXPECT_EQ(1, x);
|
|
auto buffer = nbb.DestructiveGet();
|
|
EXPECT_EQ("aaaabcdefg", FlattenSlow(buffer));
|
|
}
|
|
|
|
TEST(MakeReferencingBuffer, WithCallback)
|
|
{
|
|
static const std::string kBuffer(12345, 'a');
|
|
int x = 0;
|
|
|
|
{
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append("aaa", 3);
|
|
nbb.Append(MakeReferencingBuffer(kBuffer.data(), 1024, [&] { ++x; }));
|
|
EXPECT_EQ(0, x);
|
|
auto buffer = nbb.DestructiveGet();
|
|
EXPECT_EQ(0, x);
|
|
EXPECT_EQ("aaa" + kBuffer.substr(0, 1024), FlattenSlow(buffer));
|
|
}
|
|
EXPECT_EQ(1, x);
|
|
}
|
|
|
|
TEST(MakeForeignBuffer, String)
|
|
{
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append(MakeForeignBuffer(std::string("abcdefg")));
|
|
EXPECT_EQ("abcdefg", FlattenSlow(nbb.DestructiveGet()));
|
|
}
|
|
|
|
TEST(MakeForeignBuffer, VectorOfChar)
|
|
{
|
|
std::vector<char> data{'a', 'b', 'c', 'd', 'e', 'f', 'g'};
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append(MakeForeignBuffer(std::move(data)));
|
|
EXPECT_EQ("abcdefg", FlattenSlow(nbb.DestructiveGet()));
|
|
}
|
|
|
|
// TEST(MakeForeignBuffer, VectorOfBytes) {
|
|
// std::vector<std::byte> data;
|
|
// data.resize(7);
|
|
// memcpy(data.data(), "abcdefg", 7);
|
|
// NoncontiguousBufferBuilder nbb;
|
|
// nbb.Append(MakeForeignBuffer(std::move(data)));
|
|
// EXPECT_EQ("abcdefg", FlattenSlow(nbb.DestructiveGet()));
|
|
// }
|
|
|
|
TEST(MakeForeignBuffer, VectorOfUInt8)
|
|
{
|
|
std::vector<std::uint8_t> data;
|
|
data.resize(7);
|
|
memcpy(data.data(), "abcdefg", 7);
|
|
NoncontiguousBufferBuilder nbb;
|
|
nbb.Append(MakeForeignBuffer(std::move(data)));
|
|
EXPECT_EQ("abcdefg", FlattenSlow(nbb.DestructiveGet()));
|
|
}
|
|
|
|
}// namespace tile
|