536 lines
12 KiB
C++
536 lines
12 KiB
C++
/**
|
||
* @file test_base.cpp
|
||
* @brief base 模块单元测试(Array、String)
|
||
*
|
||
*
|
||
* @version 1.0
|
||
* @author CodeBuddy
|
||
* @date 26-09-03
|
||
*
|
||
* @note
|
||
*/
|
||
#include <gtest/gtest.h>
|
||
|
||
#include "dl_type.h"
|
||
#include "base/dl_string.h"
|
||
#include "base/dl_range_find.h"
|
||
#include "base/dl_range_select.h"
|
||
#include "base/dl_range_every.h"
|
||
#include "base/dl_range_erase.h"
|
||
#include "base/dl_tree.h"
|
||
#include "base/dl_vector2.h"
|
||
|
||
//------------------------------Array------------------------------
|
||
TEST(ArrayTest, Position)
|
||
{
|
||
dl::Position p;
|
||
p.x = 1.0f;
|
||
p.y = 2.0f;
|
||
EXPECT_FLOAT_EQ(p.x, 1.0f);
|
||
EXPECT_FLOAT_EQ(p.y, 2.0f);
|
||
EXPECT_FLOAT_EQ(p[0], 1.0f);
|
||
EXPECT_FLOAT_EQ(p[1], 2.0f);
|
||
}
|
||
|
||
TEST(ArrayTest, Position3)
|
||
{
|
||
dl::Position3 p;
|
||
p.x = 1.0f;
|
||
p.y = 2.0f;
|
||
p.z = 3.0f;
|
||
EXPECT_FLOAT_EQ(p[0], 1.0f);
|
||
EXPECT_FLOAT_EQ(p[1], 2.0f);
|
||
EXPECT_FLOAT_EQ(p[2], 3.0f);
|
||
}
|
||
|
||
TEST(ArrayTest, Size)
|
||
{
|
||
dl::Size s;
|
||
s.w = 800;
|
||
s.h = 600;
|
||
EXPECT_EQ(s.w, 800u);
|
||
EXPECT_EQ(s.h, 600u);
|
||
EXPECT_EQ(s[0], 800u);
|
||
EXPECT_EQ(s[1], 600u);
|
||
}
|
||
|
||
TEST(ArrayTest, InitList)
|
||
{
|
||
dl::Position p{ 10.0f, 20.0f };
|
||
EXPECT_FLOAT_EQ(p.x, 10.0f);
|
||
EXPECT_FLOAT_EQ(p.y, 20.0f);
|
||
}
|
||
|
||
//------------------------------String------------------------------
|
||
TEST(StringTest, SplitView)
|
||
{
|
||
auto vec = dl::String::SplitView("a,b,c", ',');
|
||
ASSERT_EQ(vec.size(), 3u);
|
||
EXPECT_EQ(vec[0], "a");
|
||
EXPECT_EQ(vec[1], "b");
|
||
EXPECT_EQ(vec[2], "c");
|
||
}
|
||
|
||
TEST(StringTest, SplitViewNoEmpty)
|
||
{
|
||
auto vec = dl::String::SplitViewNoEmpty("a,,b,", ',');
|
||
ASSERT_EQ(vec.size(), 2u);
|
||
EXPECT_EQ(vec[0], "a");
|
||
EXPECT_EQ(vec[1], "b");
|
||
}
|
||
|
||
TEST(StringTest, ToLowerUpper)
|
||
{
|
||
EXPECT_EQ(dl::String::ToLower("ABC"), "abc");
|
||
EXPECT_EQ(dl::String::ToUpper("abc"), "ABC");
|
||
}
|
||
|
||
TEST(StringTest, ToInt)
|
||
{
|
||
EXPECT_EQ(dl::String::toInt("123"), 123);
|
||
EXPECT_EQ(dl::String::toInt("abc", -1), -1);
|
||
}
|
||
|
||
TEST(StringTest, ToFloat)
|
||
{
|
||
EXPECT_FLOAT_EQ(dl::String::toFloat("1.5"), 1.5f);
|
||
EXPECT_FLOAT_EQ(dl::String::toFloat("abc", 0.0f), 0.0f);
|
||
}
|
||
|
||
TEST(StringTest, EraseBlankBoth)
|
||
{
|
||
EXPECT_EQ(dl::String::EraseBlankBoth(" hello "), "hello");
|
||
}
|
||
|
||
TEST(StringTest, ReplaceExtension)
|
||
{
|
||
EXPECT_EQ(dl::String::ReplaceExtension("a/b/c.txt", "png"), "a/b/c.png");
|
||
}
|
||
|
||
TEST(StringTest, EraseFilename)
|
||
{
|
||
EXPECT_EQ(dl::String::EraseFilename("a/b/c.txt"), "a/b/");
|
||
}
|
||
|
||
TEST(StringTest, IsRelativePath)
|
||
{
|
||
EXPECT_TRUE(dl::String::IsRelativePath("a/b/c.txt"));
|
||
EXPECT_FALSE(dl::String::IsRelativePath("/a/b/c.txt"));
|
||
}
|
||
|
||
TEST(StringTest, ToBool)
|
||
{
|
||
EXPECT_TRUE(dl::String::toBool("1"));
|
||
EXPECT_FALSE(dl::String::toBool("0"));
|
||
EXPECT_FALSE(dl::String::toBool("abc"));
|
||
EXPECT_TRUE(dl::String::toBool("abc", true));
|
||
}
|
||
|
||
TEST(StringTest, ToBoolEx)
|
||
{
|
||
EXPECT_TRUE(dl::String::toBoolEx("true"));
|
||
EXPECT_FALSE(dl::String::toBoolEx("false"));
|
||
EXPECT_TRUE(dl::String::toBoolEx("TRUE"));
|
||
EXPECT_TRUE(dl::String::toBoolEx("1"));
|
||
EXPECT_FALSE(dl::String::toBoolEx("abc"));
|
||
}
|
||
|
||
TEST(StringTest, AddQuotes)
|
||
{
|
||
EXPECT_EQ(dl::String::AddQuotes("hello"), "\"hello\"");
|
||
}
|
||
|
||
TEST(StringTest, IsBegin)
|
||
{
|
||
EXPECT_TRUE(dl::String::IsBegin("hello world", "hello"));
|
||
EXPECT_FALSE(dl::String::IsBegin("hello", "hello world"));
|
||
}
|
||
|
||
TEST(StringTest, ErasePath)
|
||
{
|
||
EXPECT_EQ(dl::String::ErasePath("a/b/c.txt", "a/"), "b/c.txt");
|
||
}
|
||
|
||
TEST(StringTest, SplitViewSub)
|
||
{
|
||
auto vec = dl::String::SplitView("a-b-c", "-");
|
||
ASSERT_EQ(vec.size(), 3u);
|
||
EXPECT_EQ(vec[0], "a");
|
||
EXPECT_EQ(vec[1], "b");
|
||
EXPECT_EQ(vec[2], "c");
|
||
}
|
||
|
||
TEST(StringTest, Range)
|
||
{
|
||
EXPECT_EQ(dl::String::Range("a[1,2]b", '[', ']'), "1,2");
|
||
}
|
||
|
||
//------------------------------Array 运算符------------------------------
|
||
TEST(ArrayTest, OperatorAddSub)
|
||
{
|
||
dl::Position a{ 1.0f, 2.0f };
|
||
dl::Position b{ 3.0f, 4.0f };
|
||
auto c = a + b;
|
||
EXPECT_FLOAT_EQ(c[0], 4.0f);
|
||
EXPECT_FLOAT_EQ(c[1], 6.0f);
|
||
|
||
auto d = a - b;
|
||
EXPECT_FLOAT_EQ(d[0], -2.0f);
|
||
EXPECT_FLOAT_EQ(d[1], -2.0f);
|
||
}
|
||
|
||
TEST(ArrayTest, OperatorMulDivScalar)
|
||
{
|
||
dl::Position a{ 2.0f, 4.0f };
|
||
auto c = a * 3.0f;
|
||
EXPECT_FLOAT_EQ(c[0], 6.0f);
|
||
EXPECT_FLOAT_EQ(c[1], 12.0f);
|
||
|
||
auto d = a / 2.0f;
|
||
EXPECT_FLOAT_EQ(d[0], 1.0f);
|
||
EXPECT_FLOAT_EQ(d[1], 2.0f);
|
||
}
|
||
|
||
TEST(ArrayTest, OperatorMulArray)
|
||
{
|
||
dl::Position a{ 2.0f, 3.0f };
|
||
dl::Position b{ 4.0f, 5.0f };
|
||
auto c = a * b;
|
||
EXPECT_FLOAT_EQ(c[0], 8.0f);
|
||
EXPECT_FLOAT_EQ(c[1], 15.0f);
|
||
}
|
||
|
||
TEST(ArrayTest, OperatorNeg)
|
||
{
|
||
dl::Position a{ 1.0f, -2.0f };
|
||
auto c = -a;
|
||
EXPECT_FLOAT_EQ(c[0], -1.0f);
|
||
EXPECT_FLOAT_EQ(c[1], 2.0f);
|
||
}
|
||
|
||
//------------------------------Find------------------------------
|
||
TEST(FindTest, FirstIndex)
|
||
{
|
||
std::vector<int> v = { 10, 20, 30, 40 };
|
||
EXPECT_EQ(dl::Find::FirstIndex(v, 30), 2u);
|
||
EXPECT_EQ(dl::Find::FirstIndex(v, 10), 0u);
|
||
EXPECT_EQ(dl::Find::FirstIndex(v, 99), (size_t)-1);
|
||
}
|
||
|
||
TEST(FindTest, FirstYes)
|
||
{
|
||
std::vector<int> v = { 1, 3, 5, 8 };
|
||
auto* p = dl::Find::FirstYes(v, [](int x) { return x % 2 == 0; });
|
||
ASSERT_NE(p, nullptr);
|
||
EXPECT_EQ(*p, 8);
|
||
|
||
auto* p2 = dl::Find::FirstYes(v, [](int x) { return x > 100; });
|
||
EXPECT_EQ(p2, nullptr);
|
||
}
|
||
|
||
//------------------------------Select------------------------------
|
||
TEST(SelectTest, MaxMin)
|
||
{
|
||
std::vector<int> v = { 3, 7, 2, 9, 5 };
|
||
EXPECT_EQ(dl::Select::Max(v), 9);
|
||
EXPECT_EQ(dl::Select::Min(v), 2);
|
||
}
|
||
|
||
TEST(SelectTest, MaxMinFunc)
|
||
{
|
||
std::vector<int> v = { 1, -2, 3, -4 };
|
||
EXPECT_EQ(dl::Select::Max(v, [](int x) { return x * x; }), 16);
|
||
EXPECT_EQ(dl::Select::Min(v, [](int x) { return x * x; }), 1);
|
||
}
|
||
|
||
TEST(SelectTest, MaxRef)
|
||
{
|
||
std::vector<std::string> v = { "a", "hello", "abc" };
|
||
auto& ref = dl::Select::MaxRef(v, [](std::string& s) { return s.size(); });
|
||
EXPECT_EQ(ref, "hello");
|
||
}
|
||
|
||
TEST(SelectTest, CreateIfEmpty)
|
||
{
|
||
std::vector<int> v = { 1, 2 };
|
||
auto& ref = dl::Select::CreateIfEmpty(v, 4);
|
||
ref = 99;
|
||
ASSERT_EQ(v.size(), 5u);
|
||
EXPECT_EQ(v[4], 99);
|
||
EXPECT_EQ(v[0], 1); // 旧元素不变
|
||
EXPECT_EQ(v[1], 2);
|
||
}
|
||
|
||
//------------------------------NTree------------------------------
|
||
TEST(NTreeTest, AddAndGet)
|
||
{
|
||
dl::NTree<int> tree;
|
||
auto* root = tree.AddRoot(1);
|
||
ASSERT_NE(root, nullptr);
|
||
EXPECT_EQ(root->GetValue(), 1);
|
||
|
||
auto* n2 = tree.Add(2, root);
|
||
auto* n3 = tree.Add(3, root);
|
||
ASSERT_NE(n2, nullptr);
|
||
ASSERT_NE(n3, nullptr);
|
||
|
||
EXPECT_EQ(tree.GetSize(), 3u);
|
||
EXPECT_EQ(tree.GetRoot(), root);
|
||
EXPECT_EQ(tree.Get(2), n2);
|
||
EXPECT_EQ(tree.Get(99), nullptr);
|
||
|
||
ASSERT_EQ(root->GetChild().size(), 2u);
|
||
EXPECT_EQ(root->GetChild()[0], n2);
|
||
EXPECT_EQ(root->GetChild()[1], n3);
|
||
EXPECT_EQ(n2->GetParent(), root);
|
||
}
|
||
|
||
TEST(NTreeTest, PushBack)
|
||
{
|
||
dl::NTree<int> tree;
|
||
auto* r = tree.PushBack(1);
|
||
auto* a = tree.PushBack(2);
|
||
auto* b = tree.PushBack(3);
|
||
EXPECT_EQ(tree.GetSize(), 3u);
|
||
EXPECT_EQ(a->GetParent(), r);
|
||
EXPECT_EQ(b->GetParent(), r);
|
||
}
|
||
|
||
TEST(NTreeTest, Del)
|
||
{
|
||
dl::NTree<int> tree;
|
||
auto* root = tree.AddRoot(1);
|
||
auto* n2 = tree.Add(2, root);
|
||
auto* n3 = tree.Add(3, n2);
|
||
|
||
EXPECT_TRUE(tree.Del(n2));
|
||
EXPECT_EQ(tree.GetSize(), 2u);
|
||
EXPECT_EQ(tree.Get(2), nullptr);
|
||
EXPECT_EQ(n3->GetParent(), root); // 子节点上移到 root
|
||
}
|
||
|
||
TEST(NTreeTest, ForEach)
|
||
{
|
||
dl::NTree<int> tree;
|
||
auto* root = tree.AddRoot(1);
|
||
tree.Add(2, root);
|
||
tree.Add(3, root);
|
||
|
||
std::vector<int> order;
|
||
tree.ForEach([&](int v) { order.push_back(v); });
|
||
ASSERT_EQ(order.size(), 3u);
|
||
EXPECT_EQ(order[0], 1); // 根先遍历
|
||
EXPECT_EQ(order[1], 2);
|
||
EXPECT_EQ(order[2], 3);
|
||
}
|
||
|
||
//------------------------------Accumulate------------------------------
|
||
TEST(AccumulateTest, Add)
|
||
{
|
||
std::vector<int> v = { 1, 2, 3, 4 };
|
||
EXPECT_EQ(dl::Accumulate::Add(v), 10);
|
||
EXPECT_EQ(dl::Accumulate::Add(std::vector<int>{}), 0);
|
||
}
|
||
|
||
TEST(AccumulateTest, Mul)
|
||
{
|
||
std::vector<int> v = { 1, 2, 3, 4 };
|
||
EXPECT_EQ(dl::Accumulate::Mul(v), 24);
|
||
EXPECT_EQ(dl::Accumulate::Mul(std::vector<int>{}), 0);
|
||
}
|
||
|
||
//------------------------------Vector2------------------------------
|
||
TEST(Vector2Test, Basic)
|
||
{
|
||
dl::Vector2<int> v({ 3, 2 }); // 宽3,高2
|
||
EXPECT_EQ(v.GetWidth(), 3u);
|
||
EXPECT_EQ(v.GetHeight(), 2u);
|
||
EXPECT_EQ(v.GetSizeMul(), 6u);
|
||
|
||
v.Set(0, 0, 1);
|
||
v.Set(0, 1, 2);
|
||
v.Set(0, 2, 3);
|
||
v.Set(1, 0, 4);
|
||
v.Set(1, 1, 5);
|
||
v.Set(1, 2, 6);
|
||
|
||
EXPECT_EQ(v.Get(0, 0), 1);
|
||
EXPECT_EQ(v.Get(1, 2), 6);
|
||
|
||
// 按行访问
|
||
auto row = v[0];
|
||
EXPECT_EQ(row[0], 1);
|
||
EXPECT_EQ(row[2], 3);
|
||
}
|
||
|
||
TEST(Vector2Test, Fill)
|
||
{
|
||
dl::Vector2<int> v({ 2, 2 });
|
||
v.Fill(7);
|
||
EXPECT_EQ(v.Get(0, 0), 7);
|
||
EXPECT_EQ(v.Get(1, 1), 7);
|
||
}
|
||
|
||
TEST(Vector2Test, RotateRightAngle1)
|
||
{
|
||
dl::Vector2<int> v({ 2, 2 });
|
||
v.Set(0, 0, 1);
|
||
v.Set(0, 1, 2);
|
||
v.Set(1, 0, 3);
|
||
v.Set(1, 1, 4);
|
||
|
||
auto r = dl::Vector2<int>::RotateRightAngle1(v);
|
||
// 原 1 2 顺时针旋转90度 3 1
|
||
// 3 4 4 2
|
||
EXPECT_EQ(r.Get(0, 0), 3);
|
||
EXPECT_EQ(r.Get(0, 1), 1);
|
||
EXPECT_EQ(r.Get(1, 0), 4);
|
||
EXPECT_EQ(r.Get(1, 1), 2);
|
||
}
|
||
|
||
//------------------------------Every------------------------------
|
||
TEST(EveryTest, AddSubMul)
|
||
{
|
||
std::vector<int> v = { 1, 2, 3 };
|
||
dl::Every::Add(v, 10);
|
||
EXPECT_EQ(v[0], 11);
|
||
EXPECT_EQ(v[2], 13);
|
||
|
||
dl::Every::Sub(v, 1);
|
||
EXPECT_EQ(v[0], 10);
|
||
|
||
dl::Every::Mul(v, 2);
|
||
EXPECT_EQ(v[0], 20);
|
||
}
|
||
|
||
TEST(EveryTest, RoundFloorCeil)
|
||
{
|
||
std::vector<float> v = { 1.4f, 1.5f, -1.5f };
|
||
dl::Every::Round(v);
|
||
EXPECT_FLOAT_EQ(v[0], 1.0f);
|
||
EXPECT_FLOAT_EQ(v[1], 2.0f);
|
||
EXPECT_FLOAT_EQ(v[2], -2.0f);
|
||
|
||
std::vector<float> f = { 1.7f, -1.2f };
|
||
dl::Every::Floor(f);
|
||
EXPECT_FLOAT_EQ(f[0], 1.0f);
|
||
EXPECT_FLOAT_EQ(f[1], -2.0f);
|
||
|
||
std::vector<float> c = { 1.2f, -1.7f };
|
||
dl::Every::Ceil(c);
|
||
EXPECT_FLOAT_EQ(c[0], 2.0f);
|
||
EXPECT_FLOAT_EQ(c[1], -1.0f);
|
||
}
|
||
|
||
TEST(EveryTest, ClampSaturate)
|
||
{
|
||
std::vector<float> v = { -1.0f, 0.5f, 2.0f };
|
||
dl::Every::Clamp(v, 0.0f, 1.0f);
|
||
EXPECT_FLOAT_EQ(v[0], 0.0f);
|
||
EXPECT_FLOAT_EQ(v[1], 0.5f);
|
||
EXPECT_FLOAT_EQ(v[2], 1.0f);
|
||
|
||
std::vector<float> s = { -1.0f, 0.5f, 2.0f };
|
||
dl::Every::Saturate(s);
|
||
EXPECT_FLOAT_EQ(s[0], 0.0f);
|
||
EXPECT_FLOAT_EQ(s[2], 1.0f);
|
||
}
|
||
|
||
TEST(EveryTest, EqualZero)
|
||
{
|
||
std::vector<int> v = { 5, 5, 5 };
|
||
EXPECT_TRUE(dl::Every::Equal(v, 5));
|
||
EXPECT_TRUE(dl::Every::NotEqual(v, 3));
|
||
|
||
std::vector<int> z = { 0, 0, 0 };
|
||
EXPECT_TRUE(dl::Every::Zero(z));
|
||
}
|
||
|
||
TEST(EveryTest, EraseReplace)
|
||
{
|
||
std::vector<int> v = { 1, 2, 3, 2, 4 };
|
||
dl::Every::Erase(v, 2);
|
||
ASSERT_EQ(v.size(), 3u);
|
||
EXPECT_EQ(v[0], 1);
|
||
EXPECT_EQ(v[1], 3);
|
||
EXPECT_EQ(v[2], 4);
|
||
|
||
std::vector<int> r = { 1, 2, 3 };
|
||
dl::Every::Replace(r, 2, 99);
|
||
EXPECT_EQ(r[1], 99);
|
||
}
|
||
|
||
//------------------------------Erase------------------------------
|
||
TEST(EraseTest, HeadFromLast)
|
||
{
|
||
std::string s = "data/image/cat.png";
|
||
EXPECT_TRUE(dl::Erase::HeadFromLast(s, '/'));
|
||
EXPECT_EQ(s, "cat.png");
|
||
}
|
||
|
||
TEST(EraseTest, TailFromLast)
|
||
{
|
||
std::string s = "data/image/cat.png";
|
||
EXPECT_TRUE(dl::Erase::TailFromLast(s, '.'));
|
||
EXPECT_EQ(s, "data/image/cat.");
|
||
}
|
||
|
||
TEST(EraseTest, TailFromFirst)
|
||
{
|
||
std::string s = "data/image/cat.png";
|
||
EXPECT_TRUE(dl::Erase::TailFromFirst(s, '.'));
|
||
EXPECT_EQ(s, "data/image/cat");
|
||
}
|
||
|
||
TEST(EraseTest, HeadSubAllSub)
|
||
{
|
||
std::string s = "hello world hello";
|
||
EXPECT_TRUE(dl::Erase::HeadSub(s, std::string("hello ")));
|
||
EXPECT_EQ(s, "world hello");
|
||
|
||
std::string s2 = "aXbXcX";
|
||
EXPECT_EQ(dl::Erase::AllSub(s2, std::string("X")), 3u);
|
||
EXPECT_EQ(s2, "abc");
|
||
}
|
||
|
||
TEST(EraseTest, First)
|
||
{
|
||
std::vector<int> v = { 1, 2, 3, 2 };
|
||
EXPECT_TRUE(dl::Erase::First(v, 2));
|
||
ASSERT_EQ(v.size(), 3u);
|
||
EXPECT_EQ(v[0], 1);
|
||
EXPECT_EQ(v[1], 3);
|
||
EXPECT_EQ(v[2], 2);
|
||
}
|
||
|
||
//------------------------------Any------------------------------
|
||
TEST(AnyTest, Equal)
|
||
{
|
||
std::vector<int> v = { 1, 2, 3 };
|
||
EXPECT_TRUE(dl::Any::Equal(v, 2));
|
||
EXPECT_FALSE(dl::Any::Equal(v, 5));
|
||
}
|
||
|
||
TEST(AnyTest, Zero)
|
||
{
|
||
std::vector<int> v = { 1, 0, 3 };
|
||
EXPECT_TRUE(dl::Any::Zero(v));
|
||
|
||
std::vector<int> v2 = { 1, 2, 3 };
|
||
EXPECT_FALSE(dl::Any::Zero(v2));
|
||
}
|
||
|
||
TEST(AnyTest, Yes)
|
||
{
|
||
std::vector<int> v = { 1, 3, 5, 8 };
|
||
EXPECT_TRUE(dl::Any::Yes(v, [](int x) { return x % 2 == 0; }));
|
||
EXPECT_FALSE(dl::Any::Yes(v, [](int x) { return x > 100; }));
|
||
}
|
||
|
||
TEST(AnyTest, Less)
|
||
{
|
||
std::vector<int> v = { 5, 10, 15 };
|
||
EXPECT_TRUE(dl::Any::Less(v, 10));
|
||
EXPECT_FALSE(dl::Any::Less(v, 5));
|
||
}
|