diff --git a/.github/workflows/cibuild.yml b/.github/workflows/cibuild.yml index a03b5a26420..1e1e61bdf98 100644 --- a/.github/workflows/cibuild.yml +++ b/.github/workflows/cibuild.yml @@ -113,6 +113,10 @@ jobs: CXX: ${{ matrix.CXX }} run: cmake --build build --config ${{ matrix.Configuration }} --parallel $(nproc || echo 4) + - name: Run CTest + working-directory: build + run: ctest --parallel $(nproc || echo 4) + - name: Make package if: ${{ steps.cmake-build.outcome == 'success' }} id: make-package @@ -171,6 +175,10 @@ jobs: shell: alpine.sh {0} run: cmake --build build --config ${{ matrix.Configuration }} --parallel $(nproc || echo 4) + - name: Run CTest + shell: alpine.sh {0} + run: ctest --parallel $(nproc || echo 4) + build-macos: name: macOS ${{ matrix.Configuration }} ${{ matrix.Platform }} runs-on: macos-latest @@ -197,3 +205,6 @@ jobs: - name: Run CMake Build run: cmake --build build --config ${{ matrix.Configuration }} --parallel $(sysctl -n hw.ncpu || echo 4) + + - name: Run CTest + run: ctest --parallel $(sysctl -n hw.ncpu || echo 4) diff --git a/.gitmodules b/.gitmodules index d653b46d1ba..62beff6839d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -46,3 +46,7 @@ [submodule "Externals/xrLuaFix"] path = Externals/xrLuaFix url = https://github.com/OpenXRay/xrLuaFix.git +[submodule "Externals/doctest"] + path = Externals/doctest + url = https://github.com/doctest/doctest.git + branch = master diff --git a/CMakeLists.txt b/CMakeLists.txt index b24593b8b1e..35ea73bba57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,6 +298,13 @@ add_subdirectory(src) add_subdirectory(res) add_subdirectory(misc) +# Tests +option(BUILD_TESTS "Build tests" ON) +if (BUILD_TESTS) + include(CTest) + add_subdirectory(tests) +endif() + get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) if ("${LIB64}" STREQUAL "TRUE") diff --git a/Externals/CMakeLists.txt b/Externals/CMakeLists.txt index 6ee73375534..738f1cda7ff 100644 --- a/Externals/CMakeLists.txt +++ b/Externals/CMakeLists.txt @@ -23,3 +23,5 @@ if (NOT TARGET xrLuabind) "Read the build instructions: https://github.com/OpenXRay/xray-16/wiki" ) endif() + +add_subdirectory(doctest EXCLUDE_FROM_ALL) diff --git a/Externals/doctest b/Externals/doctest new file mode 160000 index 00000000000..ae7a13539fb --- /dev/null +++ b/Externals/doctest @@ -0,0 +1 @@ +Subproject commit ae7a13539fb71f270b87eb2e874fbac80bc8dda2 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 00000000000..bef9148cd2f --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(xrCore) diff --git a/tests/xrCore/CMakeLists.txt b/tests/xrCore/CMakeLists.txt new file mode 100644 index 00000000000..a2fd296c839 --- /dev/null +++ b/tests/xrCore/CMakeLists.txt @@ -0,0 +1,9 @@ + +add_executable( + xrCoreTests + main.cpp + xr_ini_test.cpp) + +target_link_libraries(xrCoreTests xrCore doctest::doctest) +target_include_directories(xrCoreTests PRIVATE "${CMAKE_SOURCE_DIR}/src") +add_test(NAME xrCoreTests COMMAND xrCoreTests) diff --git a/tests/xrCore/main.cpp b/tests/xrCore/main.cpp new file mode 100644 index 00000000000..fec512c36de --- /dev/null +++ b/tests/xrCore/main.cpp @@ -0,0 +1,17 @@ +#define DOCTEST_CONFIG_IMPLEMENT +#include + +#include +#include + +int main(int argc, char** argv) +{ + doctest::Context context; + + context.applyCommandLine(argc, argv); + + // Initialize memory + Memory._initialize(); + + return context.run(); +} diff --git a/tests/xrCore/xr_ini_test.cpp b/tests/xrCore/xr_ini_test.cpp new file mode 100644 index 00000000000..0c4d7291c05 --- /dev/null +++ b/tests/xrCore/xr_ini_test.cpp @@ -0,0 +1,88 @@ +#include + +#include +#include +#include + +#include + +CInifile +read_from_string(pcstr str, + CInifile::allow_include_func_t allow_include = nullptr) { + IReader reader = IReader(const_cast(str), xr_strlen(str)); + return CInifile(&reader, "test.ini", allow_include); +} + +TEST_CASE("parse empty file") { + CInifile ini = read_from_string(""); + + CHECK_EQ(ini.section_count(), 0); +} + +TEST_CASE("parse empty section") { + CInifile ini = read_from_string("[a]"); + + CHECK_EQ(ini.section_count(), 1); + CHECK_UNARY(ini.section_exist("a")); +} + +TEST_CASE("parse simple section") { + CInifile ini = read_from_string( + R"ini( +[a] +key = value +)ini"); + + CHECK_UNARY(ini.section_exist("a")); + CHECK_UNARY(ini.line_exist("a", "key")); + CHECK_EQ(xr_strcmp(ini.read("a", "key"), "value"), 0); +} + +TEST_CASE("parse integer value") { + CInifile ini = read_from_string( + R"ini( +[a] +key = 123 +)ini"); + + CHECK_UNARY(ini.section_exist("a")); + CHECK_UNARY(ini.line_exist("a", "key")); + CHECK_EQ(ini.read("a", "key"), 123); +} + +TEST_CASE("Parse float value") { + CInifile ini = read_from_string( + R"ini( +[a] +key = 123.456 +)ini"); + + CHECK_UNARY(ini.section_exist("a")); + CHECK_UNARY(ini.line_exist("a", "key")); + CHECK_EQ(ini.read("a", "key"), 123.456f); +} + +TEST_CASE("Parse quoted value") { + CInifile ini = read_from_string( + R"ini( +[a] +key = "value" +)ini"); + + CHECK_UNARY(ini.section_exist("a")); + CHECK_UNARY(ini.line_exist("a", "key")); + CHECK_EQ(xr_strcmp(ini.read("a", "key"), "\"value\""), 0); +} + +TEST_CASE("Parse multiline value") { + CInifile ini = read_from_string( + R"ini( +[a] +key = "multiline +value" +)ini"); + + CHECK_UNARY(ini.section_exist("a")); + CHECK_UNARY(ini.line_exist("a", "key")); + CHECK_EQ(xr_strcmp(ini.read("a", "key"), "\"multiline\r\nvalue\""), 0); +}