Files
dl/project/dl_unit_test/test_base.cpp
T
2026-09-16 14:07:40 +08:00

536 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @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));
}