4f417e1f5d
Summary: Previously, our implementation of the Bolt protocol buffered all results in memory before sending them out to the client. This implementation immediately streams the results to the client to avoid any memory allocations. Also, this implementation splits the interpretation and pulling logic into two. Reviewers: teon.banek Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1495
104 lines
3.1 KiB
C++
104 lines
3.1 KiB
C++
#include "bolt_common.hpp"
|
|
#include "communication/bolt/v1/encoder/chunked_encoder_buffer.hpp"
|
|
|
|
// aliases
|
|
using BufferT = communication::bolt::ChunkedEncoderBuffer<TestOutputStream>;
|
|
|
|
// constants
|
|
using communication::bolt::kChunkHeaderSize;
|
|
using communication::bolt::kChunkMaxDataSize;
|
|
using communication::bolt::kChunkWholeSize;
|
|
|
|
// test data
|
|
constexpr const int kTestDataSize = 100000;
|
|
uint8_t test_data[kTestDataSize];
|
|
|
|
/**
|
|
* Verifies a single chunk. The chunk should be constructed from a header
|
|
* (chunk size) and data. The header is a two byte long number written in big
|
|
* endian format. Data is an array of elements from test_data whose max size is
|
|
* 0xFFFF.
|
|
*
|
|
* @param data pointer on data array (array of bytes)
|
|
* @param size of data array
|
|
* @param offset offset from the begining of the test data
|
|
*/
|
|
void VerifyChunkOfTestData(uint8_t *data, int size, uint64_t offset = 0) {
|
|
// first two bytes are size (big endian)
|
|
uint8_t lower_byte = size & 0xFF;
|
|
uint8_t higher_byte = (size & 0xFF00) >> 8;
|
|
ASSERT_EQ(*data, higher_byte);
|
|
ASSERT_EQ(*(data + 1), lower_byte);
|
|
|
|
// in the data array should be size number of ones
|
|
// the header is skipped
|
|
for (auto i = 0; i < size; ++i) {
|
|
ASSERT_EQ(data[i + kChunkHeaderSize], test_data[i + offset]);
|
|
}
|
|
}
|
|
|
|
TEST(BoltChunkedEncoderBuffer, OneSmallChunk) {
|
|
int size = 100;
|
|
|
|
// initialize tested buffer
|
|
TestOutputStream output_stream;
|
|
BufferT buffer(output_stream);
|
|
|
|
// write into buffer
|
|
buffer.Write(test_data, size);
|
|
buffer.Flush();
|
|
|
|
// check the output array
|
|
// the array should look like: [0, 100, first 100 bytes of test data]
|
|
VerifyChunkOfTestData(output_stream.output.data(), size);
|
|
}
|
|
|
|
TEST(BoltChunkedEncoderBuffer, TwoSmallChunks) {
|
|
int size1 = 100;
|
|
int size2 = 200;
|
|
|
|
// initialize tested buffer
|
|
TestOutputStream output_stream;
|
|
BufferT buffer(output_stream);
|
|
|
|
// write into buffer
|
|
buffer.Write(test_data, size1);
|
|
buffer.Flush();
|
|
buffer.Write(test_data + size1, size2);
|
|
buffer.Flush();
|
|
|
|
// check the output array
|
|
// the output array should look like this:
|
|
// [0, 100, first 100 bytes of test data] +
|
|
// [0, 100, second 100 bytes of test data]
|
|
auto data = output_stream.output.data();
|
|
VerifyChunkOfTestData(data, size1);
|
|
VerifyChunkOfTestData(data + kChunkHeaderSize + size1, size2, size1);
|
|
}
|
|
|
|
TEST(BoltChunkedEncoderBuffer, OneAndAHalfOfMaxChunk) {
|
|
// initialize tested buffer
|
|
TestOutputStream output_stream;
|
|
BufferT buffer(output_stream);
|
|
|
|
// write into buffer
|
|
buffer.Write(test_data, kTestDataSize);
|
|
buffer.Flush();
|
|
|
|
// check the output array
|
|
// the output array should look like this:
|
|
// [0xFF, 0xFF, first 65535 bytes of test data,
|
|
// 0x86, 0xA1, 34465 bytes of test data after the first 65535 bytes]
|
|
auto output = output_stream.output.data();
|
|
VerifyChunkOfTestData(output, kChunkMaxDataSize);
|
|
VerifyChunkOfTestData(output + kChunkWholeSize,
|
|
kTestDataSize - kChunkMaxDataSize, kChunkMaxDataSize);
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
InitializeData(test_data, kTestDataSize);
|
|
google::InitGoogleLogging(argv[0]);
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|