/** * @file test_base.cpp * @brief base 模块单元测试(Array、String) * * * @version 1.0 * @author CodeBuddy * @date 26-09-03 * * @note */ #include #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 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 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 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 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 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 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 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 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 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 tree; auto* root = tree.AddRoot(1); tree.Add(2, root); tree.Add(3, root); std::vector 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 v = { 1, 2, 3, 4 }; EXPECT_EQ(dl::Accumulate::Add(v), 10); EXPECT_EQ(dl::Accumulate::Add(std::vector{}), 0); } TEST(AccumulateTest, Mul) { std::vector v = { 1, 2, 3, 4 }; EXPECT_EQ(dl::Accumulate::Mul(v), 24); EXPECT_EQ(dl::Accumulate::Mul(std::vector{}), 0); } //------------------------------Vector2------------------------------ TEST(Vector2Test, Basic) { dl::Vector2 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 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 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::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 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 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 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 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 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 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 v = { 5, 5, 5 }; EXPECT_TRUE(dl::Every::Equal(v, 5)); EXPECT_TRUE(dl::Every::NotEqual(v, 3)); std::vector z = { 0, 0, 0 }; EXPECT_TRUE(dl::Every::Zero(z)); } TEST(EveryTest, EraseReplace) { std::vector 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 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 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 v = { 1, 2, 3 }; EXPECT_TRUE(dl::Any::Equal(v, 2)); EXPECT_FALSE(dl::Any::Equal(v, 5)); } TEST(AnyTest, Zero) { std::vector v = { 1, 0, 3 }; EXPECT_TRUE(dl::Any::Zero(v)); std::vector v2 = { 1, 2, 3 }; EXPECT_FALSE(dl::Any::Zero(v2)); } TEST(AnyTest, Yes) { std::vector 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 v = { 5, 10, 15 }; EXPECT_TRUE(dl::Any::Less(v, 10)); EXPECT_FALSE(dl::Any::Less(v, 5)); }