hessian2/basic_codec/object_codec_unittests.cc (248 lines of code) (raw):
#include <iostream>
#include <type_traits>
#include "gtest/gtest.h"
#include "hessian2/basic_codec/object_codec.hpp"
#include "hessian2/object.hpp"
namespace Hessian2 {
class ObjectCodecTest : public testing::Test {
public:
template <typename T>
void decodeSucc(absl::string_view data, const T &out, size_t size) {
Hessian2::Decoder decoder(data);
auto output = decoder.decode<T>();
EXPECT_EQ(out, *output);
EXPECT_EQ(size, decoder.offset());
}
template <typename T>
void decodeFail(absl::string_view data) {
Hessian2::Decoder decoder(data);
auto output = decoder.decode<T>();
EXPECT_EQ(nullptr, output);
}
template <typename T>
void encodeSucc(const T &data, size_t size, std::string expected_data = "") {
std::string res;
Hessian2::Encoder encoder(res);
encoder.encode<T>(data);
if (!expected_data.empty()) {
EXPECT_EQ(expected_data, res);
}
decodeSucc<T>(res, data, size);
}
};
TEST_F(ObjectCodecTest, Decode) {
{
std::string data;
decodeFail<Object>(data);
}
{
// Null Object
std::string data{'N'};
NullObject o;
decodeSucc<Object>(data, o, 1);
}
{
// String Object
std::string data{0x53, 0x00, 0x05, 'h', 'e', 'l', 'l', 'o'};
StringObject o(absl::string_view("hello"));
decodeSucc<Object>(data, o, 8);
}
{
// Binary Object
std::string data{0x23, 0x01, 0x02, 0x03};
BinaryObject o(std::vector<uint8_t>{1, 2, 3});
decodeSucc<Object>(data, o, 4);
}
{
// Boolean Object
std::string data{'T'};
BooleanObject o(true);
decodeSucc<Object>(data, o, 1);
}
{
// Boolean Object
std::string data{'F'};
BooleanObject o(false);
decodeSucc<Object>(data, o, 1);
}
{
// Int Object
unsigned char buf[] = {0x49, 0x00, 0x00, 0x01, 0x2c};
std::string data(reinterpret_cast<char *>(buf), 5);
IntegerObject o(300);
decodeSucc<Object>(data, o, 5);
}
{
// Long Object
unsigned char buf[] = {0x59, 0x00, 0x00, 0x01, 0x2c};
std::string data(reinterpret_cast<char *>(buf), 5);
LongObject o(300);
decodeSucc<Object>(data, o, 5);
}
// eight octet longs
{
unsigned char buf[] = {0x4c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x2c};
std::string data(reinterpret_cast<char *>(buf), 9);
LongObject o(300);
decodeSucc<Object>(data, o, 9);
}
{
// Date Object
unsigned char buf[] = {0x4b, 0x00, 0x00, 0x00, 0x00};
std::string data(reinterpret_cast<char *>(buf), 5);
DateObject o(std::chrono::milliseconds(0));
decodeSucc<Object>(data, o, 5);
}
{
// Double Object
unsigned char buf[] = {0x5d, 0x7f};
std::string data(reinterpret_cast<char *>(buf), 2);
DoubleObject o(127.0);
decodeSucc<Object>(data, o, 2);
}
{
// Typed list Object
unsigned char buf[] = {'V', 0x04, '[', 'i', 'n', 't', 0x92, 0x90, 0x91};
std::string data(reinterpret_cast<char *>(buf), sizeof(buf));
Object::UntypedList o_list;
o_list.emplace_back(std::make_unique<IntegerObject>(0));
o_list.emplace_back(std::make_unique<IntegerObject>(1));
std::string type = "[int";
TypedListObject o(std::move(type), std::move(o_list));
decodeSucc<Object>(data, o, sizeof(buf));
}
{
// Untyped list Object
unsigned char buf[] = {0x57, 0x90, 0x91, 'Z'};
std::string data(reinterpret_cast<char *>(buf), sizeof(buf));
Object::UntypedList o_list;
o_list.emplace_back(std::make_unique<IntegerObject>(0));
o_list.emplace_back(std::make_unique<IntegerObject>(1));
UntypedListObject o(std::move(o_list));
decodeSucc<Object>(data, o, sizeof(buf));
}
{
// Typed map Object
unsigned char buf[] = {'M', 0x03, 'c', 'o', 'm', 0x05, 'c', 'o', 'l',
'o', 'r', 0x05, 'h', 'e', 'l', 'l', 'o', 'Z'};
std::string data(reinterpret_cast<char *>(buf), sizeof(buf));
Object::TypedMap o_map;
o_map.type_name_ = "com";
o_map.field_name_and_value_.emplace(
std::make_unique<StringObject>(absl::string_view("color")),
std::make_unique<StringObject>(absl::string_view("hello")));
TypedMapObject o(std::move(o_map));
decodeSucc<Object>(data, o, sizeof(buf));
}
{
// Untyped map Object
unsigned char buf[] = {'H', 0x05, 'c', 'o', 'l', 'o', 'r',
0x05, 'h', 'e', 'l', 'l', 'o', 'Z'};
std::string data(reinterpret_cast<char *>(buf), sizeof(buf));
Object::UntypedMap o_map;
o_map.emplace(std::make_unique<StringObject>(absl::string_view("color")),
std::make_unique<StringObject>(absl::string_view("hello")));
UntypedMapObject o(std::move(o_map));
decodeSucc<Object>(data, o, sizeof(buf));
}
{
// Class instance Object
unsigned char buf[] = {'C', 0x05, 'h', 'e', 'l', 'l', 'o', 0x92, 0x05,
'c', 'o', 'l', 'o', 'r', 0x05, 'm', 'o', 'd',
'e', 'l', 0x60, 0x05, 'g', 'r', 'e', 'e', 'n',
0x05, 'c', 'i', 'v', 'i', 'c'};
std::string data(reinterpret_cast<char *>(buf), sizeof(buf));
Object::ClassInstance instance;
instance.data_.emplace_back(
std::make_unique<StringObject>(absl::string_view("green")));
instance.data_.emplace_back(
std::make_unique<StringObject>(absl::string_view("civic")));
instance.def_ = std::make_shared<Object::RawDefinition>(
"hello", std::vector<std::string>{"color", "model"});
ClassInstanceObject o(std::move(instance));
decodeSucc<Object>(data, o, sizeof(buf));
}
}
TEST_F(ObjectCodecTest, encode) {
{
// String Object
std::string data{0x05, 'h', 'e', 'l', 'l', 'o'};
StringObject o(absl::string_view("hello"));
encodeSucc<Object>(o, data.size(), data);
}
{
// Binary Object
std::string data{0x23, 0x01, 0x02, 0x03};
BinaryObject o(std::vector<uint8_t>{1, 2, 3});
encodeSucc<Object>(o, data.size(), data);
}
{
// Boolean Object
std::string data{'F'};
BooleanObject o(false);
encodeSucc<Object>(o, data.size(), data);
}
{
// Int Object
std::string data{'\xcf', '\xff'};
IntegerObject o(2047);
encodeSucc<Object>(o, data.size(), data);
}
{
// Long Object
std::string data{'\xff', '\xff'};
LongObject o(2047);
encodeSucc<Object>(o, data.size(), data);
}
{
// Date Object
unsigned char buf[] = {0x4b, 0x00, 0x00, 0x00, 0x00};
std::string data(reinterpret_cast<char *>(buf), 5);
DateObject o(std::chrono::milliseconds(0));
encodeSucc<Object>(o, data.size(), data);
}
{
// Double Object
unsigned char buf[] = {0x5d, 0x7f};
std::string data(reinterpret_cast<char *>(buf), 2);
DoubleObject o(127.0);
encodeSucc<Object>(o, data.size(), data);
}
{
// Typed list Object
unsigned char buf[] = {0x72, 0x04, '[', 'i', 'n', 't', 0x90, 0x91};
std::string data(reinterpret_cast<char *>(buf), sizeof(buf));
Object::UntypedList o_list;
o_list.emplace_back(std::make_unique<IntegerObject>(0));
o_list.emplace_back(std::make_unique<IntegerObject>(1));
std::string type = "[int";
TypedListObject o(std::move(type), std::move(o_list));
encodeSucc<Object>(o, data.size(), data);
}
{
// Untyped list Object
unsigned char buf[] = {0x7a, 0x90, 0x91};
std::string data(reinterpret_cast<char *>(buf), sizeof(buf));
Object::UntypedList o_list;
o_list.emplace_back(std::make_unique<IntegerObject>(0));
o_list.emplace_back(std::make_unique<IntegerObject>(1));
UntypedListObject o(std::move(o_list));
encodeSucc<Object>(o, data.size(), data);
}
{
// Typed map Object
unsigned char buf[] = {'M', 0x03, 'c', 'o', 'm', 0x05, 'c', 'o', 'l',
'o', 'r', 0x05, 'h', 'e', 'l', 'l', 'o', 'Z'};
std::string data(reinterpret_cast<char *>(buf), sizeof(buf));
Object::TypedMap o_map;
o_map.type_name_ = "com";
o_map.field_name_and_value_.emplace(
std::make_unique<StringObject>(absl::string_view("color")),
std::make_unique<StringObject>(absl::string_view("hello")));
TypedMapObject o(std::move(o_map));
encodeSucc<Object>(o, data.size(), data);
}
{
// Untyped map Object
unsigned char buf[] = {'H', 0x05, 'c', 'o', 'l', 'o', 'r',
0x05, 'h', 'e', 'l', 'l', 'o', 'Z'};
std::string data(reinterpret_cast<char *>(buf), sizeof(buf));
Object::UntypedMap o_map;
o_map.emplace(std::make_unique<StringObject>(absl::string_view("color")),
std::make_unique<StringObject>(absl::string_view("hello")));
UntypedMapObject o(std::move(o_map));
encodeSucc<Object>(o, data.size(), data);
}
{
// Class instance Object
unsigned char buf[] = {'C', 0x05, 'h', 'e', 'l', 'l', 'o', 0x92, 0x05,
'c', 'o', 'l', 'o', 'r', 0x05, 'm', 'o', 'd',
'e', 'l', 0x60, 0x05, 'g', 'r', 'e', 'e', 'n',
0x05, 'c', 'i', 'v', 'i', 'c'};
std::string data(reinterpret_cast<char *>(buf), sizeof(buf));
Object::ClassInstance instance;
instance.data_.emplace_back(
std::make_unique<StringObject>(absl::string_view("green")));
instance.data_.emplace_back(
std::make_unique<StringObject>(absl::string_view("civic")));
instance.def_ = std::make_shared<Object::RawDefinition>(
"hello", std::vector<std::string>{"color", "model"});
ClassInstanceObject o(std::move(instance));
encodeSucc<Object>(o, data.size(), data);
}
}
} // namespace Hessian2