Files
2026-07-13 12:47:42 +08:00

458 lines
14 KiB
C++

// Copyright 2025-present the zvec project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string>
#include <vector>
#include <gtest/gtest.h>
#include <zvec/ailego/container/cube.h>
using namespace zvec::ailego;
TEST(Cube, TypeInfo) {
std::cout << "* bool: " << typeid(bool).name() << std::endl;
std::cout << "* int8_t: " << typeid(int8_t).name() << std::endl;
std::cout << "* char: " << typeid(char).name() << std::endl;
std::cout << "* signed char: " << typeid(signed char).name()
<< std::endl;
std::cout << "* uint8_t: " << typeid(uint8_t).name() << std::endl;
std::cout << "* unsigned char: " << typeid(unsigned char).name()
<< std::endl;
std::cout << "* int16_t: " << typeid(int16_t).name() << std::endl;
std::cout << "* short: " << typeid(short).name() << std::endl;
std::cout << "* signed short: " << typeid(signed short).name()
<< std::endl;
std::cout << "* uint16_t: " << typeid(uint16_t).name()
<< std::endl;
std::cout << "* unsigned short: " << typeid(unsigned short).name()
<< std::endl;
std::cout << "* int32_t: " << typeid(int32_t).name() << std::endl;
std::cout << "* int: " << typeid(int).name() << std::endl;
std::cout << "* signed int: " << typeid(signed int).name()
<< std::endl;
std::cout << "* uint32_t: " << typeid(uint32_t).name()
<< std::endl;
std::cout << "* unsigned int: " << typeid(unsigned int).name()
<< std::endl;
std::cout << "* int64_t: " << typeid(int64_t).name() << std::endl;
std::cout << "* long: " << typeid(long).name() << std::endl;
std::cout << "* signed long: " << typeid(signed long).name()
<< std::endl;
std::cout << "* uint64_t: " << typeid(uint64_t).name()
<< std::endl;
std::cout << "* unsigned long: " << typeid(unsigned long).name()
<< std::endl;
std::cout << "* long long: " << typeid(long).name() << std::endl;
std::cout << "* signed long long: " << typeid(signed long).name()
<< std::endl;
std::cout << "* unsigned long long: " << typeid(unsigned long).name()
<< std::endl;
}
TEST(Cube, General) {
Cube cube1 = 11111;
EXPECT_EQ(11111, cube1.unsafe_cast<int>());
EXPECT_EQ(11111, cube1.cast<int>());
int int1 = cube1;
EXPECT_EQ(11111, int1);
EXPECT_TRUE(!cube1.empty());
EXPECT_EQ(sizeof(int), cube1.size());
Cube cube2 = 22222;
EXPECT_EQ(22222, cube2.unsafe_cast<int>());
EXPECT_EQ(22222, cube2.cast<int>());
int int2 = (const int &)cube2;
EXPECT_EQ(22222, int2);
EXPECT_TRUE(!cube2.empty());
EXPECT_EQ(sizeof(int), cube2.size());
Cube cube3 = std::vector<int>();
cube3.unsafe_cast<std::vector<int>>().push_back(1);
cube3.unsafe_cast<std::vector<int>>().push_back(2);
cube3.unsafe_cast<std::vector<int>>().push_back(3);
EXPECT_EQ(3u, cube3.unsafe_cast<std::vector<int>>().size());
EXPECT_EQ(3u, cube3.cast<std::vector<int>>().size());
std::vector<int> &vec3 = cube3;
EXPECT_EQ(3u, vec3.size());
EXPECT_TRUE(!cube3.empty());
EXPECT_EQ(sizeof(std::vector<int>), cube3.size());
std::vector<long> vec4;
vec4.push_back(1);
vec4.push_back(2);
vec4.push_back(3);
vec4.push_back(4);
Cube cube4 = vec4;
EXPECT_EQ(4u, cube4.unsafe_cast<std::vector<long>>().size());
EXPECT_EQ(4u, cube4.cast<std::vector<long>>().size());
const std::vector<long> &vec44 = cube4;
EXPECT_EQ(4u, vec44.size());
EXPECT_TRUE(!cube4.empty());
EXPECT_EQ(sizeof(std::vector<long>), cube4.size());
Cube cube5, cube6;
EXPECT_TRUE(cube5.empty());
EXPECT_TRUE(cube6.empty());
EXPECT_EQ(cube5.type(), cube6.type());
EXPECT_EQ(0u, cube5.size());
EXPECT_EQ(0u, cube6.size());
EXPECT_EQ(cube1.type(), cube2.type());
EXPECT_NE(cube3.type(), cube4.type());
EXPECT_NE(cube1.type(), cube3.type());
EXPECT_NE(cube2.type(), cube4.type());
EXPECT_NE(cube1.type(), cube5.type());
EXPECT_NE(cube2.type(), cube5.type());
EXPECT_NE(cube3.type(), cube5.type());
EXPECT_NE(cube4.type(), cube5.type());
EXPECT_TRUE(cube1.compatible(cube2));
EXPECT_TRUE(cube5.compatible(cube6));
EXPECT_FALSE(cube1.compatible(cube3));
EXPECT_FALSE(cube3.compatible(cube5));
cube1.reset();
cube3.reset();
cube5.reset();
cube6.reset();
EXPECT_TRUE(cube1.empty());
EXPECT_TRUE(cube3.empty());
EXPECT_TRUE(cube5.empty());
EXPECT_TRUE(cube6.empty());
}
TEST(Cube, LargeObject) {
std::string str1("1111111");
std::string str2("2222222");
std::string str3("3333333");
std::string str4("4444444");
std::string str5("5555555");
std::string str6("6666666");
std::string str7("7777777");
Cube cube1(str1);
Cube cube2;
cube2 = str2;
Cube cube3 = str3;
EXPECT_EQ(str1, cube1.cast<std::string>());
EXPECT_EQ(str2, cube2.cast<std::string>());
EXPECT_TRUE(cube1.compatible(cube2));
cube1 = std::move(cube2);
EXPECT_EQ(str2, cube1.cast<std::string>());
EXPECT_TRUE(cube2.empty());
EXPECT_FALSE(cube1.compatible(cube2));
EXPECT_EQ(str3, cube3.cast<std::string>());
cube3 = cube1;
EXPECT_EQ(str2, cube3.cast<std::string>());
EXPECT_EQ(str2, cube1.cast<std::string>());
// Test Constructor Cube(T &&rhs) / Cube(const T &rhs)
Cube cube41(std::string("444444"));
Cube cube42(str4);
EXPECT_NE(std::string(""), str4);
Cube cube43(std::move(str4));
EXPECT_EQ(std::string(""), str4);
const std::string str41 = str4;
Cube cube44(str41);
EXPECT_EQ(str41, str4);
EXPECT_EQ(str4, cube44.cast<std::string>());
// Test Assignment operator=(T &&rhs) / operator=(const T &rhs)
Cube cube51, cube52, cube53, cube54;
cube51 = std::string("55555");
cube52 = str5;
EXPECT_NE(std::string(""), str5);
cube53 = std::move(str5);
EXPECT_EQ(std::string(""), str5);
const std::string str51 = str5;
cube54 = str51;
EXPECT_EQ(str51, str5);
EXPECT_EQ(str5, cube54.cast<std::string>());
// Test Constructor Cube(Cube &&rhs) / Cube(const Cube &rhs)
Cube cube6(str6);
Cube cube61(cube6);
EXPECT_EQ(str6, cube61.cast<std::string>());
EXPECT_FALSE(cube6.empty());
Cube cube62(std::move(cube6));
EXPECT_EQ(str6, cube62.cast<std::string>());
EXPECT_TRUE(cube6.empty());
const Cube cube63 = cube62;
Cube cube64(cube63);
EXPECT_EQ(str6, cube64.cast<std::string>());
EXPECT_FALSE(cube63.empty());
// Test Assignment operator=(Cube &&rhs) / operator=(const Cube &rhs)
Cube cube7(str7), cube71, cube72;
cube71 = cube7;
EXPECT_EQ(str7, cube71.cast<std::string>());
EXPECT_FALSE(cube7.empty());
cube72 = std::move(cube7);
EXPECT_EQ(str7, cube72.cast<std::string>());
EXPECT_TRUE(cube7.empty());
const Cube cube73(cube72);
Cube cube74;
cube74 = cube73;
EXPECT_EQ(str7, cube74.cast<std::string>());
EXPECT_EQ(str7, cube73.cast<std::string>());
EXPECT_FALSE(cube74.empty());
}
struct SmallObject {
SmallObject() {
++assign_count;
}
SmallObject(const SmallObject &) {
++clone_count;
}
SmallObject(SmallObject &&) {
++move_count;
}
~SmallObject() {
++cleanup_count;
}
int val{0};
static int assign_count;
static int clone_count;
static int move_count;
static int cleanup_count;
};
int SmallObject::assign_count = 0;
int SmallObject::clone_count = 0;
int SmallObject::move_count = 0;
int SmallObject::cleanup_count = 0;
TEST(Cube, CubePolicy) {
EXPECT_EQ(0, SmallObject::assign_count);
EXPECT_EQ(0, SmallObject::clone_count);
EXPECT_EQ(0, SmallObject::move_count);
EXPECT_EQ(0, SmallObject::cleanup_count);
SmallObject obj1, obj2, obj3, obj4, obj5;
EXPECT_EQ(5, SmallObject::assign_count);
EXPECT_EQ(0, SmallObject::clone_count);
EXPECT_EQ(0, SmallObject::move_count);
EXPECT_EQ(0, SmallObject::cleanup_count);
Cube cube1(obj1);
EXPECT_EQ(5, SmallObject::assign_count);
EXPECT_EQ(1, SmallObject::clone_count);
EXPECT_EQ(0, SmallObject::move_count);
EXPECT_EQ(0, SmallObject::cleanup_count);
Cube cube2(std::move(obj2));
EXPECT_EQ(5, SmallObject::assign_count);
EXPECT_EQ(1, SmallObject::clone_count);
EXPECT_EQ(1, SmallObject::move_count);
EXPECT_EQ(0, SmallObject::cleanup_count);
{
Cube cube3(std::move(obj3));
EXPECT_EQ(5, SmallObject::assign_count);
EXPECT_EQ(1, SmallObject::clone_count);
EXPECT_EQ(2, SmallObject::move_count);
EXPECT_EQ(0, SmallObject::cleanup_count);
}
EXPECT_EQ(5, SmallObject::assign_count);
EXPECT_EQ(1, SmallObject::clone_count);
EXPECT_EQ(2, SmallObject::move_count);
EXPECT_EQ(1, SmallObject::cleanup_count);
{
Cube cube4(obj4);
EXPECT_EQ(5, SmallObject::assign_count);
EXPECT_EQ(2, SmallObject::clone_count);
EXPECT_EQ(2, SmallObject::move_count);
EXPECT_EQ(1, SmallObject::cleanup_count);
}
EXPECT_EQ(5, SmallObject::assign_count);
EXPECT_EQ(2, SmallObject::clone_count);
EXPECT_EQ(2, SmallObject::move_count);
EXPECT_EQ(2, SmallObject::cleanup_count);
{
Cube cube5(obj5);
EXPECT_EQ(5, SmallObject::assign_count);
EXPECT_EQ(3, SmallObject::clone_count);
EXPECT_EQ(2, SmallObject::move_count);
EXPECT_EQ(2, SmallObject::cleanup_count);
}
EXPECT_EQ(5, SmallObject::assign_count);
EXPECT_EQ(3, SmallObject::clone_count);
EXPECT_EQ(2, SmallObject::move_count);
EXPECT_EQ(3, SmallObject::cleanup_count);
}
TEST(Cube, SmallObject) {
uint64_t uint1 = 1111111;
uint64_t uint2 = 2222222;
uint64_t uint3 = 3333333;
uint64_t uint4 = 4444444;
uint64_t uint5 = 5555555;
uint64_t uint6 = 6666666;
uint64_t uint7 = 7777777;
Cube cube1(uint1);
Cube cube2;
cube2 = uint2;
Cube cube3 = uint3;
EXPECT_EQ(uint1, cube1.cast<uint64_t>());
EXPECT_EQ(uint2, cube2.cast<uint64_t>());
EXPECT_TRUE(cube1.compatible(cube2));
cube1 = std::move(cube2);
EXPECT_EQ(uint2, cube1.cast<uint64_t>());
EXPECT_TRUE(cube2.empty());
EXPECT_FALSE(cube1.compatible(cube2));
EXPECT_EQ(uint3, cube3.cast<uint64_t>());
cube3 = cube1;
EXPECT_EQ(uint2, cube3.cast<uint64_t>());
EXPECT_EQ(uint2, cube1.cast<uint64_t>());
// Test Conuintuctor Cube(T &&rhs) / Cube(const T &rhs)
Cube cube41(uint64_t(444444));
Cube cube42(uint4);
EXPECT_NE(uint64_t(0), uint4);
Cube cube43(std::move(uint4));
EXPECT_NE(uint64_t(0), uint4);
const uint64_t uint41 = uint4;
Cube cube44(uint41);
EXPECT_EQ(uint41, uint4);
EXPECT_EQ(uint4, cube44.cast<uint64_t>());
// Test Assignment operator=(T &&rhs) / operator=(const T &rhs)
Cube cube51, cube52, cube53, cube54;
cube51 = uint64_t(55555);
cube52 = uint5;
EXPECT_NE(uint64_t(0), uint5);
cube53 = std::move(uint5);
EXPECT_NE(uint64_t(0), uint5);
const uint64_t uint51 = uint5;
cube54 = uint51;
EXPECT_EQ(uint51, uint5);
EXPECT_EQ(uint5, cube54.cast<uint64_t>());
// Test Conuintuctor Cube(Cube &&rhs) / Cube(const Cube &rhs)
Cube cube6(uint6);
Cube cube61(cube6);
EXPECT_EQ(uint6, cube61.cast<uint64_t>());
EXPECT_FALSE(cube6.empty());
Cube cube62(std::move(cube6));
EXPECT_EQ(uint6, cube62.cast<uint64_t>());
EXPECT_TRUE(cube6.empty());
const Cube cube63 = cube62;
Cube cube64(cube63);
EXPECT_EQ(uint6, cube64.cast<uint64_t>());
EXPECT_FALSE(cube63.empty());
// Test Assignment operator=(Cube &&rhs) / operator=(const Cube &rhs)
Cube cube7(uint7), cube71, cube72;
cube71 = cube7;
EXPECT_EQ(uint7, cube71.cast<uint64_t>());
EXPECT_FALSE(cube7.empty());
cube72 = std::move(cube7);
EXPECT_EQ(uint7, cube72.cast<uint64_t>());
EXPECT_TRUE(cube7.empty());
const Cube cube73(cube72);
Cube cube74;
cube74 = cube73;
EXPECT_EQ(uint7, cube74.cast<uint64_t>());
EXPECT_EQ(uint7, cube73.cast<uint64_t>());
EXPECT_FALSE(cube74.empty());
}
enum EnumValueType { Unknown, Binary, Float, Double };
enum class EnumClassType { Unknown, RED, GREEN, BLUE };
TEST(Cube, EnumObject) {
std::cout << "* uint32_t: " << typeid(uint32_t).name() << std::endl;
std::cout << "* int32_t: " << typeid(int32_t).name() << std::endl;
std::cout << "* EnumValueType: " << typeid(EnumValueType).name() << std::endl;
std::cout << "* EnumValueType (underlying_type): "
<< typeid(typename std::underlying_type<EnumValueType>::type).name()
<< std::endl;
std::cout << "* EnumClassType: " << typeid(EnumClassType).name() << std::endl;
std::cout << "* EnumClassType (underlying_type): "
<< typeid(typename std::underlying_type<EnumClassType>::type).name()
<< std::endl;
EnumValueType a(EnumValueType::Binary), c(EnumValueType::Unknown);
EnumClassType b(EnumClassType::RED), d(EnumClassType::Unknown);
Cube cubeA(a);
Cube cubeB(b);
EXPECT_EQ(a, cubeA.cast<EnumValueType>());
EXPECT_NE(c, cubeA.cast<EnumValueType>());
c = cubeA.cast<EnumValueType>();
EXPECT_EQ(a, c);
EXPECT_EQ(b, cubeB.cast<EnumClassType>());
EXPECT_NE(d, cubeB.cast<EnumClassType>());
d = cubeB.cast<EnumClassType>();
EXPECT_EQ(b, d);
Cube cubeC((std::underlying_type<EnumValueType>::type)1);
Cube cubeD((std::underlying_type<EnumClassType>::type)1);
std::cout << "* cubeA: " << cubeA.type().name() << std::endl;
std::cout << "* cubeB: " << cubeB.type().name() << std::endl;
std::cout << "* cubeC: " << cubeC.type().name() << std::endl;
std::cout << "* cubeD: " << cubeD.type().name() << std::endl;
// EXPECT_TRUE(typeid(std::underlying_type<EnumValueType>::type) ==
// typeid(uint32_t));
// EXPECT_TRUE(typeid(std::underlying_type<EnumClassType>::type) ==
// typeid(int32_t));
EXPECT_TRUE(cubeA.compatible<EnumValueType>());
EXPECT_TRUE(cubeB.compatible<EnumClassType>());
EXPECT_TRUE(cubeA.compatible<std::underlying_type<EnumValueType>::type>());
EXPECT_TRUE(cubeB.compatible<std::underlying_type<EnumClassType>::type>());
EXPECT_TRUE(cubeC.compatible<std::underlying_type<EnumValueType>::type>());
EXPECT_TRUE(cubeD.compatible<std::underlying_type<EnumClassType>::type>());
EnumValueType e =
(EnumValueType)cubeA.cast<std::underlying_type<EnumValueType>::type>();
EnumClassType f =
(EnumClassType)cubeB.cast<std::underlying_type<EnumClassType>::type>();
EXPECT_EQ(a, e);
EXPECT_EQ(b, f);
}