hessian2/object_unittests.cc (347 lines of code) (raw):
#include <chrono>
#include <iostream>
#include <type_traits>
#include "gtest/gtest.h"
#include "hessian2/object.hpp"
namespace Hessian2 {
// TODO(tianqian.zyf): Refactor the Test case to avoid code duplication
TEST(ObjectTest, BasicOperation) {
{
Object::TypeRef r1(absl::string_view("ref1"));
Object::TypeRef r2(absl::string_view("ref2"));
Object::TypeRef r3(absl::string_view("ref1"));
EXPECT_EQ(r1, r3);
EXPECT_FALSE(r1 == r2);
}
{
Object::RawDefinition r1;
Object::RawDefinition r2;
EXPECT_EQ(r1, r2);
EXPECT_TRUE(r1.toDebugString().size() > 0);
}
}
TEST(ObjectTest, Binary) {
std::vector<uint8_t> vec{0x0, 0x1, 0x2, 0x3, 0x4};
BinaryObject bin(std::vector<uint8_t>{0x0, 0x1, 0x2, 0x3, 0x4});
EXPECT_NE(bin.toBinary(), absl::nullopt);
EXPECT_EQ(bin.toInteger(), absl::nullopt);
EXPECT_EQ(bin.toLong(), absl::nullopt);
EXPECT_EQ(bin.toDate(), absl::nullopt);
EXPECT_EQ(bin.toTypedList(), absl::nullopt);
EXPECT_EQ(bin.toUntypedList(), absl::nullopt);
EXPECT_EQ(bin.toUntypedMap(), absl::nullopt);
EXPECT_EQ(bin.toTypedMap(), absl::nullopt);
EXPECT_EQ(bin.toClassInstance(), absl::nullopt);
EXPECT_EQ(bin.toRefDest(), absl::nullopt);
EXPECT_TRUE(bin.toDebugString().size() > 0);
EXPECT_EQ(bin.type(), Object::Type::Binary);
EXPECT_TRUE(
std::equal(vec.begin(), vec.end(), bin.toBinary().value().get().begin()));
BinaryObject bin2(std::vector<uint8_t>{0x0, 0x1, 0x2, 0x3, 0x4});
EXPECT_EQ(bin.hash(), bin2.hash());
EXPECT_TRUE(bin.equal(bin2));
}
TEST(ObjectTest, Boolean) {
BooleanObject b(true);
BooleanObject b2(false);
BooleanObject b3(true);
EXPECT_EQ(b.type(), Object::Type::Boolean);
EXPECT_EQ(b.hash(), b3.hash());
EXPECT_EQ(b.toBoolean().value(), true);
EXPECT_TRUE(b.hash() != b2.hash());
EXPECT_TRUE(b.equal(b3));
EXPECT_FALSE(b.equal(b2));
}
TEST(ObjectTest, Double) {
DoubleObject b(0.0);
DoubleObject b2(0.0);
DoubleObject b3(0.1);
EXPECT_EQ(b.toBinary(), absl::nullopt);
EXPECT_EQ(b.toInteger(), absl::nullopt);
EXPECT_EQ(b.toLong(), absl::nullopt);
EXPECT_EQ(b.toDate(), absl::nullopt);
EXPECT_EQ(b.toTypedList(), absl::nullopt);
EXPECT_EQ(b.toUntypedList(), absl::nullopt);
EXPECT_EQ(b.toUntypedMap(), absl::nullopt);
EXPECT_EQ(b.toTypedMap(), absl::nullopt);
EXPECT_EQ(b.toClassInstance(), absl::nullopt);
EXPECT_EQ(b.toRefDest(), absl::nullopt);
EXPECT_TRUE(b.toDebugString().size() > 0);
EXPECT_EQ(b.type(), Object::Type::Double);
EXPECT_EQ(b.hash(), b2.hash());
EXPECT_EQ(b.toDouble().value(), 0.0);
EXPECT_TRUE(b.hash() != b3.hash());
EXPECT_TRUE(b.equal(b2));
EXPECT_FALSE(b3.equal(b2));
}
TEST(ObjectTest, Integer) {
IntegerObject b(0);
IntegerObject b2(0);
IntegerObject b3(1);
EXPECT_EQ(b.type(), Object::Type::Integer);
EXPECT_EQ(b.hash(), b2.hash());
EXPECT_EQ(b.toInteger().value(), 0);
EXPECT_TRUE(b.hash() != b3.hash());
EXPECT_TRUE(b.equal(b2));
EXPECT_FALSE(b3.equal(b2));
}
TEST(ObjectTest, Long) {
LongObject b(0);
LongObject b2(0);
LongObject b3(1);
EXPECT_EQ(b.toBinary(), absl::nullopt);
EXPECT_EQ(b.toInteger(), absl::nullopt);
EXPECT_EQ(b.toDouble(), absl::nullopt);
EXPECT_EQ(b.toDate(), absl::nullopt);
EXPECT_EQ(b.toTypedList(), absl::nullopt);
EXPECT_EQ(b.toUntypedList(), absl::nullopt);
EXPECT_EQ(b.toUntypedMap(), absl::nullopt);
EXPECT_EQ(b.toTypedMap(), absl::nullopt);
EXPECT_EQ(b.toClassInstance(), absl::nullopt);
EXPECT_EQ(b.toRefDest(), absl::nullopt);
EXPECT_TRUE(b.toDebugString().size() > 0);
EXPECT_EQ(b.type(), Object::Type::Long);
EXPECT_EQ(b.hash(), b2.hash());
EXPECT_EQ(b.toLong().value(), 0);
EXPECT_TRUE(b.hash() != b3.hash());
EXPECT_TRUE(b.equal(b2));
EXPECT_FALSE(b3.equal(b2));
}
TEST(ObjectTest, Date) {
DateObject b(std::chrono::milliseconds(100));
DateObject b2(std::chrono::milliseconds(100));
DateObject b3(std::chrono::milliseconds(200));
EXPECT_EQ(b.toBinary(), absl::nullopt);
EXPECT_EQ(b.toInteger(), absl::nullopt);
EXPECT_EQ(b.toDouble(), absl::nullopt);
EXPECT_EQ(b.toLong(), absl::nullopt);
EXPECT_EQ(b.toTypedList(), absl::nullopt);
EXPECT_EQ(b.toUntypedList(), absl::nullopt);
EXPECT_EQ(b.toUntypedMap(), absl::nullopt);
EXPECT_EQ(b.toTypedMap(), absl::nullopt);
EXPECT_EQ(b.toClassInstance(), absl::nullopt);
EXPECT_EQ(b.toRefDest(), absl::nullopt);
EXPECT_TRUE(b.toDebugString().size() > 0);
EXPECT_EQ(b.type(), Object::Type::Date);
EXPECT_EQ(b.hash(), b2.hash());
EXPECT_EQ(b.toDate().value().get().count(), 100);
EXPECT_TRUE(b.hash() != b3.hash());
EXPECT_TRUE(b.equal(b2));
EXPECT_FALSE(b3.equal(b2));
}
TEST(ObjectTest, String) {
StringObject b(absl::string_view("test"));
StringObject b2(absl::string_view("test"));
StringObject b3(absl::string_view("test1"));
EXPECT_EQ(b.toBinary(), absl::nullopt);
EXPECT_EQ(b.toInteger(), absl::nullopt);
EXPECT_EQ(b.toDouble(), absl::nullopt);
EXPECT_EQ(b.toDate(), absl::nullopt);
EXPECT_EQ(b.toLong(), absl::nullopt);
EXPECT_EQ(b.toTypedList(), absl::nullopt);
EXPECT_EQ(b.toUntypedList(), absl::nullopt);
EXPECT_EQ(b.toUntypedMap(), absl::nullopt);
EXPECT_EQ(b.toTypedMap(), absl::nullopt);
EXPECT_EQ(b.toClassInstance(), absl::nullopt);
EXPECT_EQ(b.toRefDest(), absl::nullopt);
EXPECT_TRUE(b.toDebugString().size() > 0);
EXPECT_EQ(b.type(), Object::Type::String);
EXPECT_EQ(b.hash(), b2.hash());
EXPECT_TRUE(b.toString().value().get() == "test");
EXPECT_TRUE(b.hash() != b3.hash());
EXPECT_TRUE(b.equal(b2));
EXPECT_FALSE(b3.equal(b2));
}
TEST(ObjectTest, Null) {
NullObject p;
NullObject p2;
EXPECT_EQ(p.toDebugString(), std::string("Type: Null"));
EXPECT_EQ(p.type(), Object::Type::Null);
EXPECT_TRUE(p.equal(p2));
EXPECT_EQ(p.hash(), p2.hash());
}
TEST(ObjectTest, Ref) {
StringObject r(absl::string_view("ref"));
RefObject p(&r);
RefObject p2(&r);
EXPECT_TRUE(p.toDebugString().size() > 0);
EXPECT_EQ(p.type(), Object::Type::Ref);
EXPECT_TRUE(p.equal(p2));
EXPECT_EQ(p.hash(), p2.hash());
EXPECT_TRUE(p.toRefDest().value()->toString().value().get() == "ref");
}
TEST(ObjectTest, UntypedList) {
Object::UntypedList untyped_list1;
Object::UntypedList untyped_list2;
Object::UntypedList untyped_list3;
untyped_list1.push_back(
std::make_unique<StringObject>(absl::string_view("obj1")));
untyped_list1.push_back(std::make_unique<IntegerObject>(1));
untyped_list1.push_back(std::make_unique<BooleanObject>(true));
untyped_list2.push_back(
std::make_unique<StringObject>(absl::string_view("obj1")));
untyped_list2.push_back(std::make_unique<IntegerObject>(1));
untyped_list2.push_back(std::make_unique<BooleanObject>(true));
untyped_list3.push_back(
std::make_unique<StringObject>(absl::string_view("obj1")));
untyped_list3.push_back(std::make_unique<IntegerObject>(1));
UntypedListObject p(std::move(untyped_list1));
UntypedListObject p2(std::move(untyped_list2));
UntypedListObject p3(std::move(untyped_list3));
EXPECT_NE(p.toUntypedList(), absl::nullopt);
EXPECT_TRUE(p.toDebugString().size() > 0);
EXPECT_EQ(p.type(), Object::Type::UntypedList);
EXPECT_EQ(p.hash(), p2.hash());
EXPECT_TRUE(p.equal(p2));
EXPECT_FALSE(p.equal(p3));
EXPECT_TRUE(p.toUntypedList().value().get().size() == 3);
UntypedListObject p4;
p4.emplace_back(std::make_unique<IntegerObject>(1));
p4.emplace_back(std::make_unique<BooleanObject>(true));
EXPECT_TRUE(p4.get(0)->toInteger().value() == 1);
EXPECT_TRUE(p4.get(1)->toBoolean().value());
EXPECT_TRUE(p4.get(2) == nullptr);
}
TEST(ObjectTest, TypedList) {
Object::UntypedList untyped_list1;
Object::UntypedList untyped_list2;
Object::UntypedList untyped_list3;
untyped_list1.push_back(
std::make_unique<StringObject>(absl::string_view("obj1")));
untyped_list1.push_back(std::make_unique<IntegerObject>(1));
untyped_list1.push_back(std::make_unique<BooleanObject>(true));
untyped_list2.push_back(
std::make_unique<StringObject>(absl::string_view("obj1")));
untyped_list2.push_back(std::make_unique<IntegerObject>(1));
untyped_list2.push_back(std::make_unique<BooleanObject>(true));
untyped_list3.push_back(
std::make_unique<StringObject>(absl::string_view("obj1")));
untyped_list3.push_back(std::make_unique<IntegerObject>(1));
TypedListObject p(std::string("typ1"), std::move(untyped_list1));
TypedListObject p2(std::string("typ2"), std::move(untyped_list2));
TypedListObject p3(std::string("typ1"), std::move(untyped_list3));
EXPECT_TRUE(p.toDebugString().size() > 0);
EXPECT_EQ(p.type(), Object::Type::TypedList);
EXPECT_NE(p.hash(), p2.hash());
EXPECT_FALSE(p.equal(p2));
EXPECT_FALSE(p.equal(p3));
EXPECT_FALSE(p2.equal(p3));
EXPECT_TRUE(p.toTypedList().value().get().values_.size() == 3);
TypedListObject p4;
p4.emplace_back(std::make_unique<IntegerObject>(1));
p4.emplace_back(std::make_unique<BooleanObject>(true));
EXPECT_TRUE(p4.get(0)->toInteger().value() == 1);
EXPECT_TRUE(p4.get(1)->toBoolean().value());
EXPECT_TRUE(p4.get(2) == nullptr);
}
TEST(ObjectTest, UntypedMap) {
Object::UntypedMap untyped_map1;
Object::UntypedMap untyped_map2;
untyped_map1.emplace(
std::make_pair(std::make_unique<StringObject>(absl::string_view("key1")),
std::make_unique<IntegerObject>(1)));
UntypedMapObject p(std::move(untyped_map1));
EXPECT_EQ(p.type(), Object::Type::UntypedMap);
EXPECT_EQ(p.toUntypedMap().value().get().size(), 1);
EXPECT_TRUE(p.toDebugString().size() > 0);
untyped_map2.emplace(
std::make_pair(std::make_unique<StringObject>(absl::string_view("key1")),
std::make_unique<IntegerObject>(1)));
UntypedMapObject p2(std::move(untyped_map2));
EXPECT_EQ(p2.toUntypedMap().value().get().size(), 1);
EXPECT_EQ(p.hash(), p2.hash());
EXPECT_TRUE(p.equal(p2));
// heterogeneous lookup by string view.
EXPECT_EQ(p.toUntypedMap()
.value()
.get()
.find(absl::string_view("key1"))
->second->toInteger()
.value()
.get(),
1);
EXPECT_EQ(p2.toUntypedMap()
.value()
.get()
.find("key1")
->second->toInteger()
.value()
.get(),
1);
}
TEST(ObjectTest, TypedMap) {
Object::TypedMap map1;
Object::TypedMap map2;
Object::TypedMap map3;
map1.type_name_ = std::string("type1");
map1.field_name_and_value_.emplace(
std::make_pair(std::make_unique<StringObject>(absl::string_view("key1")),
std::make_unique<IntegerObject>(1)));
TypedMapObject p(std::move(map1));
EXPECT_TRUE(p.toDebugString().size() > 0);
EXPECT_TRUE(p.get("key1")->toInteger().value() == 1);
EXPECT_EQ(p.type(), Object::Type::TypedMap);
EXPECT_EQ(p.toTypedMap().value().get().field_name_and_value_.size(), 1);
map2.type_name_ = std::string("type1");
map2.field_name_and_value_.emplace(
std::make_pair(std::make_unique<StringObject>(absl::string_view("key1")),
std::make_unique<IntegerObject>(2)));
TypedMapObject p2(std::move(map2));
map3.type_name_ = std::string("type2");
map3.field_name_and_value_.emplace(
std::make_pair(std::make_unique<StringObject>(absl::string_view("key1")),
std::make_unique<IntegerObject>(2)));
TypedMapObject p3(std::move(map3));
EXPECT_TRUE(p3.get("key1")->toInteger().value() == 2);
TypedMapObject p4;
p4.emplace(std::make_unique<StringObject>(absl::string_view("key2")),
std::make_unique<StringObject>(absl::string_view("key3")));
EXPECT_TRUE(p4.get("key2")->toString().value().get() == std::string("key3"));
// p and p2 have the same hash value because they have the same type and
// element size,
// but they are not actually the same.
EXPECT_EQ(p.hash(), p2.hash());
EXPECT_FALSE(p.equal(p2));
EXPECT_NE(p.hash(), p3.hash());
EXPECT_NE(p2.hash(), p3.hash());
EXPECT_FALSE(p.equal(p3));
EXPECT_FALSE(p2.equal(p3));
}
TEST(ObjectTest, ClassInstance) {
Object::ClassInstance instance1;
Object::ClassInstance instance2;
Object::ClassInstance instance3;
Object::RawDefinitionSharedPtr d1 = std::make_shared<Object::RawDefinition>();
d1->type_ = "type1";
Object::RawDefinitionSharedPtr d2 = std::make_shared<Object::RawDefinition>();
d2->type_ = "type2";
instance1.def_ = d1;
instance2.def_ = d1;
instance3.def_ = d2;
ClassInstanceObject p1(std::move(instance1));
ClassInstanceObject p2(std::move(instance2));
ClassInstanceObject p3(std::move(instance3));
EXPECT_TRUE(p1.toDebugString().size() > 0);
EXPECT_EQ(p1.hash(), p2.hash());
EXPECT_NE(p1.hash(), p3.hash());
EXPECT_NE(p2.hash(), p3.hash());
EXPECT_TRUE(p1.equal(p2));
EXPECT_FALSE(p1.equal(p3));
EXPECT_FALSE(p2.equal(p3));
}
TEST(ObjectTest, AsType) {
BooleanObject b(true);
Object* obj_b = &b;
auto convert_after = obj_b->asType<BooleanObject>();
EXPECT_EQ(convert_after.type(), Object::Type::Boolean);
EXPECT_EQ(convert_after.toBoolean().value(), true);
}
TEST(ObjectTest, Iterator) {
StringObject b(absl::string_view("test"));
const StringObject const_b(absl::string_view("test"));
std::string actual;
for (const auto& i : b) {
actual.push_back(i);
}
std::string const_actual;
for (const auto& i : const_b) {
const_actual.push_back(i);
}
EXPECT_EQ(const_actual, const_b.toString().value().get());
}
} // namespace Hessian2