初始化内容

This commit is contained in:
2026-09-16 14:07:40 +08:00
parent 6934b390bf
commit 4f643c1e7c
18350 changed files with 6088489 additions and 305 deletions
+11
View File
@@ -0,0 +1,11 @@
/log
/*.ilk
/*.pdb
/*.exe
/memory_leak_report.txt
/vld.ini
/temp
/binary
/dl
/Microsoft.DTfW.DHL.manifest
/out
+13
View File
@@ -0,0 +1,13 @@
cmake_minimum_required (VERSION 3.12)
project ("dl_unit_test")
set (PATH_SRC ${PROJECT_SOURCE_DIR})
set (PATH_RES ${PROJECT_SOURCE_DIR}/res)
set (USE_RENDER ON)
set (USE_CRASH_RPT false)
include ("../project.cmake")
# 链接 GoogleTest
target_link_libraries(${PROJECT_NAME} GTest::gtest)
# 链接 OpenXLSX(用于 Language 测试读写 xlsx
target_link_libraries(${PROJECT_NAME} OpenXLSX::OpenXLSX)
+1
View File
@@ -0,0 +1 @@
#include <dl_main.h>
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- $Id -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<noInheritable />
<assemblyIdentity type="win32" name="Microsoft.DTfW.DHL" version="6.11.1.404" processorArchitecture="amd64" />
<file name="dbghelp.dll" />
</assembly>
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,198 @@
{
"__desc": "2d粒子配置",
"__name": "2d粒子配置",
"emitter": {
"__desc": "发射器设置",
"__name": "发射器",
"offset": {
"__desc": "位置偏移",
"__name": "位置偏移",
"type": "array<float, 2>",
"value": [
0.0,
0.0
]
},
"offset1": {
"__desc": "位置偏移1,作为line模式的结束点",
"__name": "位置偏移1,作为line模式的结束点",
"type": "array<float, 2>",
"value": [
0.0,
0.0
]
},
"rate": {
"__desc": "发射速率,每秒多少个",
"__name": "发射速率",
"type": "uint",
"value": 20
},
"shape": {
"__desc": "发射区域类型(point、circle、box、line",
"__name": "发射区域类型",
"type": "string",
"value": "circle"
},
"size": {
"__desc": "区域大小(半径)",
"__name": "区域大小",
"type": "array<float, 2>",
"value": [
100.0,
100.0
]
}
},
"node": {
"__desc": "粒子参数",
"__name": "粒子参数",
"alpha": {
"__desc": "透明度(范围)",
"__name": "透明度(范围)",
"type": "array<float, 2>",
"value": [
1.0,
0.0
]
},
"angle": {
"__desc": "方向角度(范围)",
"__name": "方向角度(范围)",
"type": "array<float, 2>",
"value": [
0.0,
360.0
]
},
"color_beg": {
"__desc": "起始颜色(RGB",
"__name": "起始颜色(RGB",
"type": "array<float, 3>",
"value": [
1.0,
1.0,
1.0
]
},
"color_end": {
"__desc": "结束颜色(RGB",
"__name": "结束颜色(RGB",
"type": "array<float, 3>",
"value": [
1.0,
1.0,
1.0
]
},
"lifetime": {
"__desc": "存活时间(范围)",
"__name": "存活时间(范围)",
"type": "array<float, 2>",
"value": [
1.0,
2.0
]
},
"rotate_angle": {
"__desc": "初始旋转角度(范围)",
"__name": "初始旋转角度(范围)",
"type": "array<float, 2>",
"value": [
0.0,
0.0
]
},
"rotate_speed": {
"__desc": "旋转速度(范围)",
"__name": "旋转速度(范围)",
"type": "array<float, 2>",
"value": [
0.0,
0.0
]
},
"rotate_to_dir": {
"__desc": "旋转至运动方向(启用后,其他旋转控制失效)",
"__name": "旋转至运动方向",
"type": "bool",
"value": false
},
"scale_x_beg": {
"__desc": "起始缩放比例x轴(范围)",
"__name": "起始缩放比例x轴(范围)",
"type": "array<float, 2>",
"value": [
1.0,
1.0
]
},
"scale_x_end": {
"__desc": "结束缩放比例x轴(范围)",
"__name": "结束缩放比例x轴(范围)",
"type": "array<float, 2>",
"value": [
1.0,
1.0
]
},
"scale_y_beg": {
"__desc": "起始缩放比例y轴(范围)",
"__name": "起始缩放比例y轴(范围)",
"type": "array<float, 2>",
"value": [
1.0,
1.0
]
},
"scale_y_end": {
"__desc": "结束缩放比例y轴(范围)",
"__name": "结束缩放比例y轴(范围)",
"type": "array<float, 2>",
"value": [
1.0,
1.0
]
},
"speed": {
"__desc": "速度(范围)",
"__name": "速度(范围)",
"type": "array<float, 2>",
"value": [
100.0,
200.0
]
}
},
"system": {
"__desc": "主要参数",
"__name": "主要参数",
"delay": {
"__desc": "启动延时",
"__name": "启动延时",
"type": "float",
"value": 0.0
},
"duration": {
"__desc": "持续时间(单位秒)",
"__name": "持续时间",
"type": "float",
"value": 0.0
},
"gravity": {
"__desc": "重力方向和大小",
"__name": "重力方向和大小",
"type": "array<float, 2>",
"value": [
0.0,
0.0
]
},
"max_num": {
"__desc": "粒子数量上限",
"__name": "粒子数量上限",
"type": "uint",
"value": 1024
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,9 @@
( 0.818393886089325, 0.856512069702148, 0.979097247123718); // L00, irradiance, pre-scaled base
( 0.376601099967957, 0.388774126768112, 0.445391833782196); // L1-1, irradiance, pre-scaled base
( 0.367425948381424, 0.295479565858841, 0.251522302627563); // L10, irradiance, pre-scaled base
(-0.259449630975723, -0.213349714875221, -0.181993708014488); // L11, irradiance, pre-scaled base
(-0.096955023705959, -0.073478810489178, -0.059210501611233); // L2-2, irradiance, pre-scaled base
( 0.112052068114281, 0.086938507854939, 0.069391325116158); // L2-1, irradiance, pre-scaled base
( 0.005669212900102, 0.005782041233033, 0.003940611612052); // L20, irradiance, pre-scaled base
(-0.137584298849106, -0.123443752527237, -0.111519888043404); // L21, irradiance, pre-scaled base
(-0.029301593080163, -0.024162670597434, -0.029466325417161); // L22, irradiance, pre-scaled base
Binary file not shown.
@@ -0,0 +1,122 @@
Visual Leak Detector Version 2.5.1 installed.
Outputting the report to the debugger and to D:\dl\out\build\x64-debug\project\dl_unit_test\bin\memory_leak_report.txt
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 15582 at 0x00000000D918C5F0: 64 bytes ----------
Leak Hash: 0x6D8807E3, Count: 1, Total 64 bytes
Call Stack (TID 43668):
Data:
F0 C5 18 D9 58 01 00 00 F0 C5 18 D9 58 01 00 00 ....X... ....X...
F0 C5 18 D9 58 01 00 00 01 01 CD CD CD CD CD CD ....X... ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
---------- Block 15579 at 0x00000000D95AF540: 40 bytes ----------
Leak Hash: 0x36765E5B, Count: 1, Total 40 bytes
Call Stack (TID 43668):
ntdll.dll!RtlAllocateHeap()
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\heap\new_scalar.cpp (36): dl_unit_test.exe!operator new() + 0xA bytes
D:\dl\third\googletest\googletest\src\gtest-port.cc (413): dl_unit_test.exe!testing::internal::Mutex::ThreadSafeLazyInit() + 0xA bytes
D:\dl\third\googletest\googletest\src\gtest-port.cc (342): dl_unit_test.exe!testing::internal::Mutex::lock()
D:\dl\third\googletest\googletest\include\gtest\internal\gtest-port.h (1478): dl_unit_test.exe!testing::internal::GTestMutexLock::GTestMutexLock() + 0x29 bytes
D:\dl\third\googletest\googletest\src\gtest-port.cc (552): dl_unit_test.exe!testing::internal::ThreadLocalRegistryImpl::OnThreadLocalDestroyed() + 0x11 bytes
D:\dl\third\googletest\googletest\src\gtest-port.cc (691): dl_unit_test.exe!testing::internal::ThreadLocalRegistry::OnThreadLocalDestroyed() + 0xA bytes
D:\dl\third\googletest\googletest\include\gtest\internal\gtest-port.h (1612): dl_unit_test.exe!testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo,std::allocator<testing::internal::TraceInfo> > >::~ThreadLocal<std::vector<testing::internal::TraceInfo,std::allocator<testing::internal::TraceInfo> > >() + 0x23 bytes
D:\dl\third\googletest\googletest\src\gtest.cc (5740): dl_unit_test.exe!testing::internal::UnitTestImpl::~UnitTestImpl() + 0x13 bytes
dl_unit_test.exe!testing::internal::UnitTestImpl::`scalar deleting destructor'() + 0x18 bytes
D:\dl\third\googletest\googletest\src\gtest.cc (5685): dl_unit_test.exe!testing::UnitTest::~UnitTest() + 0x4D bytes
dl_unit_test.exe!`testing::UnitTest::GetInstance'::`2'::`dynamic atexit destructor for 'instance''() + 0x12 bytes
minkernel\crts\ucrt\src\appcrt\startup\onexit.cpp (206): dl_unit_test.exe!<lambda_d121dba8a4adeaf3a9819e48611155df>::operator()()
VCCRT\vcruntime\inc\internal_shared.h (204): dl_unit_test.exe!__crt_seh_guarded_call<int>::operator()<<lambda_6a47f4c8fd0152770a780fc1d70204eb>,<lambda_d121dba8a4adeaf3a9819e48611155df> &,<lambda_6aaa2265f5b6a89667e7d7630012e97a> >() + 0xA bytes
minkernel\crts\ucrt\inc\corecrt_internal.h (983): dl_unit_test.exe!__acrt_lock_and_call<<lambda_d121dba8a4adeaf3a9819e48611155df> >() + 0x41 bytes
minkernel\crts\ucrt\src\appcrt\startup\onexit.cpp (231): dl_unit_test.exe!_execute_onexit_table()
minkernel\crts\ucrt\src\appcrt\startup\exit.cpp (225): dl_unit_test.exe!<lambda_6e4b09c48022b2350581041d5f6b0c4c>::operator()()
VCCRT\vcruntime\inc\internal_shared.h (224): dl_unit_test.exe!__crt_seh_guarded_call<void>::operator()<<lambda_d80eeec6fff315bfe5c115232f3240e3>,<lambda_6e4b09c48022b2350581041d5f6b0c4c> &,<lambda_2358e3775559c9db80273638284d5e45> >() + 0xA bytes
minkernel\crts\ucrt\inc\corecrt_internal.h (983): dl_unit_test.exe!__acrt_lock_and_call<<lambda_6e4b09c48022b2350581041d5f6b0c4c> >() + 0x41 bytes
minkernel\crts\ucrt\src\appcrt\startup\exit.cpp (259): dl_unit_test.exe!common_exit()
minkernel\crts\ucrt\src\appcrt\startup\exit.cpp (302): dl_unit_test.exe!exit()
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (295): dl_unit_test.exe!__scrt_common_main_seh() + 0x9 bytes
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (331): dl_unit_test.exe!__scrt_common_main()
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp (17): dl_unit_test.exe!mainCRTStartup()
KERNEL32.DLL!BaseThreadInitThunk() + 0x14 bytes
ntdll.dll!RtlUserThreadStart() + 0x21 bytes
Data:
FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 ........ ........
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
D0 07 00 02 00 00 00 00 ........ ........
---------- Block 15581 at 0x00000000D95D2B50: 16 bytes ----------
Leak Hash: 0x40E41FAB, Count: 1, Total 16 bytes
Call Stack (TID 43668):
ntdll.dll!RtlAllocateHeap()
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\heap\new_scalar.cpp (36): dl_unit_test.exe!operator new() + 0xA bytes
D:\vs_2026\VC\Tools\MSVC\14.51.36231\include\xmemory (137): dl_unit_test.exe!std::_Default_allocate_traits::_Allocate()
D:\vs_2026\VC\Tools\MSVC\14.51.36231\include\xmemory (258): dl_unit_test.exe!std::_Allocate<16,std::_Default_allocate_traits>()
D:\vs_2026\VC\Tools\MSVC\14.51.36231\include\xmemory (995): dl_unit_test.exe!std::allocator<std::_Container_proxy>::allocate()
D:\vs_2026\VC\Tools\MSVC\14.51.36231\include\xmemory (1495): dl_unit_test.exe!std::_Container_proxy_ptr12<std::allocator<std::_Container_proxy> >::_Container_proxy_ptr12<std::allocator<std::_Container_proxy> >() + 0xF bytes
D:\vs_2026\VC\Tools\MSVC\14.51.36231\include\xtree (1967): dl_unit_test.exe!std::_Tree<std::_Tmap_traits<unsigned long,std::map<testing::internal::ThreadLocalBase const *,std::shared_ptr<testing::internal::ThreadLocalValueHolderBase>,std::less<testing::internal::ThreadLocalBase const *>,std::allocator<std::pair<testing::internal:() + 0x14 bytes
D:\vs_2026\VC\Tools\MSVC\14.51.36231\include\xtree (916): dl_unit_test.exe!std::_Tree<std::_Tmap_traits<unsigned long,std::map<testing::internal::ThreadLocalBase const *,std::shared_ptr<testing::internal::ThreadLocalValueHolderBase>,std::less<testing::internal::ThreadLocalBase const *>,std::allocator<std::pair<testing::internal:() + 0xA bytes
D:\vs_2026\VC\Tools\MSVC\14.51.36231\include\map (106): dl_unit_test.exe!std::map<unsigned long,std::map<testing::internal::ThreadLocalBase const *,std::shared_ptr<testing::internal::ThreadLocalValueHolderBase>,std::less<testing::internal::ThreadLocalBase const *>,std::allocator<std::pair<testing::internal::ThreadLocalBase con() + 0x19 bytes
D:\dl\third\googletest\googletest\src\gtest-port.cc (669): dl_unit_test.exe!testing::internal::ThreadLocalRegistryImpl::GetThreadLocalsMapLocked() + 0x54 bytes
D:\dl\third\googletest\googletest\src\gtest-port.cc (553): dl_unit_test.exe!testing::internal::ThreadLocalRegistryImpl::OnThreadLocalDestroyed() + 0x5 bytes
D:\dl\third\googletest\googletest\src\gtest-port.cc (691): dl_unit_test.exe!testing::internal::ThreadLocalRegistry::OnThreadLocalDestroyed() + 0xA bytes
D:\dl\third\googletest\googletest\include\gtest\internal\gtest-port.h (1612): dl_unit_test.exe!testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo,std::allocator<testing::internal::TraceInfo> > >::~ThreadLocal<std::vector<testing::internal::TraceInfo,std::allocator<testing::internal::TraceInfo> > >() + 0x23 bytes
D:\dl\third\googletest\googletest\src\gtest.cc (5740): dl_unit_test.exe!testing::internal::UnitTestImpl::~UnitTestImpl() + 0x13 bytes
dl_unit_test.exe!testing::internal::UnitTestImpl::`scalar deleting destructor'() + 0x18 bytes
D:\dl\third\googletest\googletest\src\gtest.cc (5685): dl_unit_test.exe!testing::UnitTest::~UnitTest() + 0x4D bytes
dl_unit_test.exe!`testing::UnitTest::GetInstance'::`2'::`dynamic atexit destructor for 'instance''() + 0x12 bytes
minkernel\crts\ucrt\src\appcrt\startup\onexit.cpp (206): dl_unit_test.exe!<lambda_d121dba8a4adeaf3a9819e48611155df>::operator()()
VCCRT\vcruntime\inc\internal_shared.h (204): dl_unit_test.exe!__crt_seh_guarded_call<int>::operator()<<lambda_6a47f4c8fd0152770a780fc1d70204eb>,<lambda_d121dba8a4adeaf3a9819e48611155df> &,<lambda_6aaa2265f5b6a89667e7d7630012e97a> >() + 0xA bytes
minkernel\crts\ucrt\inc\corecrt_internal.h (983): dl_unit_test.exe!__acrt_lock_and_call<<lambda_d121dba8a4adeaf3a9819e48611155df> >() + 0x41 bytes
minkernel\crts\ucrt\src\appcrt\startup\onexit.cpp (231): dl_unit_test.exe!_execute_onexit_table()
minkernel\crts\ucrt\src\appcrt\startup\exit.cpp (225): dl_unit_test.exe!<lambda_6e4b09c48022b2350581041d5f6b0c4c>::operator()()
VCCRT\vcruntime\inc\internal_shared.h (224): dl_unit_test.exe!__crt_seh_guarded_call<void>::operator()<<lambda_d80eeec6fff315bfe5c115232f3240e3>,<lambda_6e4b09c48022b2350581041d5f6b0c4c> &,<lambda_2358e3775559c9db80273638284d5e45> >() + 0xA bytes
minkernel\crts\ucrt\inc\corecrt_internal.h (983): dl_unit_test.exe!__acrt_lock_and_call<<lambda_6e4b09c48022b2350581041d5f6b0c4c> >() + 0x41 bytes
minkernel\crts\ucrt\src\appcrt\startup\exit.cpp (259): dl_unit_test.exe!common_exit()
minkernel\crts\ucrt\src\appcrt\startup\exit.cpp (302): dl_unit_test.exe!exit()
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (295): dl_unit_test.exe!__scrt_common_main_seh() + 0x9 bytes
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (331): dl_unit_test.exe!__scrt_common_main()
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp (17): dl_unit_test.exe!mainCRTStartup()
KERNEL32.DLL!BaseThreadInitThunk() + 0x14 bytes
ntdll.dll!RtlUserThreadStart() + 0x21 bytes
Data:
10 55 5E D9 58 01 00 00 00 00 00 00 00 00 00 00 .U^.X... ........
---------- Block 15580 at 0x00000000D95E5510: 24 bytes ----------
Leak Hash: 0x976A4DFF, Count: 1, Total 24 bytes
Call Stack (TID 43668):
ntdll.dll!RtlAllocateHeap()
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\heap\new_scalar.cpp (36): dl_unit_test.exe!operator new() + 0xA bytes
D:\dl\third\googletest\googletest\src\gtest-port.cc (669): dl_unit_test.exe!testing::internal::ThreadLocalRegistryImpl::GetThreadLocalsMapLocked() + 0x3D bytes
D:\dl\third\googletest\googletest\src\gtest-port.cc (553): dl_unit_test.exe!testing::internal::ThreadLocalRegistryImpl::OnThreadLocalDestroyed() + 0x5 bytes
D:\dl\third\googletest\googletest\src\gtest-port.cc (691): dl_unit_test.exe!testing::internal::ThreadLocalRegistry::OnThreadLocalDestroyed() + 0xA bytes
D:\dl\third\googletest\googletest\include\gtest\internal\gtest-port.h (1612): dl_unit_test.exe!testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo,std::allocator<testing::internal::TraceInfo> > >::~ThreadLocal<std::vector<testing::internal::TraceInfo,std::allocator<testing::internal::TraceInfo> > >() + 0x23 bytes
D:\dl\third\googletest\googletest\src\gtest.cc (5740): dl_unit_test.exe!testing::internal::UnitTestImpl::~UnitTestImpl() + 0x13 bytes
dl_unit_test.exe!testing::internal::UnitTestImpl::`scalar deleting destructor'() + 0x18 bytes
D:\dl\third\googletest\googletest\src\gtest.cc (5685): dl_unit_test.exe!testing::UnitTest::~UnitTest() + 0x4D bytes
dl_unit_test.exe!`testing::UnitTest::GetInstance'::`2'::`dynamic atexit destructor for 'instance''() + 0x12 bytes
minkernel\crts\ucrt\src\appcrt\startup\onexit.cpp (206): dl_unit_test.exe!<lambda_d121dba8a4adeaf3a9819e48611155df>::operator()()
VCCRT\vcruntime\inc\internal_shared.h (204): dl_unit_test.exe!__crt_seh_guarded_call<int>::operator()<<lambda_6a47f4c8fd0152770a780fc1d70204eb>,<lambda_d121dba8a4adeaf3a9819e48611155df> &,<lambda_6aaa2265f5b6a89667e7d7630012e97a> >() + 0xA bytes
minkernel\crts\ucrt\inc\corecrt_internal.h (983): dl_unit_test.exe!__acrt_lock_and_call<<lambda_d121dba8a4adeaf3a9819e48611155df> >() + 0x41 bytes
minkernel\crts\ucrt\src\appcrt\startup\onexit.cpp (231): dl_unit_test.exe!_execute_onexit_table()
minkernel\crts\ucrt\src\appcrt\startup\exit.cpp (225): dl_unit_test.exe!<lambda_6e4b09c48022b2350581041d5f6b0c4c>::operator()()
VCCRT\vcruntime\inc\internal_shared.h (224): dl_unit_test.exe!__crt_seh_guarded_call<void>::operator()<<lambda_d80eeec6fff315bfe5c115232f3240e3>,<lambda_6e4b09c48022b2350581041d5f6b0c4c> &,<lambda_2358e3775559c9db80273638284d5e45> >() + 0xA bytes
minkernel\crts\ucrt\inc\corecrt_internal.h (983): dl_unit_test.exe!__acrt_lock_and_call<<lambda_6e4b09c48022b2350581041d5f6b0c4c> >() + 0x41 bytes
minkernel\crts\ucrt\src\appcrt\startup\exit.cpp (259): dl_unit_test.exe!common_exit()
minkernel\crts\ucrt\src\appcrt\startup\exit.cpp (302): dl_unit_test.exe!exit()
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (295): dl_unit_test.exe!__scrt_common_main_seh() + 0x9 bytes
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (331): dl_unit_test.exe!__scrt_common_main()
D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp (17): dl_unit_test.exe!mainCRTStartup()
KERNEL32.DLL!BaseThreadInitThunk() + 0x14 bytes
ntdll.dll!RtlUserThreadStart() + 0x21 bytes
Data:
50 2B 5D D9 58 01 00 00 F0 C5 18 D9 58 01 00 00 P+].X... ....X...
00 00 00 00 00 00 00 00 ........ ........
Visual Leak Detector detected 4 memory leaks (436 bytes).
Largest number used: 15898751 bytes.
Total allocations: 18236619 bytes.
Visual Leak Detector is now exiting.
+4
View File
@@ -0,0 +1,4 @@
; dl_unit_test 单元测试专用 VLD 配置
; 关闭 VLDgtest 单例在进程退出 atexit 析构时会产生 VLD 误报泄漏(官方 issue #2255
[Options]
VLD = off
+535
View File
@@ -0,0 +1,535 @@
/**
* @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));
}
+83
View File
@@ -0,0 +1,83 @@
/**
* @file test_crypto.cpp
* @brief memory 模块单元测试(Crypto 加密哈希)
*
*
* @version 1.0
* @author CodeBuddy
* @date 26-09-03
*
* @note
*/
#include <gtest/gtest.h>
#include "memory/dl_crypto.h"
#include "base/dl_string.h"
TEST(CryptoTest, HashMd5)
{
std::string str = "abc";
dl::Buffer hash = dl::Crypto::HashMd5(dl::CreateBufferView(str));
EXPECT_EQ(dl::to_string_hex(dl::CreateBufferView(hash)), "900150983cd24fb0d6963f7d28e17f72");
}
TEST(CryptoTest, HashSha256)
{
std::string str = "abc";
dl::Buffer hash = dl::Crypto::HashSha256(dl::CreateBufferView(str));
EXPECT_EQ(dl::to_string_hex(dl::CreateBufferView(hash)),
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
}
TEST(CryptoTest, HashSha512)
{
std::string str = "abc";
dl::Buffer hash = dl::Crypto::HashSha512(dl::CreateBufferView(str));
// sha512 结果固定长度 64 字节
EXPECT_EQ(hash.size(), 64u);
}
TEST(CryptoTest, HashCrc32)
{
std::string str = "abc";
uint32_t crc = dl::Crypto::HashCrc32(dl::CreateBufferView(str));
EXPECT_NE(crc, 0u);
// 同一数据结果一致
EXPECT_EQ(crc, dl::Crypto::HashCrc32(dl::CreateBufferView(str)));
}
TEST(CryptoTest, Base64)
{
std::string str = "hello world";
std::string enc = dl::Crypto::EncodeBase64(dl::CreateBufferView(str));
EXPECT_EQ(enc, "aGVsbG8gd29ybGQ=");
dl::Buffer dec;
EXPECT_TRUE(dl::Crypto::DecodeBase64(enc, dec));
EXPECT_EQ(dl::to_string(dec), str);
}
TEST(CryptoTest, Xor)
{
std::string str = "hello dl";
dl::Buffer buf = dl::CreateBuffer(dl::CreateBufferView(str));
dl::BufferView view = dl::CreateBufferView(buf);
dl::Crypto::EncryptXor(view);
EXPECT_NE(dl::to_string(view), str); // 加密后应不同
dl::Crypto::DecryptXor(view);
EXPECT_EQ(dl::to_string(view), str); // 解密后还原
}
TEST(CryptoTest, Aes256)
{
std::string str = "hello dl aes256";
dl::Crypto::Aes256Key key = dl::Crypto::GenerateKeyAes256();
dl::Buffer enc = dl::Crypto::EncryptAes256(dl::CreateBufferView(str), key);
EXPECT_FALSE(enc.empty());
dl::Buffer dec = dl::Crypto::DecryptAes256(enc, key);
EXPECT_EQ(dl::to_string(dec), str);
}
+191
View File
@@ -0,0 +1,191 @@
/**
* @file test_io.cpp
* @brief io 模块单元测试(Json
*
*
* @version 1.0
* @author CodeBuddy
* @date 26-09-03
*
* @note
*/
#include <gtest/gtest.h>
#include "io/dl_json.h"
#include "io/dl_file.h"
#include "memory/dl_code_cvt.h"
#include "render/dl_factory.h"
TEST(JsonTest, ParseArray)
{
auto j = dl::Json::ParseString("[1,2,3]");
ASSERT_TRUE(j.is_array());
ASSERT_EQ(j.size(), 3u);
EXPECT_EQ(j[0], 1);
EXPECT_EQ(j[1], 2);
EXPECT_EQ(j[2], 3);
}
TEST(JsonTest, ParseObject)
{
auto j = dl::Json::ParseString(R"({"a": 123, "b": "hello"})");
ASSERT_TRUE(j.is_object());
EXPECT_EQ(j["a"], 123);
EXPECT_EQ(j["b"], "hello");
}
TEST(JsonTest, ParseNested)
{
auto j = dl::Json::ParseString(R"({"outer": {"inner": [true, false, null]}})");
ASSERT_TRUE(j.is_object());
EXPECT_TRUE(j["outer"]["inner"][0]);
EXPECT_FALSE(j["outer"]["inner"][1]);
EXPECT_TRUE(j["outer"]["inner"][2].is_null());
}
TEST(JsonTest, Get)
{
auto j = dl::Json::ParseString(R"({"key": 456})");
int v = 0;
EXPECT_TRUE(dl::Json::Get(j, "key", v));
EXPECT_EQ(v, 456);
}
TEST(JsonTest, GetMissing)
{
auto j = dl::Json::ParseString(R"({"key": 456})");
int v = 0;
EXPECT_FALSE(dl::Json::Get(j, "nokey", v));
}
TEST(JsonTest, ParseInvalid)
{
auto j = dl::Json::ParseString("{invalid json");
EXPECT_TRUE(j.is_null());
}
TEST(JsonTest, SaveFileDump)
{
json j = dl::Json::ParseString(R"({"a": 1, "b": "hello"})");
// Dump 成字符串
std::string dump = dl::Json::Dump(j);
EXPECT_NE(dump.find("\"a\""), std::string::npos);
EXPECT_NE(dump.find("1"), std::string::npos);
// SaveFile + ParseFile 往返
std::string path = dl::g_factory->GetPathTemp() + "dl_json_save_test.json";
ASSERT_TRUE(dl::Json::SaveFile(j, path));
json j2 = dl::Json::ParseFile(path);
EXPECT_EQ(j2["a"], 1);
EXPECT_EQ(j2["b"], "hello");
dl::File::Delete(path);
}
//------------------------------File------------------------------
TEST(FileTest, GetExtension)
{
EXPECT_EQ(dl::File::GetExtension("a/b/c.txt"), "txt");
EXPECT_EQ(dl::File::GetExtension("a/b/c.txt", true), ".txt");
EXPECT_EQ(dl::File::GetExtension("a/b/c"), "");
}
TEST(FileTest, GetFileName)
{
EXPECT_EQ(dl::File::GetFileName("a/b/c.txt"), "c.txt");
EXPECT_EQ(dl::File::GetFileName("a/b/"), "");
}
TEST(FileTest, GetStem)
{
EXPECT_EQ(dl::File::GetStem("a/b/c.txt"), "c");
}
TEST(FileTest, GetFilePath)
{
EXPECT_EQ(dl::File::GetFilePath("a/b/c.txt"), "a/b/");
EXPECT_EQ(dl::File::GetFilePath("a/b/"), "a/b/");
EXPECT_EQ(dl::File::GetFilePath("c.txt"), "");
}
TEST(FileTest, GetFolderName)
{
EXPECT_EQ(dl::File::GetFolderName("a/b/c.txt"), "b");
}
//------------------------------CodeCvt------------------------------
TEST(CodeCvtTest, Utf8Check)
{
EXPECT_EQ(dl::CodeCvt::Utf8::Check("hello"), 1); // ascii
EXPECT_EQ(dl::CodeCvt::Utf8::Check("你好"), 2); // utf-8
}
TEST(CodeCvtTest, Utf8Sub)
{
std::string s = "你好世界"; // 每个字 3 字节,共 12 字节
EXPECT_EQ(dl::CodeCvt::Utf8::Sub(s, 0), 0u);
EXPECT_EQ(dl::CodeCvt::Utf8::Sub(s, 4), 3u); // 截断到"你"3 字节边界)
EXPECT_EQ(dl::CodeCvt::Utf8::Sub(s, 12), 12u); // 足够时返回全部
}
TEST(CodeCvtTest, WideCharRoundtrip)
{
std::string u8 = "hello 你好";
std::wstring wc = dl::CodeCvt::Utf8ToWideChar(u8);
std::string back = dl::CodeCvt::WideCharToUtf8(wc);
EXPECT_EQ(back, u8);
}
TEST(CodeCvtTest, Utf32Roundtrip)
{
std::string u8 = "hello 你好";
std::u32string u32 = dl::CodeCvt::Utf8ToUtf32(u8);
std::string back = dl::CodeCvt::Utf32ToUtf8(u32);
EXPECT_EQ(back, u8);
}
//------------------------------File 文件操作------------------------------
TEST(FileTest, CreateReadDelete)
{
std::string dir = dl::g_factory->GetPathTemp() + "dl_file_test/";
dl::File::Delete(dir, true);
ASSERT_TRUE(dl::File::CreateFolder(dir));
EXPECT_TRUE(dl::File::IsExist(dir));
std::string file = dir + "a.txt";
ASSERT_TRUE(dl::File::SaveString("hello", file));
EXPECT_TRUE(dl::File::IsExist(file));
EXPECT_FALSE(dl::File::IsExist(dir + "none.txt"));
EXPECT_EQ(dl::File::GetString(file), "hello");
EXPECT_TRUE(dl::File::Delete(file));
EXPECT_FALSE(dl::File::IsExist(file));
dl::File::Delete(dir, true);
}
TEST(FileTest, CopyRename)
{
std::string dir = dl::g_factory->GetPathTemp() + "dl_file_test/";
dl::File::Delete(dir, true);
ASSERT_TRUE(dl::File::CreateFolder(dir));
std::string src = dir + "src.txt";
std::string dst = dir + "dst.txt";
ASSERT_TRUE(dl::File::SaveString("data", src));
EXPECT_TRUE(dl::File::Copy(src, dst));
EXPECT_TRUE(dl::File::IsExist(dst));
EXPECT_EQ(dl::File::GetString(dst), "data");
std::string dst2 = dir + "dst2.txt";
EXPECT_TRUE(dl::File::Rename(dst, dst2));
EXPECT_TRUE(dl::File::IsExist(dst2));
EXPECT_FALSE(dl::File::IsExist(dst));
dl::File::Delete(dir, true);
}
+118
View File
@@ -0,0 +1,118 @@
/**
* @file test_main.cpp
* @brief dl 单元测试入口(Main 函数,由 dl_main 调用)
*
*
* @version 1.0
* @author CodeBuddy
* @date 26-09-03
*
* @note 复用 dl_main 的 main 入口,这里提供 Main() 跑 GoogleTest
*/
#include <gtest/gtest.h>
#include "system/dl_engine.h"
#include "system/dl_system.h"
#include "io/dl_log.h"
#include "io/dl_file.h"
#include "render/dl_factory.h"
//! 用 dl 日志打印 gtest 结果(dl 日志会同时写入日志文件,控制台滚动后仍可查完整结果)
class DlLogListener : public ::testing::EmptyTestEventListener
{
//! 用 dl::Output 直接输出(纯字符串,同时写入 stdout/VS/日志文件)
static void Print(std::string_view str)
{
dl::Output(str);
dl::Output("\n");
}
static std::string FileName(const char* path)
{
return dl::File::GetFileName(path);
}
public:
void OnTestProgramStart(const ::testing::UnitTest& unit_test) override
{
Print(fmt::format("[==========] 运行 {} 个测试", unit_test.test_to_run_count()));
}
void OnTestStart(const ::testing::TestInfo& test_info) override
{
Print(fmt::format("[ RUN ] {}.{} ({}:{})",
test_info.test_suite_name(), test_info.name(),
FileName(test_info.file()), test_info.line()));
}
void OnTestPartResult(const ::testing::TestPartResult& result) override
{
if (result.failed())
Print(fmt::format("{}:{}: {}", result.file_name(), result.line_number(), result.message()));
}
void OnTestEnd(const ::testing::TestInfo& test_info) override
{
if (test_info.result()->Passed())
Print(fmt::format("[ OK ] {}.{}", test_info.test_suite_name(), test_info.name()));
else
Print(fmt::format("[ FAILED ] {}.{} ({}:{})",
test_info.test_suite_name(), test_info.name(),
FileName(test_info.file()), test_info.line()));
}
void OnTestProgramEnd(const ::testing::UnitTest& unit_test) override
{
Print(fmt::format("[==========] {} 通过,{} 失败,{} 跳过",
unit_test.successful_test_count(),
unit_test.failed_test_count(),
unit_test.skipped_test_count()));
}
};
int Main()
{
// 测试结果写入 dl 日志文件
dl::g_log->SetLogFile("log/", "unit_test.txt");
// 按正常使用方式初始化引擎(log_err/log_warn 依赖的 g_log 等全局对象在此初始化)
dl::Engine::GetParamRef()._test = false; // 关闭引擎内置测试
dl::Engine::GetParamRef()._showInfo = false; // 关闭引擎信息输出
dl::Engine::Init();
// 初始化 g_factory 路径(正常在 System::Start 时调用 _init_path,测试环境手动设置)
dl::g_factory->SetPath();
dl::File::CreateFolder(dl::g_factory->GetPathTemp());
// 关闭 err 日志的 MessageBox 弹窗(单元测试触发 log_err 不应中断等待点击)
dl::g_log->SetLevelMsgBox(dl::LogSystem::Level::DAMAGE);
// gtest 命令行参数(dl_main_init 已通过 Engine::_init_cmd 保存)
const auto& cmd = dl::Engine::GetCmd();
std::vector<char*> argv;
if (cmd.empty())
{
static std::string exe = "dl_unit_test";
argv.push_back(const_cast<char*>(exe.c_str()));
}
else
{
for (auto& c : cmd)
argv.push_back(const_cast<char*>(c.c_str()));
}
int argc = (int)argv.size();
::testing::InitGoogleTest(&argc, argv.data());
// 用 dl 日志打印测试结果(替换 gtest 默认输出,避免控制台刷屏)
auto& listeners = ::testing::UnitTest::GetInstance()->listeners();
delete listeners.Release(listeners.default_result_printer());
listeners.Append(new DlLogListener);
int ret = RUN_ALL_TESTS();
// 测试完成后暂停,方便观察结果
dl::g_system->Pause();
dl::Engine::Release();
return ret;
}
+237
View File
@@ -0,0 +1,237 @@
/**
* @file test_math.cpp
* @brief math 模块单元测试(Math 命名空间)
*
*
* @version 1.0
* @author CodeBuddy
* @date 26-09-03
*
* @note
*/
#include <gtest/gtest.h>
#include "math/dl_math.h"
#include "math/dl_random.h"
#include "math/dl_texture_pack.h"
TEST(MathTest, Pow)
{
EXPECT_EQ(dl::Math::Pow(2, 10), 1024);
EXPECT_EQ(dl::Math::Pow64(2, 10), 1024ull);
EXPECT_EQ(dl::Math::Pow32(2, 10), 1024u);
}
TEST(MathTest, SubU)
{
EXPECT_EQ(dl::Math::SubU(5u, 3u), 2u);
EXPECT_EQ(dl::Math::SubU(3u, 5u), 0u);
}
TEST(MathTest, DisU)
{
EXPECT_EQ(dl::Math::DisU(3u, 5u), 2u);
EXPECT_EQ(dl::Math::DisU(5u, 3u), 2u);
}
TEST(MathTest, IsPow2)
{
EXPECT_TRUE(dl::Math::IsPow2(8));
EXPECT_TRUE(dl::Math::IsPow2(1));
EXPECT_FALSE(dl::Math::IsPow2(0));
EXPECT_FALSE(dl::Math::IsPow2(6));
}
TEST(MathTest, AlignPow2)
{
EXPECT_EQ(dl::Math::AlignPow2(5u, 4u), 8u);
EXPECT_EQ(dl::Math::AlignPow2(8u, 4u), 8u);
EXPECT_EQ(dl::Math::AlignPow2(1u, 4u), 4u);
// 非 2 的幂返回 0
EXPECT_EQ(dl::Math::AlignPow2(5u, 3u), 0u);
}
TEST(MathTest, DistancePow2)
{
dl::Position a{ 0.0f, 0.0f };
dl::Position b{ 3.0f, 4.0f };
EXPECT_FLOAT_EQ(dl::Math::DistancePow2(a, b), 25.0f);
EXPECT_FLOAT_EQ(dl::Math::Distance(b - a), 5.0f);
}
TEST(MathTest, DotProduct)
{
dl::Position a{ 1.0f, 2.0f };
dl::Position b{ 3.0f, 4.0f };
EXPECT_FLOAT_EQ(dl::Math::DotProduct(a, b), 11.0f); // 1*3 + 2*4
}
TEST(MathTest, CrossProduct)
{
dl::Position2 a{ 1.0f, 0.0f };
dl::Position2 b{ 0.0f, 1.0f };
EXPECT_FLOAT_EQ(dl::Math::CrossProduct(a, b), 1.0f);
}
TEST(MathTest, IsLeapYear)
{
EXPECT_TRUE(dl::Math::IsLeapYear(2000));
EXPECT_TRUE(dl::Math::IsLeapYear(2024));
EXPECT_FALSE(dl::Math::IsLeapYear(1900));
EXPECT_FALSE(dl::Math::IsLeapYear(2023));
}
TEST(MathTest, GetMouthDayNum)
{
EXPECT_EQ(dl::Math::GetMouthDayNum(2024, 2), 29); // 闰年二月
EXPECT_EQ(dl::Math::GetMouthDayNum(2023, 2), 28); // 平年二月
EXPECT_EQ(dl::Math::GetMouthDayNum(2024, 1), 31);
EXPECT_EQ(dl::Math::GetMouthDayNum(2024, 4), 30);
}
//------------------------------算法------------------------------
TEST(MathTest, Clamp)
{
EXPECT_EQ(dl::clamp(5, 1, 3), 3); // 上界
EXPECT_EQ(dl::clamp(0, 1, 3), 1); // 下界
EXPECT_EQ(dl::clamp(2, 1, 3), 2); // 中间
EXPECT_FLOAT_EQ(dl::clamp(1.5f, 0.0f, 1.0f), 1.0f);
EXPECT_FLOAT_EQ(dl::clamp(-0.5f, 0.0f, 1.0f), 0.0f);
}
TEST(MathTest, Saturate)
{
EXPECT_FLOAT_EQ(dl::saturate(0.5f), 0.5f);
EXPECT_FLOAT_EQ(dl::saturate(2.0f), 1.0f);
EXPECT_FLOAT_EQ(dl::saturate(-1.0f), 0.0f);
EXPECT_TRUE(dl::is_saturate(0.5f));
EXPECT_FALSE(dl::is_saturate(1.5f));
}
TEST(MathTest, Sign)
{
EXPECT_EQ(dl::sign(5), 1);
EXPECT_EQ(dl::sign(-5), -1);
EXPECT_EQ(dl::sign(0), 0);
}
TEST(MathTest, Cross3)
{
dl::Position3 a{ 1.0f, 0.0f, 0.0f };
dl::Position3 b{ 0.0f, 1.0f, 0.0f };
auto c = dl::cross(a, b);
EXPECT_FLOAT_EQ(c[0], 0.0f);
EXPECT_FLOAT_EQ(c[1], 0.0f);
EXPECT_FLOAT_EQ(c[2], 1.0f);
}
TEST(MathTest, InsertPerNum)
{
EXPECT_EQ(dl::insert_per_num(std::string("1234567890"), ',', 3), "123,456,789,0");
EXPECT_EQ(dl::r_insert_per_num(std::string("123456789"), ',', 3), "123,456,789");
}
TEST(MathTest, MakeSequence)
{
std::vector<int> v;
dl::make_sequence<std::vector<int>, int>(v, { {0, 3}, {5, 7} });
ASSERT_EQ(v.size(), 5u);
EXPECT_EQ(v[0], 0);
EXPECT_EQ(v[1], 1);
EXPECT_EQ(v[2], 2);
EXPECT_EQ(v[3], 5);
EXPECT_EQ(v[4], 6);
}
//------------------------------Random------------------------------
TEST(RandomTest, SetSeed)
{
dl::Random::SetSeed(42);
int a = dl::Random::Int(0, 100);
dl::Random::SetSeed(42);
int b = dl::Random::Int(0, 100);
EXPECT_EQ(a, b); // 同种子结果一致
}
TEST(RandomTest, IntRange)
{
dl::Random::SetSeed(1);
for (int i = 0; i < 100; ++i)
{
int v = dl::Random::Int(10, 20);
EXPECT_GE(v, 10);
EXPECT_LE(v, 20);
}
}
TEST(RandomTest, FloatRange)
{
dl::Random::SetSeed(1);
for (int i = 0; i < 100; ++i)
{
float v = dl::Random::Float(0.0f, 1.0f);
EXPECT_GE(v, 0.0f);
EXPECT_LT(v, 1.0f);
}
}
TEST(RandomTest, Percent)
{
dl::Random::SetSeed(1);
EXPECT_TRUE(dl::Random::Percent(100));
EXPECT_FALSE(dl::Random::Percent(0));
}
TEST(RandomTest, Select)
{
std::vector<int> v = { 1, 2, 3, 4, 5 };
dl::Random::SetSeed(1);
int sel = dl::Random::Select(v);
EXPECT_GE(sel, 1);
EXPECT_LE(sel, 5);
}
//------------------------------TexturePack------------------------------
TEST(TexturePackTest, Dynamic)
{
dl::TexturePack::Dynamic<2> pack;
pack.Reset({ 100, 100 });
dl::RectU r1;
EXPECT_TRUE(pack.Add({ 30, 30 }, r1));
EXPECT_EQ(r1[0], 0u);
EXPECT_EQ(r1[1], 0u);
EXPECT_EQ(r1[2], 30u);
EXPECT_EQ(r1[3], 30u);
dl::RectU r2;
EXPECT_TRUE(pack.Add({ 30, 30 }, r2));
EXPECT_EQ(r2[0], 30u); // 同一行,x 偏移
EXPECT_EQ(r2[1], 0u);
dl::RectU r3;
EXPECT_TRUE(pack.Add({ 30, 30 }, r3));
EXPECT_EQ(r3[0], 60u);
EXPECT_EQ(r3[1], 0u);
dl::RectU r4;
EXPECT_TRUE(pack.Add({ 30, 30 }, r4));
EXPECT_EQ(r4[0], 0u); // 换行
EXPECT_EQ(r4[1], 30u);
}
TEST(TexturePackTest, Static)
{
dl::TexturePack::Static pack;
pack.SetSize({ 100, 100 });
std::list<dl::Size> boxes = { {50, 50}, {50, 50}, {100, 50} };
std::vector<dl::PointU> results;
pack.Calc(boxes,
[](const dl::Size& s) { return s; },
[&](const dl::Size& s, const dl::PointU& lt) { results.push_back(lt); });
// 3 个箱子总面积 10000 = 100*100,能全部放下
EXPECT_TRUE(boxes.empty());
EXPECT_EQ(results.size(), 3u);
}
+198
View File
@@ -0,0 +1,198 @@
/**
* @file test_memory.cpp
* @brief memory 模块单元测试(压缩)
*
*
* @version 1.0
* @author CodeBuddy
* @date 26-09-03
*
* @note
*/
#include <gtest/gtest.h>
#include "memory/dl_memory.h"
#include "memory/dl_stream_output.h"
#include "memory/dl_stream_input.h"
#include "base/dl_string.h"
TEST(MemoryTest, CompressLz4)
{
std::string str("abcabcabcabcabc");
dl::BufferView buf = dl::CreateBufferView(str);
dl::Buffer zip = dl::Memory::CompressLz4(buf);
EXPECT_FALSE(zip.empty());
dl::Buffer unzip = dl::Memory::DecompressLz4(zip);
EXPECT_EQ(dl::to_string(unzip), str);
}
TEST(MemoryTest, DecompressLz4WithSize)
{
std::string str("hello world hello world");
dl::BufferView buf = dl::CreateBufferView(str);
dl::Buffer zip = dl::Memory::CompressLz4(buf);
dl::Buffer unzip = dl::Memory::DecompressLz4(zip, str.size());
EXPECT_EQ(dl::to_string(unzip), str);
}
TEST(MemoryTest, CompressZip)
{
std::string str("abcabcabcabcabc");
dl::BufferView buf = dl::CreateBufferView(str);
dl::Buffer zip = dl::Memory::CompressZip(buf);
EXPECT_FALSE(zip.empty());
dl::Buffer unzip = dl::Memory::DecompressZip(zip);
EXPECT_EQ(dl::to_string(unzip), str);
}
TEST(MemoryTest, CompressEmpty)
{
std::string str;
dl::BufferView buf = dl::CreateBufferView(str);
dl::Buffer zip = dl::Memory::CompressLz4(buf);
dl::Buffer unzip = dl::Memory::DecompressLz4(zip);
EXPECT_EQ(dl::to_string(unzip), str);
}
//------------------------------Stream 序列化往返------------------------------
TEST(StreamTest, WriteReadBasic)
{
dl::StreamOutput s;
int a = 42;
float b = 3.14f;
double c = 2.718;
s.Write(&a);
s.Write(&b);
s.Write(&c);
dl::Buffer buf = s.ToBuffer();
dl::StreamInput in;
in.LoadFromMemory(buf);
int a2 = 0;
float b2 = 0;
double c2 = 0;
in.Read(&a2);
in.Read(&b2);
in.Read(&c2);
EXPECT_EQ(a2, 42);
EXPECT_FLOAT_EQ(b2, 3.14f);
EXPECT_DOUBLE_EQ(c2, 2.718);
}
TEST(StreamTest, WriteRead64)
{
dl::StreamOutput s;
size_t v = 123456789;
s.Write64(&v);
dl::Buffer buf = s.ToBuffer();
dl::StreamInput in;
in.LoadFromMemory(buf);
size_t v2 = 0;
in.Read64(&v2);
EXPECT_EQ(v2, 123456789u);
}
TEST(StreamTest, WriteReadString)
{
dl::StreamOutput s;
std::string str = "hello world";
s.Write(&str);
dl::Buffer buf = s.ToBuffer();
dl::StreamInput in;
in.LoadFromMemory(buf);
std::string str2;
in.Read(&str2);
EXPECT_EQ(str2, "hello world");
}
TEST(StreamTest, WriteReadVector)
{
dl::StreamOutput s;
std::vector<int> vec = { 1, 2, 3, 4, 5 };
s.Write(&vec);
dl::Buffer buf = s.ToBuffer();
dl::StreamInput in;
in.LoadFromMemory(buf);
std::vector<int> vec2;
in.Read(&vec2);
ASSERT_EQ(vec2.size(), 5u);
EXPECT_EQ(vec2[0], 1);
EXPECT_EQ(vec2[4], 5);
}
TEST(StreamTest, WriteReadMap)
{
dl::StreamOutput s;
std::map<std::string, int> m = { {"a", 1}, {"b", 2} };
s.Write(&m);
dl::Buffer buf = s.ToBuffer();
dl::StreamInput in;
in.LoadFromMemory(buf);
std::map<std::string, int> m2;
in.Read(&m2);
ASSERT_EQ(m2.size(), 2u);
EXPECT_EQ(m2["a"], 1);
EXPECT_EQ(m2["b"], 2);
}
TEST(StreamTest, WriteReadUnorderedMap)
{
dl::StreamOutput s;
std::unordered_map<std::string, int> m = { {"x", 10}, {"y", 20} };
s.Write(&m);
dl::Buffer buf = s.ToBuffer();
dl::StreamInput in;
in.LoadFromMemory(buf);
std::unordered_map<std::string, int> m2;
in.Read(&m2);
ASSERT_EQ(m2.size(), 2u);
EXPECT_EQ(m2["x"], 10);
EXPECT_EQ(m2["y"], 20);
}
//------------------------------Buffer------------------------------
TEST(BufferTest, Hex)
{
// "Hello" 的十六进制
dl::Buffer buf = dl::CreateBufferHex("48656c6c6f");
ASSERT_EQ(buf.size(), 5u);
EXPECT_EQ(dl::to_string(buf), "Hello");
EXPECT_EQ(dl::to_string_hex(buf), "48656c6c6f");
EXPECT_EQ(dl::to_string_hex(buf, false, true), "0x48656c6c6f");
}
TEST(BufferTest, Append)
{
dl::Buffer buf = dl::CreateBuffer(dl::CreateBufferView(std::string("hello")));
dl::BufferAppend(buf, dl::CreateBufferView(std::string(" world")));
EXPECT_EQ(dl::to_string(buf), "hello world");
}
TEST(BufferTest, Basic)
{
dl::Buffer buf;
EXPECT_TRUE(buf.empty());
buf.resize(10);
EXPECT_EQ(buf.size(), 10u);
EXPECT_FALSE(buf.empty());
buf.clear();
EXPECT_TRUE(buf.empty());
EXPECT_EQ(buf.size(), 0u);
}
+589
View File
@@ -0,0 +1,589 @@
/**
* @file test_misc.cpp
* @brief misc 模块单元测试(Value、Locator、Timer、Layout、AStar、CodeWriter
*
*
* @version 1.0
* @author CodeBuddy
* @date 26-09-03
*
* @note
*/
#include <gtest/gtest.h>
#include "dl_type.h"
#include "misc/dl_value.h"
#include "misc/dl_locator.h"
#include "misc/dl_layout.h"
#include "misc/dl_timer.h"
#include "misc/dl_astar.h"
#include "misc/dl_code_writer.h"
#include "misc/dl_tilemap.h"
#include "misc/dl_json_config.h"
#include "misc/dl_language.h"
#include "io/dl_file.h"
#include "render/dl_factory.h"
#include <OpenXLSX.hpp>
//------------------------------Value------------------------------
TEST(ValueTest, DefaultNone)
{
dl::Value v;
EXPECT_EQ(v.GetType(), dl::ValueType::NONE);
EXPECT_FALSE(v);
EXPECT_EQ(v.GetString(), "null");
}
TEST(ValueTest, Bool)
{
dl::Value v(true);
EXPECT_EQ(v.GetType(), dl::ValueType::BOOL);
EXPECT_TRUE(v.ToBool());
EXPECT_EQ(v.GetString(), "true");
dl::Value vf(false);
EXPECT_FALSE(vf.ToBool());
EXPECT_EQ(vf.GetString(), "false");
}
TEST(ValueTest, Int)
{
dl::Value v(42);
EXPECT_EQ(v.GetType(), dl::ValueType::INT);
EXPECT_EQ(v.ToInt(), 42);
EXPECT_FLOAT_EQ(v.ToFloat(), 42.0f);
EXPECT_DOUBLE_EQ(v.ToDouble(), 42.0);
EXPECT_EQ(v.GetString(), "42");
}
TEST(ValueTest, FloatDouble)
{
dl::Value vf(3.14f);
EXPECT_EQ(vf.GetType(), dl::ValueType::FLOAT);
EXPECT_FLOAT_EQ(vf.ToFloat(), 3.14f);
dl::Value vd(3.14);
EXPECT_EQ(vd.GetType(), dl::ValueType::DOUBLE);
EXPECT_DOUBLE_EQ(vd.ToDouble(), 3.14);
}
TEST(ValueTest, String)
{
dl::Value v("hello");
EXPECT_EQ(v.GetType(), dl::ValueType::STRING);
EXPECT_EQ(v.ToString(), "hello");
EXPECT_EQ(v.GetString(), "\"hello\"");
EXPECT_EQ(v.GetString(false), "hello");
}
TEST(ValueTest, CopyString)
{
dl::Value a(std::string("hello"));
dl::Value b = a;
EXPECT_EQ(b.GetType(), dl::ValueType::STRING);
EXPECT_EQ(b.ToString(), "hello");
}
TEST(ValueTest, Vector)
{
dl::ValueVector vec(dl::ValueType::INT);
vec.PushBack(1);
vec.PushBack(2);
vec.PushBack(3);
dl::Value v(vec);
EXPECT_EQ(v.GetType(), dl::ValueType::VECTOR);
EXPECT_EQ(v.GetString(), "{ 1, 2, 3 }");
auto j = v.GetJson();
ASSERT_TRUE(j.is_array());
ASSERT_EQ(j.size(), 3u);
EXPECT_EQ(j[0], 1);
EXPECT_EQ(j[2], 3);
}
TEST(ValueTest, Array)
{
dl::Value v(std::array<int, 3>{10, 20, 30});
EXPECT_EQ(v.GetType(), dl::ValueType::ARRAY);
auto arr = v.ToArray<3>();
EXPECT_EQ(arr[0].ToInt(), 10);
EXPECT_EQ(arr[1].ToInt(), 20);
EXPECT_EQ(arr[2].ToInt(), 30);
}
TEST(ValueTest, Struct)
{
dl::ValueStruct s("student");
dl::Value v_id(100);
dl::Value v_name("tom");
s.AddMember("id", v_id);
s.AddMember("name", v_name);
EXPECT_EQ(s.GetName(), "student");
EXPECT_EQ(s["id"].ToInt(), 100);
EXPECT_EQ(s.GetMember("name").ToString(), "tom");
}
TEST(ValueTest, CastFailed)
{
dl::Value v("hello");
EXPECT_EQ(v.ToInt(), 0);
EXPECT_FLOAT_EQ(v.ToFloat(), 0.0f);
EXPECT_FALSE(v.ToBool());
}
TEST(ValueTest, OperatorBool)
{
dl::Value v_none;
EXPECT_FALSE(v_none);
dl::Value v_false(false);
EXPECT_FALSE(v_false);
dl::Value v_true(true);
EXPECT_TRUE(v_true);
dl::Value v_int(0);
EXPECT_TRUE(v_int); // 非 NONE/BOOL 恒为真
}
//------------------------------类型转换------------------------------
TEST(ValueTest, String2ValueType)
{
EXPECT_EQ(dl::String2ValueType("bool"), dl::ValueType::BOOL);
EXPECT_EQ(dl::String2ValueType("int"), dl::ValueType::INT);
EXPECT_EQ(dl::String2ValueType("uint"), dl::ValueType::UINT);
EXPECT_EQ(dl::String2ValueType("int64"), dl::ValueType::INT64);
EXPECT_EQ(dl::String2ValueType("float"), dl::ValueType::FLOAT);
EXPECT_EQ(dl::String2ValueType("double"), dl::ValueType::DOUBLE);
EXPECT_EQ(dl::String2ValueType("string"), dl::ValueType::STRING);
EXPECT_EQ(dl::String2ValueType("array<int, 3>"), dl::ValueType::ARRAY);
EXPECT_EQ(dl::String2ValueType("vector<int>"), dl::ValueType::VECTOR);
EXPECT_EQ(dl::String2ValueType("MyStruct"), dl::ValueType::STRUCT);
}
TEST(ValueTest, String2ValueTypeEx)
{
auto info = dl::String2ValueTypeEx("array<int, 3>");
EXPECT_EQ(info._type0, dl::ValueType::ARRAY);
EXPECT_EQ(info._type1, dl::ValueType::INT);
EXPECT_EQ(info._length, 3u);
EXPECT_EQ(info._strType1, "int");
auto info2 = dl::String2ValueTypeEx("vector<float>");
EXPECT_EQ(info2._type0, dl::ValueType::VECTOR);
EXPECT_EQ(info2._type1, dl::ValueType::FLOAT);
EXPECT_EQ(info2._length, 0u);
}
TEST(ValueTest, ToStringType)
{
EXPECT_EQ(dl::to_string(dl::ValueType::NONE), "null");
EXPECT_EQ(dl::to_string(dl::ValueType::INT), "int");
EXPECT_EQ(dl::to_string(dl::ValueType::STRING), "string");
EXPECT_EQ(dl::to_string(dl::ValueType::ARRAY), "array");
EXPECT_EQ(dl::to_string(dl::ValueType::MAP), "map");
}
TEST(ValueTest, Type2CppType)
{
EXPECT_EQ(dl::Type2CppType(dl::ValueType::INT), "int");
EXPECT_EQ(dl::Type2CppType(dl::ValueType::UINT), "unsigned");
EXPECT_EQ(dl::Type2CppType(dl::ValueType::UCHAR), "unsigned char");
EXPECT_EQ(dl::Type2CppType(dl::ValueType::STRING), "std::string");
EXPECT_EQ(dl::Type2CppType(dl::ValueType::ARRAY), "std::array");
EXPECT_EQ(dl::Type2CppType(dl::ValueType::VECTOR), "std::vector");
EXPECT_EQ(dl::Type2CppType(dl::ValueType::POINTER), "void*");
EXPECT_EQ(dl::Type2CppTypeEx(dl::ValueType::ARRAY, dl::ValueType::INT, 3), "std::array<int, 3>");
}
//------------------------------Layout------------------------------
TEST(LayoutTest, String2Layout)
{
EXPECT_EQ(dl::String2Layout("x"), dl::Layout::X);
EXPECT_EQ(dl::String2Layout("y"), dl::Layout::Y);
EXPECT_EQ(dl::String2Layout("xy"), dl::Layout::XY);
EXPECT_EQ(dl::String2Layout("origin"), dl::Layout::ORIGIN);
EXPECT_EQ(dl::String2Layout("X"), dl::Layout::X);
EXPECT_EQ(dl::String2Layout("XY"), dl::Layout::XY);
}
//------------------------------Locator------------------------------
TEST(LocatorTest, DirectX)
{
auto loc = dl::createLocatorX(10.0f);
EXPECT_FLOAT_EQ(loc.Get(0)[0], 0.0f);
EXPECT_FLOAT_EQ(loc.Get(0)[1], 0.0f);
EXPECT_FLOAT_EQ(loc.Get(1)[0], 10.0f);
EXPECT_FLOAT_EQ(loc.Get(2)[0], 20.0f);
}
TEST(LocatorTest, DirectXWrap)
{
auto loc = dl::createLocatorX(10.0f, 3);
EXPECT_FLOAT_EQ(loc.Get(0)[0], 0.0f);
EXPECT_FLOAT_EQ(loc.Get(1)[0], 10.0f);
EXPECT_FLOAT_EQ(loc.Get(2)[0], 20.0f);
auto p3 = loc.Get(3);
EXPECT_FLOAT_EQ(p3[0], 0.0f);
EXPECT_FLOAT_EQ(p3[1], 32.0f);
}
TEST(LocatorTest, DirectY)
{
auto loc = dl::createLocatorY(10.0f);
EXPECT_FLOAT_EQ(loc.Get(0)[1], 0.0f);
EXPECT_FLOAT_EQ(loc.Get(1)[1], 10.0f);
EXPECT_FLOAT_EQ(loc.Get(2)[1], 20.0f);
}
TEST(LocatorTest, DirectXY)
{
dl::Locator::SL sl;
sl._dt = { 10.0f, 20.0f };
sl._layout = dl::Layout::XY;
dl::Locator loc(sl);
auto p = loc.Get(3);
EXPECT_FLOAT_EQ(p[0], 30.0f);
EXPECT_FLOAT_EQ(p[1], 60.0f);
}
TEST(LocatorTest, Origin)
{
auto loc = dl::createLocatorZero();
auto p = loc.Get(5);
EXPECT_FLOAT_EQ(p[0], 0.0f);
EXPECT_FLOAT_EQ(p[1], 0.0f);
}
TEST(LocatorTest, AdaptX)
{
auto loc = dl::createLocatorX(10.0f, 0, 32.0f, dl::Locator::Mode::ADAPT);
dl::Size s{ 10, 10 };
auto p0 = loc.Get(s);
EXPECT_FLOAT_EQ(p0[0], 0.0f);
auto p1 = loc.Get(s);
EXPECT_FLOAT_EQ(p1[0], 20.0f);
}
TEST(LocatorTest, ExGet)
{
auto loc = dl::createLocatorX(10.0f);
dl::Position pos{ 5.0f, 5.0f };
EXPECT_TRUE(loc.ExGet(2, dl::Size{}, pos));
EXPECT_FLOAT_EQ(pos[0], 25.0f);
EXPECT_FLOAT_EQ(pos[1], 5.0f);
}
//------------------------------Timer------------------------------
TEST(TimerTest, Regular)
{
dl::TimerRegular t(2.0f);
EXPECT_FALSE(t.Run(1.0f));
EXPECT_FALSE(t.Run(0.5f));
EXPECT_TRUE(t.Run(0.5f));
EXPECT_FALSE(t.Run(0.1f));
}
TEST(TimerTest, Reverse)
{
dl::TimerReverse t(1.0f);
EXPECT_FALSE(t.Run(0.5f));
EXPECT_TRUE(t.Run(0.5f));
EXPECT_TRUE(t.Run(0.5f));
EXPECT_FALSE(t.Run(0.5f));
}
//------------------------------AStar------------------------------
TEST(AStarTest, Search)
{
auto g = [](const dl::Point& a, const dl::Point& b) -> int { return 10; };
dl::AStar<dl::Point, int> astar(dl::Point{}, g);
astar.SetSize({ 5, 5 });
std::list<dl::Point> path;
EXPECT_TRUE(astar.Search({ 0, 0 }, { 4, 4 }, false, path));
EXPECT_FALSE(path.empty());
EXPECT_EQ(path.front(), (dl::Point{ 0, 0 }));
EXPECT_EQ(path.back(), (dl::Point{ 4, 4 }));
}
TEST(AStarTest, SearchBlocked)
{
auto g = [](const dl::Point& a, const dl::Point& b) -> int
{
if (b.x == 2)
return 0; // x=2 整列不可通行
return 10;
};
dl::AStar<dl::Point, int> astar(dl::Point{}, g);
astar.SetSize({ 5, 5 });
std::list<dl::Point> path;
EXPECT_FALSE(astar.Search({ 0, 0 }, { 4, 4 }, false, path));
}
//------------------------------CodeWriter------------------------------
TEST(CodeWriterTest, IsStdType)
{
EXPECT_TRUE(dl::CodeWriter::IsStdType("string"));
EXPECT_FALSE(dl::CodeWriter::IsStdType("int"));
}
TEST(CodeWriterTest, AddStdNamespace)
{
std::string s = "string";
dl::CodeWriter::AddStdNamespace(s);
EXPECT_EQ(s, "std::string");
std::string i = "int";
dl::CodeWriter::AddStdNamespace(i);
EXPECT_EQ(i, "int");
}
TEST(CodeWriterTest, ReplaceType)
{
std::string s = "uchar";
dl::CodeWriter::ReplaceType(s);
EXPECT_EQ(s, "unsigned char");
std::string i = "int64";
dl::CodeWriter::ReplaceType(i);
EXPECT_EQ(i, "int64_t");
std::string i2 = "int32";
dl::CodeWriter::ReplaceType(i2);
EXPECT_EQ(i2, "int32_t");
}
TEST(CodeWriterTest, StructGetVariable)
{
dl::CodeWriter::Struct s;
s._name = "Student";
s._value = "stu";
dl::CodeWriter::Variable v;
v._name = "id";
v._type = "int";
s._allVariable.push_back(v);
auto* p = s.GetVariable("id");
ASSERT_NE(p, nullptr);
EXPECT_EQ(p->_type, "int");
EXPECT_EQ(s.GetVariable("none"), nullptr);
}
TEST(CodeWriterTest, SegmentGetStruct)
{
dl::CodeWriter::Segment seg;
dl::CodeWriter::Struct s;
s._name = "Student";
s._value = "stu";
dl::CodeWriter::Variable v;
v._name = "id";
v._type = "int";
s._allVariable.push_back(v);
seg._allStruct.push_back(s);
auto* ps = seg.GetStruct("Student");
ASSERT_NE(ps, nullptr);
EXPECT_EQ(ps->_value, "stu");
auto* pv = seg.GetVariable("Student", "id");
ASSERT_NE(pv, nullptr);
EXPECT_EQ(pv->_type, "int");
EXPECT_EQ(seg.GetStruct("None"), nullptr);
EXPECT_EQ(seg.GetVariable("Student", "none"), nullptr);
}
TEST(CodeWriterTest, StructFormatVariable)
{
dl::CodeWriter::Struct s;
s._name = "Test";
s._value = "t";
dl::CodeWriter::Variable v1;
v1._name = "a";
v1._type = "int";
dl::CodeWriter::Variable v2;
v2._name = "long_name";
v2._type = "std::string";
s._allVariable.push_back(v1);
s._allVariable.push_back(v2);
s.FormatVariable();
// 对齐后,短的名字/类型会被补 tab,长度不小于 4
EXPECT_GE(s._allVariable[0]._name.size(), 4u);
EXPECT_GE(s._allVariable[1]._name.size(), 4u);
EXPECT_GE(s._allVariable[0]._type.size(), 4u);
EXPECT_GE(s._allVariable[1]._type.size(), 4u);
EXPECT_EQ(s._allVariable[0]._name.back(), '\t');
EXPECT_EQ(s._allVariable[1]._name.back(), '\t');
EXPECT_EQ(s._allVariable[0]._type.back(), '\t');
EXPECT_EQ(s._allVariable[1]._type.back(), '\t');
}
//------------------------------TileMap------------------------------
TEST(TileMapTest, Rectangle)
{
dl::TileMap::Rectangle<dl::Position{32.0f, 32.0f}> map;
auto world = map.Map2World(dl::Point{1, 2});
EXPECT_FLOAT_EQ(world[0], 32.0f);
EXPECT_FLOAT_EQ(world[1], 64.0f);
auto mp = map.World2Map(dl::Position{32.0f, 64.0f});
EXPECT_EQ(mp[0], 1);
EXPECT_EQ(mp[1], 2);
}
TEST(TileMapTest, DiamondSlant)
{
dl::TileMap::DiamondSlant<dl::Position{32.0f, 32.0f}> map;
auto world = map.Map2World(dl::Point{0, 0});
EXPECT_FLOAT_EQ(world[0], 0.0f);
EXPECT_FLOAT_EQ(world[1], 0.0f);
auto world2 = map.Map2World(dl::Point{1, 0});
EXPECT_FLOAT_EQ(world2[0], 16.0f);
EXPECT_FLOAT_EQ(world2[1], -16.0f);
}
//------------------------------JsonConfig------------------------------
TEST(JsonConfigTest, LoadFailed)
{
dl::JsonConfig cfg;
EXPECT_FALSE(cfg.Load("/nonexistent/path/file.json"));
}
TEST(JsonConfigTest, LoadGenerateCode)
{
std::string path = dl::g_factory->GetPathTemp() + "dl_json_config_test.json";
std::string json_str = R"({
"name": "测试配置",
"desc": "配置描述",
"type": "config",
"value": {
"speed": {
"name": "速度",
"desc": "移动速度",
"type": "int",
"value": 100
},
"title": {
"name": "标题",
"type": "string",
"value": "hello"
}
}
})";
ASSERT_TRUE(dl::File::SaveString(json_str, path));
dl::JsonConfig cfg;
ASSERT_TRUE(cfg.Load(path));
dl::JsonConfig::GenerateParam p;
p._filename = "test.h";
p._brief = "测试";
p._author = "tester";
p._date = "2026";
p._logFunction = "log_err";
p._namespace = "test";
std::string code = cfg.GenerateCode(p);
EXPECT_FALSE(code.empty());
EXPECT_NE(code.find("struct config"), std::string::npos);
EXPECT_NE(code.find("int speed"), std::string::npos);
dl::File::Delete(path);
}
TEST(JsonConfigTest, GenerateConfigUser)
{
std::string path = dl::g_factory->GetPathTemp() + "dl_json_config_test.json";
std::string json_str = R"({
"name": "测试配置",
"type": "config",
"value": {
"speed": {
"type": "int",
"value": 100
}
}
})";
ASSERT_TRUE(dl::File::SaveString(json_str, path));
dl::JsonConfig cfg;
ASSERT_TRUE(cfg.Load(path));
std::string user = cfg.GenerateConfigUser();
EXPECT_FALSE(user.empty());
EXPECT_NE(user.find("speed"), std::string::npos);
EXPECT_NE(user.find("100"), std::string::npos);
dl::File::Delete(path);
}
//------------------------------Language------------------------------
TEST(LanguageTest, LoadGet)
{
std::string path = dl::g_factory->GetPathTemp() + "dl_language_test.xlsx";
// 用 OpenXLSX 写临时 xlsx:第0列 tag、第1列 name、第2+列语言
{
OpenXLSX::XLDocument doc;
doc.create(path);
auto wks = doc.workbook().worksheet("Sheet1");
wks.cell(1, 1).value() = "tag";
wks.cell(1, 2).value() = "name";
wks.cell(1, 3).value() = "English";
wks.cell(1, 4).value() = "简体中文";
wks.cell(2, 1).value() = "menu";
wks.cell(2, 2).value() = "start";
wks.cell(2, 3).value() = "Start";
wks.cell(2, 4).value() = "开始";
wks.cell(3, 1).value() = "menu";
wks.cell(3, 2).value() = "exit";
wks.cell(3, 3).value() = "Exit";
wks.cell(3, 4).value() = "退出";
doc.save();
doc.close();
}
dl::Language lang;
lang.LoadXlsx(path);
// 英文
lang.SetLangCurrent(dl::Language::E_ENGLISH);
EXPECT_EQ(lang.Get("menu", "start"), "Start");
EXPECT_EQ(lang.Get("menu", "exit"), "Exit");
// 中文
lang.SetLangCurrent(dl::Language::E_CHINESE);
EXPECT_EQ(lang.Get("menu", "start"), "开始");
EXPECT_EQ(lang.Get("menu", "exit"), "退出");
// 失败返回特定字符串
EXPECT_EQ(lang.Get("nottag", "start"), "not_find_tag");
EXPECT_EQ(lang.Get("menu", "notname"), "not_find");
// GetCheck
auto check = lang.GetCheck("menu", "start");
ASSERT_TRUE(check.has_value());
EXPECT_EQ(*check, "开始");
EXPECT_FALSE(lang.GetCheck("menu", "none").has_value());
// GetTagSize
EXPECT_EQ(lang.GetTagSize("menu"), 2u);
// GetTagMap
auto m = lang.GetTagMap("menu");
EXPECT_EQ(m.size(), 2u);
EXPECT_EQ(m["start"], "开始");
EXPECT_EQ(m["exit"], "退出");
// GetLangAll
const auto& langs = lang.GetLangAll();
ASSERT_EQ(langs.size(), 2u);
EXPECT_EQ(langs[0], "English");
dl::File::Delete(path);
}
+146
View File
@@ -0,0 +1,146 @@
/**
* @file test_tool.cpp
* @brief tool 模块单元测试(Archiver 归档器)
*
*
* @version 1.0
* @author CodeBuddy
* @date 26-09-03
*
* @note
*/
#include <gtest/gtest.h>
#include "tool/dl_tool_archiver.h"
#include "io/dl_file.h"
#include "render/dl_factory.h"
namespace
{
//! 构造一个测试用的临时源目录(含 a.txt 与 sub/b.txt
bool CreateTestSrc(const std::string& dir_src)
{
if (!dl::File::CreateFolder(dir_src))
return false;
if (!dl::File::CreateFolder(dir_src + "sub/"))
return false;
if (!dl::File::SaveString("hello world", dir_src + "a.txt"))
return false;
if (!dl::File::SaveString("second file", dir_src + "sub/b.txt"))
return false;
return true;
}
}
TEST(ArchiverTest, CompressDecompress)
{
std::string dir_src = dl::g_factory->GetPathTemp() + "dl_archiver_src/";
std::string dir_out = dl::g_factory->GetPathTemp() + "dl_archiver_out/";
std::string file_arc = dl::g_factory->GetPathTemp() + "dl_archiver.bin";
dl::File::Delete(dir_src, true);
dl::File::Delete(dir_out, true);
dl::File::Delete(file_arc);
ASSERT_TRUE(CreateTestSrc(dir_src));
dl::Tool::Archiver::Param p;
p._src = dir_src;
p._out = file_arc;
p._compressMode = dl::Memory::E_NONE;
p._bCrc = false;
dl::Tool::Archiver::Compress(p);
ASSERT_TRUE(dl::File::IsExist(file_arc));
ASSERT_TRUE(dl::Tool::Archiver::Decompress(file_arc, dir_out));
EXPECT_TRUE(dl::File::IsExist(dir_out + "a.txt"));
EXPECT_TRUE(dl::File::IsExist(dir_out + "sub/b.txt"));
EXPECT_EQ(dl::File::GetString(dir_out + "a.txt"), "hello world");
EXPECT_EQ(dl::File::GetString(dir_out + "sub/b.txt"), "second file");
dl::File::Delete(dir_src, true);
dl::File::Delete(dir_out, true);
dl::File::Delete(file_arc);
}
TEST(ArchiverTest, CompressDecompressLz4)
{
std::string dir_src = dl::g_factory->GetPathTemp() + "dl_archiver_src/";
std::string dir_out = dl::g_factory->GetPathTemp() + "dl_archiver_out/";
std::string file_arc = dl::g_factory->GetPathTemp() + "dl_archiver.bin";
dl::File::Delete(dir_src, true);
dl::File::Delete(dir_out, true);
dl::File::Delete(file_arc);
ASSERT_TRUE(CreateTestSrc(dir_src));
dl::Tool::Archiver::Param p;
p._src = dir_src;
p._out = file_arc;
p._compressMode = dl::Memory::E_LZ4;
p._bCrc = false;
dl::Tool::Archiver::Compress(p);
ASSERT_TRUE(dl::File::IsExist(file_arc));
ASSERT_TRUE(dl::Tool::Archiver::Decompress(file_arc, dir_out));
EXPECT_TRUE(dl::File::IsExist(dir_out + "a.txt"));
EXPECT_TRUE(dl::File::IsExist(dir_out + "sub/b.txt"));
EXPECT_EQ(dl::File::GetString(dir_out + "a.txt"), "hello world");
EXPECT_EQ(dl::File::GetString(dir_out + "sub/b.txt"), "second file");
dl::File::Delete(dir_src, true);
dl::File::Delete(dir_out, true);
dl::File::Delete(file_arc);
}
TEST(ArchiverTest, GetFileList)
{
std::string dir_src = dl::g_factory->GetPathTemp() + "dl_archiver_src/";
std::string file_arc = dl::g_factory->GetPathTemp() + "dl_archiver.bin";
dl::File::Delete(dir_src, true);
dl::File::Delete(file_arc);
ASSERT_TRUE(CreateTestSrc(dir_src));
dl::Tool::Archiver::Param p;
p._src = dir_src;
p._out = file_arc;
p._compressMode = dl::Memory::E_NONE;
p._bCrc = false;
dl::Tool::Archiver::Compress(p);
dl::Buffer buf = dl::File::GetBuffer(file_arc);
ASSERT_FALSE(buf.empty());
dl::Tool::Archiver::FileList list;
ASSERT_TRUE(dl::Tool::Archiver::GetFileList(buf, list));
EXPECT_EQ(list.size(), 2u);
bool found_a = false;
bool found_b = false;
for (auto& [name, info] : list)
{
if (name.find("a.txt") != std::string::npos)
found_a = true;
if (name.find("b.txt") != std::string::npos)
found_b = true;
}
EXPECT_TRUE(found_a);
EXPECT_TRUE(found_b);
dl::File::Delete(dir_src, true);
dl::File::Delete(file_arc);
}
TEST(ArchiverTest, DecompressBadType)
{
std::string bad = "this is not an archiver file";
dl::Buffer buf = dl::CreateBuffer(dl::CreateBufferView(bad));
std::string dir_out = dl::g_factory->GetPathTemp() + "dl_archiver_bad/";
dl::File::Delete(dir_out, true);
EXPECT_FALSE(dl::Tool::Archiver::Decompress(buf, dir_out));
dl::File::Delete(dir_out, true);
}