From 2a98519451b49e3efe15a72b2b91a27d4792c6d2 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Tue, 25 Apr 2023 22:26:29 +0200 Subject: [PATCH] initial conversion to cxxopts for mwiniimporter clang-format clang-format again add cxxopts to cmake and 3 oses use version and not tag for cxxopts add the include dir for windows maybe add the include dir for windows maybe: part 2 give _DIR a try and point to cmake dir try prefix path add FindCXXOPTS.cmake slim down findcxxopts remove boost stuff from mwiiniimporter cmake; set include path in windows one too many S add support for fetching formatting validated that we need MaybeQuotedPath naive attempt to use vcpkg remove findCXXOPTS.cmake naive attempt to use vcpkg more cleanup; make use of cxxopts::cxxopts remove offending bad line try to integration the cxxopts install via vcpkg add vcpkg.cmake toolchain file use the right path? go the fetch route for windows fetch cxxopts workaround make use of CONFIG and also put in TODO add code coverage fix clang-format fix clang-format again add some tooling for tests const params and use order of operations allow to be run from anywhere appease the jvoisin u8 all the things make sure we can run on all systems; but require that it run in the same directory as the binary we wish to test give CLI11 a try get things building on windows too give this a try... clean-format fix1 clean-format fix2 clang-format fix3 do not check if file already exists; overwrite existing try to abstract out _wsystem and std::system appease the clang-format gods purge cli11 bring back tests --- .gitlab-ci.yml | 1 + CI/before_script.linux.sh | 2 + CI/before_script.msvc.sh | 1 + CMakeLists.txt | 7 +- apps/mwiniimporter_tests/CMakeLists.txt | 26 ++++++ apps/mwiniimporter_tests/main.cpp | 113 ++++++++++++++++++++++++ 6 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 apps/mwiniimporter_tests/CMakeLists.txt create mode 100644 apps/mwiniimporter_tests/main.cpp diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 63f5bfb45e..1e4e58fd6a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -72,6 +72,7 @@ Ubuntu_GCC_preprocess: - cmake --install . - if [[ "${BUILD_TESTS_ONLY}" ]]; then ./openmw_test_suite --gtest_output="xml:openmw_tests.xml"; fi - if [[ "${BUILD_TESTS_ONLY}" ]]; then ./openmw-cs-tests --gtest_output="xml:openmw_cs_tests.xml"; fi + - if [[ "${BUILD_TESTS_ONLY}" ]]; then ./openmw-iniimporter-tests --gtest_output="xml:openmw_iniimporter_tests.xml"; fi - if [[ "${BUILD_TESTS_ONLY}" && ! "${BUILD_WITH_CODE_COVERAGE}" ]]; then ./openmw_detournavigator_navmeshtilescache_benchmark; fi - if [[ "${BUILD_TESTS_ONLY}" && ! "${BUILD_WITH_CODE_COVERAGE}" ]]; then ./openmw_esm_refid_benchmark; fi - if [[ "${BUILD_TESTS_ONLY}" && ! "${BUILD_WITH_CODE_COVERAGE}" ]]; then ./openmw_settings_access_benchmark; fi diff --git a/CI/before_script.linux.sh b/CI/before_script.linux.sh index 0edd38628f..2a5a33d841 100755 --- a/CI/before_script.linux.sh +++ b/CI/before_script.linux.sh @@ -49,6 +49,7 @@ if [[ $CI_CLANG_TIDY ]]; then -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--warnings-as-errors=*" -DBUILD_UNITTESTS=ON -DBUILD_OPENCS_TESTS=ON + -DBUILD_TOOL_TESTS=ON -DBUILD_BENCHMARKS=ON ) fi @@ -105,6 +106,7 @@ if [[ "${BUILD_TESTS_ONLY}" ]]; then -DBUILD_NIFTEST=OFF \ -DBUILD_UNITTESTS=${BUILD_UNITTESTS} \ -DBUILD_OPENCS_TESTS=${BUILD_UNITTESTS} \ + -DBUILD_TOOL_TESTS=${BUILD_UNITTESTS} \ -DBUILD_BENCHMARKS=${BUILD_BENCHMARKS} \ .. elif [[ "${BUILD_OPENMW_ONLY}" ]]; then diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index e11ceb499d..83c3acd187 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -1119,6 +1119,7 @@ fi if [ -n "${TEST_FRAMEWORK}" ]; then add_cmake_opts -DBUILD_UNITTESTS=ON add_cmake_opts -DBUILD_OPENCS_TESTS=ON + add_cmake_opts -DBUILD_TOOL_TESTS=ON fi if [ -n "$ACTIVATE_MSVC" ]; then diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ea891b56d..d0c919a892 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ option(BUILD_BENCHMARKS "Build benchmarks with Google Benchmark" OFF) option(BUILD_NAVMESHTOOL "Build navmesh tool" ON) option(BUILD_BULLETOBJECTTOOL "Build Bullet object tool" ON) option(BUILD_OPENCS_TESTS "Build OpenMW Construction Set tests" OFF) +option(BUILD_TOOL_TESTS "Build OpenMW related tool tests" OFF) set(OpenGL_GL_PREFERENCE LEGACY) # Use LEGACY as we use GL2; GLNVD is for GL3 and up. @@ -633,7 +634,7 @@ if (BUILD_LAUNCHER) add_subdirectory( apps/launcher ) endif() -if (BUILD_MWINIIMPORTER) +if (BUILD_MWINIIMPORTER OR BUILD_TOOL_TESTS) add_subdirectory( apps/mwiniimporter ) endif() @@ -674,6 +675,10 @@ if (BUILD_OPENCS_TESTS) add_subdirectory(apps/opencs_tests) endif() +if (BUILD_TOOL_TESTS) + add_subdirectory( apps/mwiniimporter_tests ) +endif() + if (WIN32) if (MSVC) foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} ) diff --git a/apps/mwiniimporter_tests/CMakeLists.txt b/apps/mwiniimporter_tests/CMakeLists.txt new file mode 100644 index 0000000000..6692c6021d --- /dev/null +++ b/apps/mwiniimporter_tests/CMakeLists.txt @@ -0,0 +1,26 @@ +file(GLOB INIIMPORTER_TESTS_SRC_FILES + main.cpp +) + +source_group(apps\\openmw-iniimporter-tests FILES ${INIIMPORTER_TESTS_SRC_FILES}) + +openmw_add_executable(openmw-iniimporter-tests ${INIIMPORTER_TESTS_SRC_FILES}) + +target_include_directories(openmw-iniimporter-tests SYSTEM PRIVATE ${GTEST_INCLUDE_DIRS}) +target_include_directories(openmw-iniimporter-tests SYSTEM PRIVATE ${GMOCK_INCLUDE_DIRS}) + +target_link_libraries(openmw-iniimporter-tests PRIVATE + GTest::GTest + GMock::GMock +) + +if (BUILD_WITH_CODE_COVERAGE) + target_compile_options(openmw-iniimporter-tests PRIVATE --coverage) + target_link_libraries(openmw-iniimporter-tests PRIVATE gcov) +endif() + +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC) + target_precompile_headers(openmw-iniimporter-tests PRIVATE + + ) +endif() diff --git a/apps/mwiniimporter_tests/main.cpp b/apps/mwiniimporter_tests/main.cpp new file mode 100644 index 0000000000..2c40db293d --- /dev/null +++ b/apps/mwiniimporter_tests/main.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#elif defined(__APPLE__) +#include +#else +#include +#endif + +std::filesystem::path getExecutablePath() +{ +#ifdef _WIN32 + WCHAR buffer[MAX_PATH]; + GetModuleFileNameW(NULL, buffer, MAX_PATH); + std::wstring exe_path(buffer); + return std::filesystem::path(exe_path).parent_path(); +#elif defined(__APPLE__) + char buffer[PATH_MAX]; + uint32_t bufsize = sizeof(buffer); + _NSGetExecutablePath(buffer, &bufsize); + return std::filesystem::path(buffer).parent_path(); +#else + char buffer[PATH_MAX]; + ssize_t len = ::readlink("/proc/self/exe", buffer, sizeof(buffer) - 1); + if (len == -1) + { + throw std::runtime_error("Could not retrieve executable path"); + } + buffer[len] = '\0'; + std::string exe_path(buffer); + return std::filesystem::path(exe_path).parent_path(); +#endif +} + +int runBinary( + const std::filesystem::path& binaryPath, const std::filesystem::path& iniPath, const std::filesystem::path& cfgPath) +{ +#ifdef _WIN32 + std::wstring wBinaryPath = binaryPath.native(); + std::wstring wIniPath = iniPath.native(); + std::wstring wCfgPath = cfgPath.native(); + std::wstringstream cmd; + cmd << wBinaryPath << L" -i " << wIniPath << L" -c " << wCfgPath; + return _wsystem(cmd.str().c_str()); +#else + std::stringstream cmd; + cmd << binaryPath << " -i " << iniPath << " -c " << cfgPath; + return std::system(cmd.str().c_str()); +#endif +} + +struct TestParam +{ + std::string name; + std::string fileName; +}; + +const std::vector testParams = { { "ascii", "ascii" }, { "unicode", "(╯°□°)╯︵ ┻━┻" }, { "emoji", "💩" } }; + +class IniImporterTest : public ::testing::TestWithParam +{ +}; + +TEST_P(IniImporterTest, TestIniImport) +{ + auto const& param = IniImporterTest::GetParam(); + + // Create temporary file + std::string iniData = R"([Archives] +Archive 0=game1.bsa +Archive 1=game2.bsa +)"; + std::filesystem::path tempIniFile = std::filesystem::temp_directory_path() / (param.fileName + ".ini"); + std::ofstream tempFile(tempIniFile); + tempFile << iniData; + tempFile.close(); + std::filesystem::path tempCfgFile = std::filesystem::temp_directory_path() / (param.fileName + ".cfg"); + std::filesystem::path binaryPath = getExecutablePath() / "openmw-iniimporter"; + + int ret = runBinary(binaryPath, tempIniFile, tempCfgFile); + ASSERT_EQ(ret, 0); + + // Verify the cfg file was created and has the expected contents + std::ifstream ifs(tempCfgFile); + ASSERT_TRUE(ifs.good()); + + std::string cfgData = R"(fallback-archive=Morrowind.bsa +fallback-archive=game1.bsa +fallback-archive=game2.bsa +)"; + + std::stringstream actual; + actual << ifs.rdbuf(); + + ASSERT_EQ(cfgData, actual.str()); + + // Clean up temporary file + std::filesystem::remove(tempCfgFile); + std::filesystem::remove(tempIniFile); +} + +INSTANTIATE_TEST_SUITE_P(IniImporterTests, IniImporterTest, ::testing::ValuesIn(testParams)); + +int main(int argc, char* argv[]) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file