memgraph/tests/unit/bolt_chunked_encoder_buffer.cpp
Matej Ferencevic 4f417e1f5d Support streaming of Bolt results
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
2018-07-18 13:01:50 +02:00

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();
}