diff --git a/.ci/build-linux-aarch64.sh b/.ci/build-linux-aarch64.sh index f53a24d249..e067f23445 100755 --- a/.ci/build-linux-aarch64.sh +++ b/.ci/build-linux-aarch64.sh @@ -43,8 +43,8 @@ cmake .. \ -DOpenGL_GL_PREFERENCE=LEGACY \ -DLLVM_DIR=/opt/llvm/lib/cmake/llvm \ -DSTATIC_LINK_LLVM=ON \ - -DBUILD_RPCS3_TESTS=ON \ - -DRUN_RPCS3_TESTS=ON \ + -DBUILD_RPCS3_TESTS="${RUN_UNIT_TESTS}" \ + -DRUN_RPCS3_TESTS="${RUN_UNIT_TESTS}" \ -G Ninja ninja; build_status=$?; diff --git a/.ci/build-linux.sh b/.ci/build-linux.sh index f44efea2a4..4d9e9d0d09 100755 --- a/.ci/build-linux.sh +++ b/.ci/build-linux.sh @@ -54,8 +54,8 @@ cmake .. \ -DOpenGL_GL_PREFERENCE=LEGACY \ -DLLVM_DIR=/opt/llvm/lib/cmake/llvm \ -DSTATIC_LINK_LLVM=ON \ - -DBUILD_RPCS3_TESTS=ON \ - -DRUN_RPCS3_TESTS=ON \ + -DBUILD_RPCS3_TESTS="${RUN_UNIT_TESTS}" \ + -DRUN_RPCS3_TESTS="${RUN_UNIT_TESTS}" \ -G Ninja ninja; build_status=$?; diff --git a/.ci/docker.env b/.ci/docker.env index 2b36fb34c0..ee037bfb4d 100644 --- a/.ci/docker.env +++ b/.ci/docker.env @@ -8,6 +8,7 @@ BUILD_SOURCEBRANCHNAME APPDIR ARTDIR RELEASE_MESSAGE +RUN_UNIT_TESTS # Variables for build matrix COMPILER DEPLOY_APPIMAGE diff --git a/.github/workflows/rpcs3.yml b/.github/workflows/rpcs3.yml index 986bc715f5..2f68adefd5 100644 --- a/.github/workflows/rpcs3.yml +++ b/.github/workflows/rpcs3.yml @@ -56,6 +56,7 @@ jobs: COMPILER: ${{ matrix.compiler }} UPLOAD_COMMIT_HASH: ${{ matrix.UPLOAD_COMMIT_HASH }} UPLOAD_REPO_FULL_NAME: ${{ matrix.UPLOAD_REPO_FULL_NAME }} + RUN_UNIT_TESTS: github.event_name == 'pull_request' && 'ON' || 'OFF' steps: - name: Checkout repository uses: actions/checkout@main @@ -132,6 +133,12 @@ jobs: with: fetch-depth: 0 + - name: Setup NuGet + uses: nuget/setup-nuget@v2 + + - name: Restore NuGet packages + run: nuget restore rpcs3.sln + - name: Setup env shell: pwsh run: | @@ -171,7 +178,12 @@ jobs: - name: Compile RPCS3 shell: pwsh - run: msbuild rpcs3.sln /p:Configuration=Release /v:minimal /p:Platform=x64 /p:CLToolPath=${{ env.CCACHE_BIN_DIR }} /p:UseMultiToolTask=true /p:CustomAfterMicrosoftCommonTargets="${{ github.workspace }}\buildfiles\msvc\ci_only.targets" + run: msbuild rpcs3.sln /p:Configuration=Release /v:minimal /p:Platform=x64 /p:PreferredToolArchitecture=x64 /p:CLToolPath=${{ env.CCACHE_BIN_DIR }} /p:UseMultiToolTask=true /p:CustomAfterMicrosoftCommonTargets="${{ github.workspace }}\buildfiles\msvc\ci_only.targets" + + - name: Run Unit Tests + if: github.event_name == 'pull_request' + shell: pwsh + run: build\lib\Release-x64\rpcs3_test.exe - name: Pack up build artifacts run: | diff --git a/3rdparty/FAudio b/3rdparty/FAudio index 091c6b4693..6077ea740a 160000 --- a/3rdparty/FAudio +++ b/3rdparty/FAudio @@ -1 +1 @@ -Subproject commit 091c6b4693ce507ac48037836a5a884e35cd2860 +Subproject commit 6077ea740a7114a54f76ed9b7abe08cffc0034b6 diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index a826f6acf9..727bee8cae 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -67,8 +67,8 @@ if (NOT ANDROID) PUBLIC 3rdparty::stblib 3rdparty::libevdev - PRIVATE rpcs3_emu + PRIVATE rpcs3_ui 3rdparty::discordRPC 3rdparty::qt6 @@ -187,9 +187,7 @@ if (NOT ANDROID) endif() # Unit tests -if(BUILD_RPCS3_TESTS AND CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_C_COMPILER_ID STREQUAL "GNU") - message(STATUS "FIXME: Unit tests are currently not linking with GCC") -elseif(BUILD_RPCS3_TESTS) +if(BUILD_RPCS3_TESTS) enable_testing() find_package(GTest REQUIRED) @@ -201,6 +199,7 @@ elseif(BUILD_RPCS3_TESTS) PRIVATE tests/test.cpp tests/test_fmt.cpp + tests/test_simple_array.cpp ) target_link_libraries(rpcs3_test diff --git a/rpcs3/Emu/RSX/Common/simple_array.hpp b/rpcs3/Emu/RSX/Common/simple_array.hpp index 08bb97cb86..dfec324eeb 100644 --- a/rpcs3/Emu/RSX/Common/simple_array.hpp +++ b/rpcs3/Emu/RSX/Common/simple_array.hpp @@ -23,9 +23,9 @@ namespace rsx Ty* _data = _local_capacity ? reinterpret_cast(_local_storage) : nullptr; u32 _size = 0; - inline u64 offset(const_iterator pos) + inline u32 offset(const_iterator pos) { - return (_data) ? u64(pos - _data) : 0ull; + return (_data) ? u32(pos - _data) : 0u; } bool is_local_storage() const diff --git a/rpcs3/tests/rpcs3_test.vcxproj b/rpcs3/tests/rpcs3_test.vcxproj index 928a7b5663..05ca115d7f 100644 --- a/rpcs3/tests/rpcs3_test.vcxproj +++ b/rpcs3/tests/rpcs3_test.vcxproj @@ -10,6 +10,9 @@ x64 + + false + {d1cbf84e-07f8-4acb-9cd2-bd205fdeee1e} Application @@ -37,6 +40,7 @@ + false X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) Level3 ProgramDatabase @@ -59,6 +63,7 @@ Disabled + false X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) Level3 $(IntDir) @@ -77,12 +82,13 @@ - + - + + @@ -95,4 +101,4 @@ - \ No newline at end of file + diff --git a/rpcs3/tests/test_simple_array.cpp b/rpcs3/tests/test_simple_array.cpp new file mode 100644 index 0000000000..f64e01200e --- /dev/null +++ b/rpcs3/tests/test_simple_array.cpp @@ -0,0 +1,192 @@ +#include + +#define private public +#include "Emu/RSX/Common/simple_array.hpp" +#undef private + +namespace rsx +{ + TEST(SimpleArray, DefaultConstructor) + { + rsx::simple_array arr; + + EXPECT_TRUE(arr.empty()); + EXPECT_EQ(arr.size(), 0); + EXPECT_GE(arr.capacity(), 1u); + } + + TEST(SimpleArray, InitialSizeConstructor) + { + rsx::simple_array arr(5); + + EXPECT_FALSE(arr.empty()); + EXPECT_EQ(arr.size(), 5); + EXPECT_GE(arr.capacity(), 5u); + } + + TEST(SimpleArray, InitialSizeValueConstructor) + { + rsx::simple_array arr(3, 42); + + EXPECT_EQ(arr.size(), 3); + for (int i = 0; i < 3; ++i) + { + EXPECT_EQ(arr[i], 42); + } + } + + TEST(SimpleArray, InitializerListConstructor) + { + rsx::simple_array arr{ 1, 2, 3, 4, 5 }; + + EXPECT_EQ(arr.size(), 5); + for (int i = 0; i < 5; ++i) + { + EXPECT_EQ(arr[i], i + 1); + } + } + + TEST(SimpleArray, CopyConstructor) + { + rsx::simple_array arr1{ 1, 2, 3 }; + rsx::simple_array arr2(arr1); + + EXPECT_EQ(arr1.size(), arr2.size()); + for (u32 i = 0; i < arr1.size(); ++i) + { + EXPECT_EQ(arr1[i], arr2[i]); + } + } + + TEST(SimpleArray, MoveConstructor) + { + rsx::simple_array arr1{ 1, 2, 3 }; + u32 original_size = arr1.size(); + rsx::simple_array arr2(std::move(arr1)); + + EXPECT_EQ(arr2.size(), original_size); + EXPECT_TRUE(arr1.empty()); + } + + TEST(SimpleArray, PushBackAndAccess) + { + rsx::simple_array arr; + arr.push_back(1); + arr.push_back(2); + arr.push_back(3); + + EXPECT_EQ(arr.size(), 3); + EXPECT_EQ(arr[0], 1); + EXPECT_EQ(arr[1], 2); + EXPECT_EQ(arr[2], 3); + EXPECT_EQ(arr.front(), 1); + EXPECT_EQ(arr.back(), 3); + } + + TEST(SimpleArray, PopBack) + { + rsx::simple_array arr{ 1, 2, 3 }; + + EXPECT_EQ(arr.pop_back(), 3); + EXPECT_EQ(arr.size(), 2); + EXPECT_EQ(arr.back(), 2); + } + + TEST(SimpleArray, Insert) + { + rsx::simple_array arr{ 1, 3, 4 }; + auto it = arr.insert(arr.begin() + 1, 2); + + EXPECT_EQ(*it, 2); + EXPECT_EQ(arr.size(), 4); + + for (int i = 0; i < 4; ++i) + { + EXPECT_EQ(arr[i], i + 1); + } + } + + TEST(SimpleArray, Clear) + { + rsx::simple_array arr{ 1, 2, 3 }; + arr.clear(); + + EXPECT_TRUE(arr.empty()); + EXPECT_EQ(arr.size(), 0); + } + + TEST(SimpleArray, SmallBufferOptimization) + { + // Test with a small type that should use stack storage + rsx::simple_array small_arr(3, 'a'); + EXPECT_TRUE(small_arr.is_local_storage()); + + // Test with a larger type or more elements that should use heap storage + struct LargeType { char data[128]; }; + rsx::simple_array large_arr(10); + EXPECT_FALSE(large_arr.is_local_storage()); + } + + TEST(SimpleArray, Iterator) + { + rsx::simple_array arr{ 1, 2, 3, 4, 5 }; + int sum = 0; + for (const auto& val : arr) + { + sum += val; + } + + EXPECT_EQ(sum, 15); + } + + TEST(SimpleArray, EraseIf) + { + rsx::simple_array arr{ 1, 2, 3, 4, 5 }; + bool modified = arr.erase_if([](const int& val) { return val % 2 == 0; }); + arr.sort(FN(x < y)); + + EXPECT_TRUE(modified); + EXPECT_EQ(arr.size(), 3); + EXPECT_EQ(arr[0], 1); + EXPECT_EQ(arr[1], 3); + EXPECT_EQ(arr[2], 5); + } + + TEST(SimpleArray, Map) + { + rsx::simple_array arr{ 1, 2, 3 }; + auto result = arr.map([](const int& val) { return val * 2; }); + + EXPECT_EQ(result.size(), 3); + EXPECT_EQ(result[0], 2); + EXPECT_EQ(result[1], 4); + EXPECT_EQ(result[2], 6); + } + + TEST(SimpleArray, Reduce) + { + rsx::simple_array arr{ 1, 2, 3, 4, 5 }; + int sum = arr.reduce(0, [](const int& acc, const int& val) { return acc + val; }); + + EXPECT_EQ(sum, 15); + } + + TEST(SimpleArray, Any) + { + rsx::simple_array arr{ 1, 2, 3, 4, 5 }; + + EXPECT_TRUE(arr.any([](const int& val) { return val > 3; })); + EXPECT_FALSE(arr.any([](const int& val) { return val > 5; })); + } + + TEST(SimpleArray, Sort) + { + rsx::simple_array arr{ 5, 3, 1, 4, 2 }; + arr.sort([](const int& a, const int& b) { return a < b; }); + + for (u32 i = 0; i < arr.size(); ++i) + { + EXPECT_EQ(arr[i], i + 1); + } + } +}