diff --git a/DetourCrowd/Source/DetourPathCorridor.cpp b/DetourCrowd/Source/DetourPathCorridor.cpp index bddea5a2..3835a389 100644 --- a/DetourCrowd/Source/DetourPathCorridor.cpp +++ b/DetourCrowd/Source/DetourPathCorridor.cpp @@ -59,13 +59,13 @@ int dtMergeCorridorStartMoved(dtPolyRef* path, const int npath, const int maxPat int size = dtMax(0, npath-orig); if (req+size > maxPath) size = maxPath-req; - if (size) + if (size > 0) memmove(path+req, path+orig, size*sizeof(dtPolyRef)); - + // Store visited - for (int i = 0; i < req; ++i) - path[i] = visited[(nvisited-1)-i]; - + for (int i = 0, n = dtMin(req, maxPath); i < n; ++i) + path[i] = visited[(nvisited-1)-i]; + return req+size; } diff --git a/RecastDemo/premake5.lua b/RecastDemo/premake5.lua index 7ede4d6b..826859e1 100644 --- a/RecastDemo/premake5.lua +++ b/RecastDemo/premake5.lua @@ -223,14 +223,15 @@ project "Tests" "../Tests/Recast/*.cpp", "../Tests/Detour/*.h", "../Tests/Detour/*.cpp", + "../Tests/DetourCrowd/*.cpp", "../Tests/Contrib/catch2/*.cpp" } -- project dependencies links { "DebugUtils", - "Detour", "DetourCrowd", + "Detour", "DetourTileCache", "Recast", } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 9a87479e..c37a6c9c 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1,14 +1,19 @@ -file(GLOB TESTS_SOURCES Detour/*.cpp Recast/*.cpp) - include_directories(../Detour/Include) include_directories(../Recast/Include) -add_executable(Tests ${TESTS_SOURCES}) +add_executable(Tests + Detour/Tests_Detour.cpp + Recast/Bench_rcVector.cpp + Recast/Tests_Alloc.cpp + Recast/Tests_Recast.cpp + Recast/Tests_RecastFilter.cpp + DetourCrowd/Tests_DetourPathCorridor.cpp +) set_property(TARGET Tests PROPERTY CXX_STANDARD 17) -add_dependencies(Tests Recast Detour) -target_link_libraries(Tests Recast Detour) +add_dependencies(Tests Recast Detour DetourCrowd) +target_link_libraries(Tests Recast Detour DetourCrowd) find_package(Catch2 QUIET) if (Catch2_FOUND) diff --git a/Tests/DetourCrowd/Tests_DetourPathCorridor.cpp b/Tests/DetourCrowd/Tests_DetourPathCorridor.cpp new file mode 100644 index 00000000..1c199cb3 --- /dev/null +++ b/Tests/DetourCrowd/Tests_DetourPathCorridor.cpp @@ -0,0 +1,119 @@ +#include "catch2/catch_all.hpp" + +#include "DetourPathCorridor.h" + +TEST_CASE("dtMergeCorridorStartMoved") +{ + SECTION("Should handle empty input") + { + dtPolyRef* const path = nullptr; + const int npath = 0; + const int maxPath = 0; + const dtPolyRef* const visited = nullptr; + const int nvisited = 0; + const int result = dtMergeCorridorStartMoved(path, npath, maxPath, visited, nvisited); + CHECK(result == 0); + } + + SECTION("Should handle empty visited") + { + dtPolyRef path[] = {1}; + const int npath = 1; + const int maxPath = 1; + const dtPolyRef* const visited = nullptr; + const int nvisited = 0; + const int result = dtMergeCorridorStartMoved(path, npath, maxPath, visited, nvisited); + CHECK(result == 1); + const dtPolyRef expectedPath[] = {1}; + CHECK_THAT(path, Catch::Matchers::RangeEquals(expectedPath)); + } + + SECTION("Should handle empty path") + { + dtPolyRef* const path = nullptr; + const int npath = 0; + const int maxPath = 0; + const dtPolyRef visited[] = {1}; + const int nvisited = 1; + const int result = dtMergeCorridorStartMoved(path, npath, maxPath, visited, nvisited); + CHECK(result == 0); + } + + SECTION("Should strip visited points from path except last") + { + dtPolyRef path[] = {1, 2}; + const int npath = 2; + const int maxPath = 2; + const dtPolyRef visited[] = {1, 2}; + const int nvisited = 2; + const int result = dtMergeCorridorStartMoved(path, npath, maxPath, visited, nvisited); + CHECK(result == 1); + const dtPolyRef expectedPath[] = {2, 2}; + CHECK_THAT(path, Catch::Matchers::RangeEquals(expectedPath)); + } + + SECTION("Should add visited points not present in path in reverse order") + { + dtPolyRef path[] = {1, 2, 0}; + const int npath = 2; + const int maxPath = 3; + const dtPolyRef visited[] = {1, 2, 3, 4}; + const int nvisited = 4; + const int result = dtMergeCorridorStartMoved(path, npath, maxPath, visited, nvisited); + CHECK(result == 3); + const dtPolyRef expectedPath[] = {4, 3, 2}; + CHECK_THAT(path, Catch::Matchers::RangeEquals(expectedPath)); + } + + SECTION("Should add visited points not present in path up to the path capacity") + { + dtPolyRef path[] = {1, 2, 0}; + const int npath = 2; + const int maxPath = 3; + const dtPolyRef visited[] = {1, 2, 3, 4, 5}; + const int nvisited = 5; + const int result = dtMergeCorridorStartMoved(path, npath, maxPath, visited, nvisited); + CHECK(result == 3); + const dtPolyRef expectedPath[] = {5, 4, 3}; + CHECK_THAT(path, Catch::Matchers::RangeEquals(expectedPath)); + } + + SECTION("Should not change path if there is no intersection with visited") + { + dtPolyRef path[] = {1, 2}; + const int npath = 2; + const int maxPath = 2; + const dtPolyRef visited[] = {3, 4}; + const int nvisited = 2; + const int result = dtMergeCorridorStartMoved(path, npath, maxPath, visited, nvisited); + CHECK(result == 2); + const dtPolyRef expectedPath[] = {1, 2}; + CHECK_THAT(path, Catch::Matchers::RangeEquals(expectedPath)); + } + + SECTION("Should save unvisited path points") + { + dtPolyRef path[] = {1, 2, 0}; + const int npath = 2; + const int maxPath = 3; + const dtPolyRef visited[] = {1, 3}; + const int nvisited = 2; + const int result = dtMergeCorridorStartMoved(path, npath, maxPath, visited, nvisited); + CHECK(result == 3); + const dtPolyRef expectedPath[] = {3, 1, 2}; + CHECK_THAT(path, Catch::Matchers::RangeEquals(expectedPath)); + } + + SECTION("Should save unvisited path points up to the path capacity") + { + dtPolyRef path[] = {1, 2}; + const int npath = 2; + const int maxPath = 2; + const dtPolyRef visited[] = {1, 3}; + const int nvisited = 2; + const int result = dtMergeCorridorStartMoved(path, npath, maxPath, visited, nvisited); + CHECK(result == 2); + const dtPolyRef expectedPath[] = {3, 1}; + CHECK_THAT(path, Catch::Matchers::RangeEquals(expectedPath)); + } +}