2022-02-22 20:33:45 +08:00
|
|
|
// Copyright 2022 Memgraph Ltd.
|
2021-10-26 14:53:56 +08:00
|
|
|
//
|
|
|
|
// Use of this software is governed by the Business Source License
|
|
|
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
|
|
|
// License, and you may not use this file except in compliance with the Business Source License.
|
|
|
|
//
|
|
|
|
// As of the Change Date specified in that file, in accordance with
|
|
|
|
// the Business Source License, use of this software will be governed
|
|
|
|
// by the Apache License, Version 2.0, included in the file
|
|
|
|
// licenses/APL.txt.
|
|
|
|
|
2021-08-12 00:04:01 +08:00
|
|
|
#include <bit>
|
|
|
|
|
2017-04-06 20:30:04 +08:00
|
|
|
#include "bolt_common.hpp"
|
|
|
|
#include "bolt_testdata.hpp"
|
|
|
|
#include "communication/bolt/v1/decoder/decoder.hpp"
|
2017-04-10 18:22:48 +08:00
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
using memgraph::communication::bolt::Value;
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
constexpr const int SIZE = 131072;
|
|
|
|
uint8_t data[SIZE];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TestDecoderBuffer
|
|
|
|
* This class provides a dummy Buffer used for testing the Decoder.
|
|
|
|
* It's Read function is the necessary public interface for the Decoder.
|
|
|
|
* It's Write and Clear methods are used for testing. Through the Write
|
|
|
|
* method you can store data in the buffer, and throgh the Clear method
|
|
|
|
* you can clear the buffer. The decoder uses the Read function to get
|
|
|
|
* data from the buffer.
|
|
|
|
*/
|
|
|
|
class TestDecoderBuffer {
|
|
|
|
public:
|
|
|
|
bool Read(uint8_t *data, size_t len) {
|
|
|
|
if (len > buffer_.size()) return false;
|
|
|
|
memcpy(data, buffer_.data(), len);
|
|
|
|
buffer_.erase(buffer_.begin(), buffer_.begin() + len);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-04-07 21:03:37 +08:00
|
|
|
void Write(const uint8_t *data, size_t len) {
|
|
|
|
for (size_t i = 0; i < len; ++i) buffer_.push_back(data[i]);
|
2017-04-06 20:30:04 +08:00
|
|
|
}
|
|
|
|
|
2017-04-07 21:03:37 +08:00
|
|
|
void Clear() { buffer_.clear(); }
|
|
|
|
|
2017-04-06 20:30:04 +08:00
|
|
|
private:
|
|
|
|
std::vector<uint8_t> buffer_;
|
|
|
|
};
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
using DecoderT = memgraph::communication::bolt::Decoder<TestDecoderBuffer>;
|
2017-04-06 20:30:04 +08:00
|
|
|
|
2021-01-21 22:47:56 +08:00
|
|
|
struct BoltDecoder : ::testing::Test {
|
|
|
|
// In newer gtest library (1.8.1+) this is changed to SetUpTestSuite
|
|
|
|
static void SetUpTestCase() { InitializeData(data, SIZE); }
|
|
|
|
};
|
|
|
|
|
|
|
|
TEST_F(BoltDecoder, NullAndBool) {
|
2017-04-06 20:30:04 +08:00
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
2018-07-24 21:11:18 +08:00
|
|
|
Value dv;
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test null
|
|
|
|
buffer.Write((const uint8_t *)"\xC0", 1);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), true);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(dv.type(), Value::Type::Null);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test true
|
|
|
|
buffer.Write((const uint8_t *)"\xC3", 1);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), true);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(dv.type(), Value::Type::Bool);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(dv.ValueBool(), true);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test false
|
|
|
|
buffer.Write((const uint8_t *)"\xC2", 1);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), true);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(dv.type(), Value::Type::Bool);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(dv.ValueBool(), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
}
|
|
|
|
|
2021-01-21 22:47:56 +08:00
|
|
|
TEST_F(BoltDecoder, Int) {
|
2017-04-06 20:30:04 +08:00
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
|
2018-07-24 21:11:18 +08:00
|
|
|
Value dv;
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test invalid marker
|
|
|
|
buffer.Clear();
|
2017-04-07 21:03:37 +08:00
|
|
|
buffer.Write((uint8_t *)"\xCD", 1); // 0xCD is reserved in the protocol
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
for (int i = 0; i < 28; ++i) {
|
|
|
|
// test missing data
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(int_encoded[i], int_encoded_len[i] - 1);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test all ok
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(int_encoded[i], int_encoded_len[i]);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), true);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(dv.type(), Value::Type::Int);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(dv.ValueInt(), int_decoded[i]);
|
2017-04-06 20:30:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-21 22:47:56 +08:00
|
|
|
TEST_F(BoltDecoder, Double) {
|
2017-04-06 20:30:04 +08:00
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
|
2018-07-24 21:11:18 +08:00
|
|
|
Value dv;
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
// test missing data
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(double_encoded[i], 8);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test all ok
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(double_encoded[i], 9);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), true);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(dv.type(), Value::Type::Double);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(dv.ValueDouble(), double_decoded[i]);
|
2017-04-06 20:30:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-21 22:47:56 +08:00
|
|
|
TEST_F(BoltDecoder, String) {
|
2017-04-06 20:30:04 +08:00
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
|
2018-07-24 21:11:18 +08:00
|
|
|
Value dv;
|
2017-04-06 20:30:04 +08:00
|
|
|
|
2021-02-18 22:32:43 +08:00
|
|
|
uint8_t headers[][6] = {"\x8F", "\xD0\x0F", "\xD1\x00\x0F", "\xD2\x00\x00\x00\x0F"};
|
2017-04-06 20:30:04 +08:00
|
|
|
int headers_len[] = {1, 2, 3, 5};
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
// test missing data in header
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i] - 1);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test missing elements
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i]);
|
|
|
|
buffer.Write(data, 14);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test all ok
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i]);
|
|
|
|
buffer.Write(data, 15);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), true);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(dv.type(), Value::Type::String);
|
2017-08-24 21:23:33 +08:00
|
|
|
std::string &str = dv.ValueString();
|
2017-04-07 21:03:37 +08:00
|
|
|
for (int j = 0; j < 15; ++j) EXPECT_EQ((uint8_t)str[j], data[j]);
|
2017-04-06 20:30:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-21 22:47:56 +08:00
|
|
|
TEST_F(BoltDecoder, StringLarge) {
|
2018-05-18 20:25:11 +08:00
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
2018-07-24 21:11:18 +08:00
|
|
|
Value dv;
|
2018-05-18 20:25:11 +08:00
|
|
|
|
|
|
|
uint8_t header[6] = "\xD2\x00\x01\x86\xA0";
|
|
|
|
|
|
|
|
// test missing data
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 5);
|
|
|
|
buffer.Write(data, 10);
|
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
|
|
|
|
|
|
|
// test all ok
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 5);
|
|
|
|
buffer.Write(data, 100000);
|
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), true);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(dv.type(), Value::Type::String);
|
2018-05-18 20:25:11 +08:00
|
|
|
std::string &str = dv.ValueString();
|
|
|
|
for (int j = 0; j < 100000; ++j) EXPECT_EQ((uint8_t)str[j], data[j]);
|
|
|
|
}
|
|
|
|
|
2021-01-21 22:47:56 +08:00
|
|
|
TEST_F(BoltDecoder, List) {
|
2017-04-06 20:30:04 +08:00
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
|
2018-07-24 21:11:18 +08:00
|
|
|
Value dv;
|
2017-04-06 20:30:04 +08:00
|
|
|
|
2021-02-18 22:32:43 +08:00
|
|
|
uint8_t headers[][6] = {"\x9F", "\xD4\x0F", "\xD5\x00\x0F", "\xD6\x00\x00\x00\x0F"};
|
2017-04-06 20:30:04 +08:00
|
|
|
int headers_len[] = {1, 2, 3, 5};
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
// test missing data in header
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i] - 1);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test missing elements
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i]);
|
2017-04-07 21:03:37 +08:00
|
|
|
for (uint8_t j = 0; j < 14; ++j) buffer.Write(&j, 1);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test all ok
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i]);
|
2017-04-07 21:03:37 +08:00
|
|
|
for (uint8_t j = 0; j < 15; ++j) buffer.Write(&j, 1);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), true);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(dv.type(), Value::Type::List);
|
|
|
|
std::vector<Value> &val = dv.ValueList();
|
2017-04-06 20:30:04 +08:00
|
|
|
ASSERT_EQ(val.size(), 15);
|
2017-08-24 21:23:33 +08:00
|
|
|
for (int j = 0; j < 15; ++j) EXPECT_EQ(val[j].ValueInt(), j);
|
2017-04-06 20:30:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-21 22:47:56 +08:00
|
|
|
TEST_F(BoltDecoder, Map) {
|
2017-04-06 20:30:04 +08:00
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
|
2018-07-24 21:11:18 +08:00
|
|
|
Value dv;
|
2017-04-06 20:30:04 +08:00
|
|
|
|
2021-02-18 22:32:43 +08:00
|
|
|
uint8_t headers[][6] = {"\xAF", "\xD8\x0F", "\xD9\x00\x0F", "\xDA\x00\x00\x00\x0F"};
|
2017-04-06 20:30:04 +08:00
|
|
|
int headers_len[] = {1, 2, 3, 5};
|
|
|
|
|
|
|
|
uint8_t index[] = "\x81\x61";
|
|
|
|
uint8_t wrong_index = 1;
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
// test missing data in header
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i] - 1);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test wrong index type
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i]);
|
|
|
|
buffer.Write(&wrong_index, 1);
|
|
|
|
buffer.Write(&wrong_index, 1);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test missing element data
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i]);
|
|
|
|
buffer.Write(index, 2);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test missing elements
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i]);
|
|
|
|
for (uint8_t j = 0; j < 14; ++j) {
|
|
|
|
buffer.Write(index, 2);
|
|
|
|
buffer.Write(&j, 1);
|
|
|
|
}
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test elements with same index
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i]);
|
|
|
|
for (uint8_t j = 0; j < 15; ++j) {
|
|
|
|
buffer.Write(index, 2);
|
|
|
|
buffer.Write(&j, 1);
|
|
|
|
}
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test all ok
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(headers[i], headers_len[i]);
|
|
|
|
for (uint8_t j = 0; j < 15; ++j) {
|
|
|
|
uint8_t tmp = 'a' + j;
|
|
|
|
buffer.Write(index, 1);
|
|
|
|
buffer.Write(&tmp, 1);
|
|
|
|
buffer.Write(&j, 1);
|
|
|
|
}
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv), true);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(dv.type(), Value::Type::Map);
|
|
|
|
std::map<std::string, Value> &val = dv.ValueMap();
|
2017-04-06 20:30:04 +08:00
|
|
|
ASSERT_EQ(val.size(), 15);
|
|
|
|
for (int j = 0; j < 15; ++j) {
|
|
|
|
char tmp_chr = 'a' + j;
|
2018-07-24 21:11:18 +08:00
|
|
|
Value tmp_dv = val[std::string(1, tmp_chr)];
|
|
|
|
EXPECT_EQ(tmp_dv.type(), Value::Type::Int);
|
2017-08-24 21:23:33 +08:00
|
|
|
EXPECT_EQ(tmp_dv.ValueInt(), j);
|
2017-04-06 20:30:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-21 22:47:56 +08:00
|
|
|
TEST_F(BoltDecoder, Vertex) {
|
2017-04-06 20:30:04 +08:00
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
|
2018-07-24 21:11:18 +08:00
|
|
|
Value dv;
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
uint8_t header[] = "\xB3\x4E";
|
|
|
|
uint8_t wrong_header[] = "\x00\x00";
|
|
|
|
uint8_t test_int[] = "\x01";
|
|
|
|
uint8_t test_str[] = "\x81\x61";
|
|
|
|
uint8_t test_list[] = "\x91";
|
|
|
|
uint8_t test_map[] = "\xA1";
|
|
|
|
|
|
|
|
// test missing signature
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(wrong_header, 1);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Vertex), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test wrong marker
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(wrong_header, 2);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Vertex), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test wrong signature
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 1);
|
|
|
|
buffer.Write(wrong_header, 1);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Vertex), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test ID wrong type
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 2);
|
|
|
|
buffer.Write(test_str, 2);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Vertex), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test labels wrong outer type
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 2);
|
|
|
|
buffer.Write(test_int, 1);
|
|
|
|
buffer.Write(test_int, 1);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Vertex), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test labels wrong inner type
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 2);
|
|
|
|
buffer.Write(test_int, 1);
|
|
|
|
buffer.Write(test_list, 1);
|
|
|
|
buffer.Write(test_int, 1);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Vertex), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test properties wrong outer type
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 2);
|
|
|
|
buffer.Write(test_int, 1);
|
|
|
|
buffer.Write(test_list, 1);
|
|
|
|
buffer.Write(test_str, 2);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Vertex), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test all ok
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 2);
|
|
|
|
buffer.Write(test_int, 1);
|
|
|
|
buffer.Write(test_list, 1);
|
|
|
|
buffer.Write(test_str, 2);
|
|
|
|
buffer.Write(test_map, 1);
|
|
|
|
buffer.Write(test_str, 2);
|
|
|
|
buffer.Write(test_int, 1);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Vertex), true);
|
2017-08-24 21:23:33 +08:00
|
|
|
auto &vertex = dv.ValueVertex();
|
2018-07-02 21:34:33 +08:00
|
|
|
ASSERT_EQ(vertex.id.AsUint(), 1);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(vertex.labels[0], std::string("a"));
|
|
|
|
ASSERT_EQ(vertex.properties[std::string("a")].ValueInt(), 1);
|
2017-04-06 20:30:04 +08:00
|
|
|
}
|
|
|
|
|
2021-01-21 22:47:56 +08:00
|
|
|
TEST_F(BoltDecoder, Edge) {
|
2017-04-06 20:30:04 +08:00
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
|
2018-07-24 21:11:18 +08:00
|
|
|
Value de;
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
uint8_t header[] = "\xB5\x52";
|
|
|
|
uint8_t wrong_header[] = "\x00\x00";
|
|
|
|
uint8_t test_int1[] = "\x01";
|
|
|
|
uint8_t test_int2[] = "\x02";
|
|
|
|
uint8_t test_int3[] = "\x03";
|
|
|
|
uint8_t test_str[] = "\x81\x61";
|
|
|
|
uint8_t test_map[] = "\xA1";
|
|
|
|
|
|
|
|
// test missing signature
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(wrong_header, 1);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&de, Value::Type::Edge), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test wrong marker
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(wrong_header, 2);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&de, Value::Type::Edge), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test wrong signature
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 1);
|
|
|
|
buffer.Write(wrong_header, 1);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&de, Value::Type::Edge), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test ID wrong type
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 2);
|
|
|
|
buffer.Write(test_str, 2);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&de, Value::Type::Edge), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test from_id wrong type
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 2);
|
|
|
|
buffer.Write(test_int1, 1);
|
|
|
|
buffer.Write(test_str, 2);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&de, Value::Type::Edge), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test to_id wrong type
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 2);
|
|
|
|
buffer.Write(test_int1, 1);
|
|
|
|
buffer.Write(test_int2, 1);
|
|
|
|
buffer.Write(test_str, 2);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&de, Value::Type::Edge), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test type wrong type
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 2);
|
|
|
|
buffer.Write(test_int1, 1);
|
|
|
|
buffer.Write(test_int2, 1);
|
|
|
|
buffer.Write(test_int3, 1);
|
|
|
|
buffer.Write(test_int1, 1);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&de, Value::Type::Edge), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test properties wrong outer type
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 2);
|
|
|
|
buffer.Write(test_int1, 1);
|
|
|
|
buffer.Write(test_int2, 1);
|
|
|
|
buffer.Write(test_int3, 1);
|
|
|
|
buffer.Write(test_str, 2);
|
|
|
|
buffer.Write(test_int1, 1);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&de, Value::Type::Edge), false);
|
2017-04-06 20:30:04 +08:00
|
|
|
|
|
|
|
// test all ok
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(header, 2);
|
|
|
|
buffer.Write(test_int1, 1);
|
|
|
|
buffer.Write(test_int2, 1);
|
|
|
|
buffer.Write(test_int3, 1);
|
|
|
|
buffer.Write(test_str, 2);
|
|
|
|
buffer.Write(test_map, 1);
|
|
|
|
buffer.Write(test_str, 2);
|
|
|
|
buffer.Write(test_int1, 1);
|
2018-07-24 21:11:18 +08:00
|
|
|
ASSERT_EQ(decoder.ReadValue(&de, Value::Type::Edge), true);
|
2017-08-24 21:23:33 +08:00
|
|
|
auto &edge = de.ValueEdge();
|
2018-07-02 21:34:33 +08:00
|
|
|
ASSERT_EQ(edge.id.AsUint(), 1);
|
|
|
|
ASSERT_EQ(edge.from.AsUint(), 2);
|
|
|
|
ASSERT_EQ(edge.to.AsUint(), 3);
|
2017-08-24 21:23:33 +08:00
|
|
|
ASSERT_EQ(edge.type, std::string("a"));
|
|
|
|
ASSERT_EQ(edge.properties[std::string("a")].ValueInt(), 1);
|
2017-04-06 20:30:04 +08:00
|
|
|
}
|
2021-08-12 00:04:01 +08:00
|
|
|
|
|
|
|
// Temporal types testing starts here
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
constexpr uint8_t Cast(T marker) {
|
|
|
|
return static_cast<uint8_t>(marker);
|
|
|
|
}
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
void AssertThatDatesAreEqual(const memgraph::utils::Date &d1, const memgraph::utils::Date &d2) {
|
2021-10-02 22:14:27 +08:00
|
|
|
ASSERT_EQ(d1.day, d2.day);
|
|
|
|
ASSERT_EQ(d1.month, d2.month);
|
|
|
|
ASSERT_EQ(d1.year, d2.year);
|
2021-08-12 00:04:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(BoltDecoder, DateOld) {
|
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
|
|
|
|
Value dv;
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
using Marker = memgraph::communication::bolt::Marker;
|
|
|
|
using Sig = memgraph::communication::bolt::Signature;
|
|
|
|
const auto date = memgraph::utils::Date({1970, 1, 1});
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto days = date.DaysSinceEpoch();
|
|
|
|
ASSERT_EQ(days, 0);
|
|
|
|
// clang-format off
|
|
|
|
std::array<uint8_t, 3> data = {
|
2022-02-22 20:33:45 +08:00
|
|
|
Cast(Marker::TinyStruct1),
|
|
|
|
Cast(Sig::Date),
|
2021-08-12 00:04:01 +08:00
|
|
|
0x0 };
|
|
|
|
// clang-format on
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(data.data(), data.size());
|
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Date), true);
|
|
|
|
AssertThatDatesAreEqual(dv.ValueDate(), date);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(BoltDecoder, DateRecent) {
|
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
Value dv;
|
2022-02-22 20:33:45 +08:00
|
|
|
using Marker = memgraph::communication::bolt::Marker;
|
|
|
|
using Sig = memgraph::communication::bolt::Signature;
|
|
|
|
const auto date = memgraph::utils::Date({2021, 7, 20});
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto days = date.DaysSinceEpoch();
|
|
|
|
ASSERT_EQ(days, 18828);
|
|
|
|
const auto *d_bytes = std::bit_cast<const uint8_t *>(&days);
|
|
|
|
// clang-format off
|
|
|
|
std::array<uint8_t, 7> data = {
|
2022-02-22 20:33:45 +08:00
|
|
|
Cast(Marker::TinyStruct1),
|
|
|
|
Cast(Sig::Date),
|
|
|
|
Cast(Marker::Int32),
|
|
|
|
d_bytes[3],
|
|
|
|
d_bytes[2],
|
|
|
|
d_bytes[1],
|
2021-08-12 00:04:01 +08:00
|
|
|
d_bytes[0] };
|
2022-02-22 20:33:45 +08:00
|
|
|
// clang-format on
|
2021-08-12 00:04:01 +08:00
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(data.data(), data.size());
|
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Date), true);
|
|
|
|
AssertThatDatesAreEqual(dv.ValueDate(), date);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(BoltDecoder, DurationOneSec) {
|
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
Value dv;
|
2022-02-22 20:33:45 +08:00
|
|
|
const auto value = Value(memgraph::utils::Duration(1));
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto &dur = value.ValueDuration();
|
|
|
|
const auto nanos = dur.SubSecondsAsNanoseconds();
|
2021-09-17 22:40:57 +08:00
|
|
|
ASSERT_EQ(dur.Days(), 0);
|
2021-08-12 00:04:01 +08:00
|
|
|
ASSERT_EQ(dur.SubDaysAsSeconds(), 0);
|
2022-02-22 20:33:45 +08:00
|
|
|
ASSERT_EQ(nanos, 1000);
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto *n_bytes = std::bit_cast<const uint8_t *>(&nanos);
|
2022-02-22 20:33:45 +08:00
|
|
|
using Marker = memgraph::communication::bolt::Marker;
|
|
|
|
using Sig = memgraph::communication::bolt::Signature;
|
2021-08-12 00:04:01 +08:00
|
|
|
// clang-format off
|
|
|
|
std::array<uint8_t, 8> data = {
|
|
|
|
Cast(Marker::TinyStruct4),
|
|
|
|
Cast(Sig::Duration),
|
|
|
|
0x0,
|
|
|
|
0x0,
|
|
|
|
0x0,
|
|
|
|
Cast(Marker::Int16),
|
|
|
|
n_bytes[1], n_bytes[0] };
|
|
|
|
// clang-format on
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(data.data(), data.size());
|
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Duration), true);
|
|
|
|
ASSERT_EQ(dv.ValueDuration().microseconds, dur.microseconds);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(BoltDecoder, DurationMinusOneSec) {
|
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
Value dv;
|
2022-02-22 20:33:45 +08:00
|
|
|
const auto value = Value(memgraph::utils::Duration(-1));
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto &dur = value.ValueDuration();
|
|
|
|
const auto nanos = dur.SubSecondsAsNanoseconds();
|
2021-09-17 22:40:57 +08:00
|
|
|
ASSERT_EQ(dur.Days(), 0);
|
2021-08-12 00:04:01 +08:00
|
|
|
ASSERT_EQ(dur.SubDaysAsSeconds(), 0);
|
|
|
|
ASSERT_EQ(nanos, -1000);
|
|
|
|
const auto *n_bytes = std::bit_cast<const uint8_t *>(&nanos);
|
2022-02-22 20:33:45 +08:00
|
|
|
using Marker = memgraph::communication::bolt::Marker;
|
|
|
|
using Sig = memgraph::communication::bolt::Signature;
|
2021-08-12 00:04:01 +08:00
|
|
|
// clang-format off
|
|
|
|
std::array<uint8_t, 8> data = {
|
|
|
|
Cast(Marker::TinyStruct4),
|
|
|
|
Cast(Sig::Duration),
|
|
|
|
0x0,
|
|
|
|
0x0,
|
|
|
|
0x0,
|
|
|
|
Cast(Marker::Int16),
|
|
|
|
n_bytes[1], n_bytes[0] };
|
|
|
|
// clang-format on
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(data.data(), data.size());
|
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Duration), true);
|
|
|
|
ASSERT_EQ(dv.ValueDuration().microseconds, dur.microseconds);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(BoltDecoder, ArbitraryDuration) {
|
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
Value dv;
|
2022-02-22 20:33:45 +08:00
|
|
|
const auto value = Value(memgraph::utils::Duration({15, 1, 2, 3, 5, 0}));
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto &dur = value.ValueDuration();
|
2021-09-17 22:40:57 +08:00
|
|
|
ASSERT_EQ(dur.Days(), 15);
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto secs = dur.SubDaysAsSeconds();
|
2021-09-17 22:40:57 +08:00
|
|
|
ASSERT_EQ(secs, 3723);
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto *sec_bytes = std::bit_cast<const uint8_t *>(&secs);
|
|
|
|
const auto nanos = dur.SubSecondsAsNanoseconds();
|
2021-09-17 22:40:57 +08:00
|
|
|
ASSERT_EQ(nanos, 5000000);
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto *nano_bytes = std::bit_cast<const uint8_t *>(&nanos);
|
2022-02-22 20:33:45 +08:00
|
|
|
using Marker = memgraph::communication::bolt::Marker;
|
|
|
|
using Sig = memgraph::communication::bolt::Signature;
|
2021-08-12 00:04:01 +08:00
|
|
|
// clang-format off
|
|
|
|
std::array<uint8_t, 12> data = {
|
|
|
|
Cast(Marker::TinyStruct4),
|
|
|
|
Cast(Sig::Duration),
|
2021-09-17 22:40:57 +08:00
|
|
|
0x0,
|
|
|
|
0xF,
|
2021-08-12 00:04:01 +08:00
|
|
|
Cast(Marker::Int16),
|
|
|
|
sec_bytes[1],
|
|
|
|
sec_bytes[0],
|
2022-02-22 20:33:45 +08:00
|
|
|
Cast(Marker::Int32),
|
2021-08-12 00:04:01 +08:00
|
|
|
nano_bytes[3],
|
|
|
|
nano_bytes[2],
|
|
|
|
nano_bytes[1],
|
|
|
|
nano_bytes[0] };
|
|
|
|
|
|
|
|
// clang-format on
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(data.data(), data.size());
|
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::Duration), true);
|
|
|
|
ASSERT_EQ(dv.ValueDuration().microseconds, dur.microseconds);
|
|
|
|
}
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
void AssertThatLocalTimeIsEqual(memgraph::utils::LocalTime t1, memgraph::utils::LocalTime t2) {
|
2021-10-02 22:14:27 +08:00
|
|
|
ASSERT_EQ(t1.hour, t2.hour);
|
|
|
|
ASSERT_EQ(t1.minute, t2.minute);
|
|
|
|
ASSERT_EQ(t1.second, t2.second);
|
|
|
|
ASSERT_EQ(t1.microsecond, t2.microsecond);
|
|
|
|
ASSERT_EQ(t1.millisecond, t2.millisecond);
|
2021-08-12 00:04:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(BoltDecoder, LocalTimeOneMicro) {
|
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
Value dv;
|
2022-02-22 20:33:45 +08:00
|
|
|
const auto value = Value(memgraph::utils::LocalTime(1));
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto &local_time = value.ValueLocalTime();
|
|
|
|
const auto nanos = local_time.NanosecondsSinceEpoch();
|
|
|
|
ASSERT_EQ(nanos, 1000);
|
|
|
|
const auto *n_bytes = std::bit_cast<const uint8_t *>(&nanos);
|
2022-02-22 20:33:45 +08:00
|
|
|
using Marker = memgraph::communication::bolt::Marker;
|
|
|
|
using Sig = memgraph::communication::bolt::Signature;
|
2021-08-12 00:04:01 +08:00
|
|
|
// clang-format off
|
|
|
|
std::array<uint8_t, 5> data = {
|
2022-02-22 20:33:45 +08:00
|
|
|
Cast(Marker::TinyStruct1),
|
|
|
|
Cast(Sig::LocalTime),
|
|
|
|
Cast(Marker::Int16),
|
2021-08-12 00:04:01 +08:00
|
|
|
n_bytes[1],
|
|
|
|
n_bytes[0] };
|
|
|
|
// clang-format on
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(data.data(), data.size());
|
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::LocalTime), true);
|
|
|
|
AssertThatLocalTimeIsEqual(dv.ValueLocalTime(), local_time);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(BoltDecoder, LocalTimeOneThousandMicro) {
|
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
Value dv;
|
2022-02-22 20:33:45 +08:00
|
|
|
const auto value = Value(memgraph::utils::LocalTime(1000));
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto &local_time = value.ValueLocalTime();
|
|
|
|
const auto nanos = local_time.NanosecondsSinceEpoch();
|
|
|
|
ASSERT_EQ(nanos, 1000000);
|
|
|
|
const auto *n_bytes = std::bit_cast<const uint8_t *>(&nanos);
|
2022-02-22 20:33:45 +08:00
|
|
|
using Marker = memgraph::communication::bolt::Marker;
|
|
|
|
using Sig = memgraph::communication::bolt::Signature;
|
2021-08-12 00:04:01 +08:00
|
|
|
// clang-format off
|
|
|
|
std::array<uint8_t, 7> data = {
|
2022-02-22 20:33:45 +08:00
|
|
|
Cast(Marker::TinyStruct1),
|
|
|
|
Cast(Sig::LocalTime),
|
|
|
|
Cast(Marker::Int32),
|
2021-08-12 00:04:01 +08:00
|
|
|
n_bytes[3], n_bytes[2],
|
|
|
|
n_bytes[1], n_bytes[0] };
|
|
|
|
// clang-format on
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(data.data(), data.size());
|
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::LocalTime), true);
|
|
|
|
AssertThatLocalTimeIsEqual(dv.ValueLocalTime(), local_time);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(BoltDecoder, LocalDateTime) {
|
|
|
|
TestDecoderBuffer buffer;
|
|
|
|
DecoderT decoder(buffer);
|
|
|
|
|
|
|
|
Value dv;
|
|
|
|
|
2022-02-22 20:33:45 +08:00
|
|
|
const auto local_time = memgraph::utils::LocalTime(memgraph::utils::LocalTimeParameters({0, 0, 30, 1, 0}));
|
|
|
|
const auto date = memgraph::utils::Date(1);
|
|
|
|
const auto value = Value(memgraph::utils::LocalDateTime(date, local_time));
|
2021-08-12 00:04:01 +08:00
|
|
|
const auto local_date_time = value.ValueLocalDateTime();
|
|
|
|
const auto secs = local_date_time.SecondsSinceEpoch();
|
|
|
|
ASSERT_EQ(secs, 30);
|
|
|
|
const auto *sec_bytes = std::bit_cast<const uint8_t *>(&secs);
|
|
|
|
const auto nanos = local_date_time.SubSecondsAsNanoseconds();
|
|
|
|
ASSERT_EQ(nanos, 1000000);
|
|
|
|
const auto *nano_bytes = std::bit_cast<const uint8_t *>(&nanos);
|
2022-02-22 20:33:45 +08:00
|
|
|
using Marker = memgraph::communication::bolt::Marker;
|
|
|
|
using Sig = memgraph::communication::bolt::Signature;
|
2021-08-12 00:04:01 +08:00
|
|
|
// clang-format off
|
|
|
|
std::array<uint8_t, 8> data = {
|
|
|
|
Cast(Marker::TinyStruct2),
|
|
|
|
Cast(Sig::LocalDateTime),
|
|
|
|
// Seconds
|
|
|
|
sec_bytes[0],
|
2022-02-22 20:33:45 +08:00
|
|
|
// Nanoseconds
|
2021-08-12 00:04:01 +08:00
|
|
|
Cast(Marker::Int32),
|
|
|
|
nano_bytes[3], nano_bytes[2],
|
|
|
|
nano_bytes[1], nano_bytes[0] };
|
|
|
|
|
|
|
|
// clang-format on
|
|
|
|
buffer.Clear();
|
|
|
|
buffer.Write(data.data(), data.size());
|
|
|
|
ASSERT_EQ(decoder.ReadValue(&dv, Value::Type::LocalDateTime), true);
|
|
|
|
AssertThatDatesAreEqual(dv.ValueLocalDateTime().date, local_date_time.date);
|
|
|
|
AssertThatLocalTimeIsEqual(dv.ValueLocalDateTime().local_time, local_date_time.local_time);
|
|
|
|
}
|