diff --git a/.github/workflows/ci_action.yml b/.github/workflows/ci_action.yml index c031b9e..f1017d8 100644 --- a/.github/workflows/ci_action.yml +++ b/.github/workflows/ci_action.yml @@ -22,7 +22,7 @@ jobs: BUILD_DIR: ${{ github.workspace }}\build steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: List Workspace run: dir /a ${{ github.workspace }} - name: Compile @@ -30,7 +30,7 @@ jobs: echo "== CMAKE VERSION ==" cmake --version echo "== CMAKE CONFIGURE ==" - cmake -B${{env.BUILD_DIR}} -DCLOVE_CMAKE__UC_BUILD=true + cmake -B${{env.BUILD_DIR}} -DCLOVE_CMAKE__UC_BUILD=ON echo "== CMAKE BUILD ==" cmake --build ${{env.BUILD_DIR}} --config Release - name: List Build @@ -53,7 +53,7 @@ jobs: BUILD_DIR: ${{ github.workspace }}/build steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: List Workspace run: ls -la ${{ github.workspace }} - name: Compile @@ -61,7 +61,7 @@ jobs: echo "== CMAKE VERSION ==" cmake --version echo "== CMAKE CONFIGURE ==" - cmake -B${{env.BUILD_DIR}} -DCLOVE_CMAKE__UC_BUILD=true + cmake -B${{env.BUILD_DIR}} -DCLOVE_CMAKE__UC_BUILD=ON echo "== CMAKE BUILD ==" cmake --build ${{env.BUILD_DIR}} --config Release - name: List Build @@ -73,19 +73,19 @@ jobs: cd ${{ github.workspace }} build_ubuntu: name: Build ubuntu_${{matrix.compiler.c}}-${{matrix.compiler.v}} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: compiler: - - {c: gcc, cpp: g++, v: 11, strict: false} - - {c: gcc, cpp: g++, v: 12, strict: false} - - {c: gcc, cpp: g++, v: 13, strict: true} - - {c: clang, cpp: clang++, v: 13, strict: true} - - {c: clang, cpp: clang++, v: 14, strict: true} - - {c: clang, cpp: clang++, v: 15, strict: true} - - {c: clang, cpp: clang++, v: 16, strict: true} - - {c: clang, cpp: clang++, v: 17, strict: true} + - {c: gcc, cpp: g++, v: 11, strict: OFF} + - {c: gcc, cpp: g++, v: 12, strict: OFF} + - {c: gcc, cpp: g++, v: 13, strict: ON} + - {c: clang, cpp: clang++, v: 13, strict: ON} + - {c: clang, cpp: clang++, v: 14, strict: ON} + - {c: clang, cpp: clang++, v: 15, strict: ON} + - {c: clang, cpp: clang++, v: 16, strict: ON} + - {c: clang, cpp: clang++, v: 17, strict: ON} defaults: run: shell: bash @@ -93,7 +93,7 @@ jobs: BUILD_DIR: ${{ github.workspace }}/build steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: List Workspace run: ls -la ${{ github.workspace }} - name: Install Clang (if needed) @@ -102,20 +102,30 @@ jobs: with: version: "${{ matrix.compiler.v }}" env: true # set CC / CXX variable + - name: Install GCC (if needed) + # Installing GCC-13 due to regression introduced in ubuntu 22.04 image + # https://github.com/actions/runner-images/issues/9866 + if: ${{ matrix.compiler.c == 'gcc' && matrix.compiler.v == 13 }} + run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y + sudo apt-get update -y + sudo apt-get install gcc-13 + sudo apt-get install g++-13 - name: Set Compiler # only if CC / CXX are not already set from new installation run: | if [ -z "${CC}" ]; then echo "CC=${{matrix.compiler.c}}-${{matrix.compiler.v}}" >> "$GITHUB_ENV" echo "CXX=${{matrix.compiler.cpp}}-${{matrix.compiler.v}}" >> "$GITHUB_ENV" + else + echo CC=$CC + echo CXX=$CXX fi - echo CC=$CC - echo CXX=$CXX - name: Compile run: | echo "== CMAKE VERSION ==" cmake --version echo "== CMAKE CONFIGURE ==" - cmake -B${{env.BUILD_DIR}} -DCLOVE_CMAKE__UC_BUILD=true -DCLOVE_CMAKE__CPP_STRICT_WARN_AS_ERROR=${{matrix.compiler.strict}} + cmake -B${{env.BUILD_DIR}} -DCLOVE_CMAKE__UC_BUILD=ON -DCLOVE_CMAKE__CPP_STRICT_WARN_AS_ERROR=${{matrix.compiler.strict}} echo "== CMAKE BUILD ==" cmake --build ${{env.BUILD_DIR}} --config Release - name: List Build @@ -135,7 +145,7 @@ jobs: BUILD_DIR: ${{ github.workspace }}/build steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: List Workspace run: ls -la ${{ github.workspace }} - name: Compile @@ -143,7 +153,7 @@ jobs: echo "== CMAKE VERSION ==" cmake --version echo "== CMAKE CONFIGURE ==" - cmake -B${{env.BUILD_DIR}} -DCLOVE_CMAKE__UC_SANITY=true + cmake -B${{env.BUILD_DIR}} -DCLOVE_CMAKE__UC_SANITY=ON echo "== CMAKE BUILD ==" cmake --build ${{env.BUILD_DIR}} --config Release - name: List Build diff --git a/.github/workflows/release_action.yml b/.github/workflows/release_action.yml index 8235ab2..5e9a8e2 100644 --- a/.github/workflows/release_action.yml +++ b/.github/workflows/release_action.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Upload Release Asset id: upload-release-asset uses: actions/upload-release-asset@v1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 632888c..9afcf3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,33 +1,105 @@ cmake_minimum_required(VERSION 3.18) -project(CLoveUnit LANGUAGES C) -include(CTest) -#[[ -add_subdirectory(tests/functs) -if (DEFINED CLOVE_CMAKE__CI_TRIGGERED) - add_subdirectory(tests/stricts/clove-c) - add_subdirectory(tests/stricts/clove-cpp) - add_subdirectory(examples/clove101) - add_subdirectory(examples/clovepp) -endif() +set(CLOVE_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) +list(INSERT CMAKE_MODULE_PATH 0 ${CLOVE_SOURCE_DIR}/cmake/modules) -if (DEFINED CLOVE_CMAKE__ENABLE_PERFS) -add_subdirectory(tests/perfs) -endif() -]] +include(CLoveModules) +clove_get_version(CLOVE_VERSION) + +# Configure Project +project( + CLoveUnit + VERSION ${CLOVE_VERSION} + DESCRIPTION "Single-header Unit Testing framework for C (interoperable with C++) with test autodiscovery feature" + HOMEPAGE_URL "https://github.com/fdefelici/clove-unit" + LANGUAGES C +) + +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +# Eventually CMAKE_INSTALL_PREFIX can be overridden by the user to change base installation path for the package +clove_join_paths(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" clove-unit ${PROJECT_VERSION}) + +# Library Target definition and configuration +add_library(clove-unit INTERFACE) +add_library(clove-unit::clove-unit ALIAS clove-unit) + +target_include_directories( + clove-unit INTERFACE + $ + $ +) + +target_compile_features(clove-unit INTERFACE c_std_11) + +# Install command stuffs for enabling find_package usage +install( + TARGETS clove-unit + EXPORT clove-unit-targets + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) -if (CLOVE_CMAKE__UC_BUILD) +write_basic_package_version_file( + clove-unit-config-version.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) + +configure_package_config_file( + ${CLOVE_SOURCE_DIR}/cmake/in/clove-unit-config.cmake.in + clove-unit-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/cmake +) + +install( + FILES ${CLOVE_SOURCE_DIR}/clove-unit.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + +install( + FILES + ${PROJECT_BINARY_DIR}/clove-unit-config.cmake + ${PROJECT_BINARY_DIR}/clove-unit-config-version.cmake + DESTINATION ${CMAKE_INSTALL_PREFIX}/cmake +) + +install( + EXPORT clove-unit-targets + #NAMESPACE clove-unit:: + DESTINATION ${CMAKE_INSTALL_PREFIX}/cmake +) + +export(PACKAGE clove-unit) + + +#[[ + In case this is the root project add dev targets (Development mode). + To avoid targets pollution when using FetchContent were only the target library is required + Note: PROJECT_IS_TOP_LEVEL cmake variable exists in version 3.21+ +]] +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + include(CTest) + + option(CLOVE_CMAKE__UC_BUILD "enable build use case" OFF) + option(CLOVE_CMAKE__UC_SANITY "enable sanity check use case" OFF) + option(CLOVE_CMAKE__UC_PERFS "enable performance test use case" OFF) + option(CLOVE_CMAKE__CPP_STRICT_WARN_AS_ERROR "threat compilation warning as error" OFF) + + if (CLOVE_CMAKE__UC_BUILD) add_subdirectory(tests/functs) add_subdirectory(tests/stricts/clove-c) add_subdirectory(tests/stricts/clove-cpp) add_subdirectory(examples/clove101) add_subdirectory(examples/clovepp) -endif() + endif() -if (CLOVE_CMAKE__UC_SANITY) + if (CLOVE_CMAKE__UC_SANITY) add_subdirectory(tests/stricts/clove-sanity) -endif() + endif() -if (CLOVE_CMAKE__UC_PERFS) + if (CLOVE_CMAKE__UC_PERFS) add_subdirectory(tests/perfs) + endif() + endif() diff --git a/README.md b/README.md index 2371d60..e1c17e7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# CLove-Unit · [![version](https://img.shields.io/github/v/release/fdefelici/clove-unit?label=latest&sort=semver)](./clove-unit.h) [![workflow](https://img.shields.io/github/actions/workflow/status/fdefelici/clove-unit/ci_action.yml)](https://github.com/fdefelici/clove-unit/actions/workflows/ci_action.yml) [![conan](https://img.shields.io/badge/conan-available-blueviolet)](https://conan.io/center/recipes/clove-unit) [![Discord channel](https://img.shields.io/discord/1167864219190964255?logo=discord&logoColor=violet)](https://discord.gg/Mjx4YRQfFt) +# CLove-Unit · [![version](https://img.shields.io/github/v/release/fdefelici/clove-unit?label=latest&sort=semver)](./clove-unit.h) [![workflow](https://img.shields.io/github/actions/workflow/status/fdefelici/clove-unit/ci_action.yml)](https://github.com/fdefelici/clove-unit/actions/workflows/ci_action.yml) [![conan](https://img.shields.io/conan/v/clove-unit)](https://conan.io/center/recipes/clove-unit) [![Discord channel](https://img.shields.io/discord/1167864219190964255?logo=discord&logoColor=violet)](https://discord.gg/Mjx4YRQfFt) `CLove-Unit` is a single-header unit testing library designed for C (compatible with C++). @@ -19,7 +19,7 @@ Consider also supporting `CLove-Unit` development becoming a [**sponsor**](https * [Features](#features) * [IDE Extensions](#ide-extensions) -* [Supported Package Managers](#supported-package-managers) +* [How to Integrate](#how-to-integrate) * [How It Works](#how-it-works) * [Getting Started](#getting-started) * [Programming API](#programming-api) @@ -48,11 +48,88 @@ For those who prefer a UI oriented test executor, `CLove-Unit` is supported on t Have a look and enjoy ;-) -## Supported Package Managers +## How to Integrate -`CLove-Unit` is also available on the following Package Managers: +`CLove-Unit` can be imported in your project in the following ways: +- Sourcing the header file +- Using a Package Manager +- Using CMake -* [Conan](https://conan.io/center/recipes/clove-unit) +### Sourcing the Header file +Being an header-only library, you can just download [clove-unit.h](./clove-unit.h) file and include it in your project. + +```c +#include "clove-unit.h" +``` + +Then remember to properly configure your compiler include paths. + +### Using a Package Manager +`CLove-Unit` is currently available on the following Package Managers: + +* [Conan](https://conan.io): read [here](https://conan.io/center/recipes/clove-unit) for details on how to import it. + +### Using CMake +In case you still need dependency management, but you want to avoid Package Manager configuration complexity, you can use standard mechansim provided by `CMake` such as [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html), [add_subdirectory](https://cmake.org/cmake/help/latest/command/add_subdirectory.html) and [find_package](https://cmake.org/cmake/help/latest/command/find_package.html). + +> NOTE: CMake library is named `clove-unit` + +Here a few examples: + +* **FetchContent** + + ```cmake + cmake_minimum_required(VERSION 3.18) + project(TestProject C) + + Include(FetchContent) + FetchContent_Declare( + clove-unit + GIT_REPOSITORY https://github.com/fdefelici/clove-unit.git + GIT_TAG master # or eventually any branch, tag or commit sha + ) + FetchContent_MakeAvailable(clove-unit) + + add_executable(tests ) + target_link_libraries(tests clove-unit) + ``` + +* **add_subdirectory** + + First download `CLove-Unit` repository and then point properly to it like this: + + ```cmake + cmake_minimum_required(VERSION 3.18) + project(TestProject C) + + add_subdirectory() + + add_executable(tests ) + target_link_libraries(tests clove-unit) + ``` + +* **find_package** + + First download `CLove-Unit` repository and then run cmake install command on it. + + Package will be installed in at following path: `/clove-unit/` + + Eventually you may want to customize [CMAKE_INSTALL_PREFIX](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html) variable to override cmake default installation path for packages. + + + Then use the package as follow: + ```cmake + cmake_minimum_required(VERSION 3.18) + project(TestProject C) + + find_package(clove-unit REQUIRED PATHS ) + + # or more strict + # find_package(clove-unit EXACT REQUIRED PATHS ) + + add_executable(tests ) + target_link_libraries(tests clove-unit) + ``` ## How It Works @@ -236,10 +313,10 @@ Assertions that can be used within a `CLOVE_TEST` definition. Helper APIs to support test implementation. -| API | Description | -|--------------------------|------------------------------------------------------------| -| `CLOVE_EXEC_PATH()` | Macro to easily retrieve executable path as a `char*` | -| `CLOVE_EXEC_BASE_PATH()` | Macro to easily retrieve executable base path as a `char*` | +| API | Description | +|--------------------------|---------------------------------------------------------------------------| +| `CLOVE_EXEC_PATH()` | Macro to easily retrieve executable absolute path as a `const char*` | +| `CLOVE_EXEC_BASE_PATH()` | Macro to easily retrieve executable absolute base path as a `const char*` | ## Command-Line API diff --git a/clove-unit.h b/clove-unit.h index a88008d..dd01157 100644 --- a/clove-unit.h +++ b/clove-unit.h @@ -1,6 +1,6 @@ /* * clove-unit - * v2.4.4 + * v2.4.5 * Single-Header Unit Testing library for C/C++ * https://github.com/fdefelici/clove-unit * @@ -10,8 +10,8 @@ #define __CLOVE_VERSION_MAJOR 2 #define __CLOVE_VERSION_MINOR 4 -#define __CLOVE_VERSION_PATCH 4 -#define __CLOVE_VERSION "2.4.4" +#define __CLOVE_VERSION_PATCH 5 +#define __CLOVE_VERSION "2.4.5" //Preventing "unknown-pragmas" warning on GCC <= 12 for '#pragma region' usage //NOTE1: GCC and G++ v13+ support '#pragma region' by the way. @@ -43,10 +43,10 @@ #include __CLOVE_EXTERN_C void __clove_utils_empty_funct(void); -extern char* __clove_exec_path; -extern char* __clove_exec_base_path; -__CLOVE_EXTERN_C const char* __clove_get_exec_base_path(void); -__CLOVE_EXTERN_C const char* __clove_get_exec_path(void); +extern char* __clove_exec_abs_path; +extern char* __clove_exec_abs_basepath; +__CLOVE_EXTERN_C const char* __clove_utils_get_exec_abs_path(void); +__CLOVE_EXTERN_C const char* __clove_utils_get_exec_abs_basepath(void); //Switch implementation for pointer types #define __CLOVE_SWITCH_BEG(X) \ @@ -84,12 +84,15 @@ __CLOVE_EXTERN_C double __clove_math_decimald(unsigned char precision); #define __CLOVE_PATH_SEPARATOR_STR "/" #endif //_WIN32 -__CLOVE_EXTERN_C char* __clove_path_concat(const char separator, const char* path1, const char* path2); +__CLOVE_EXTERN_C char* __clove_path_concat(const char* path1, const char* path2, const char separator); __CLOVE_EXTERN_C const char* __clove_path_relative(const char* abs_path, const char* base_path); __CLOVE_EXTERN_C char* __clove_path_rel_to_abs_exec_path(const char* rel_path); __CLOVE_EXTERN_C bool __clove_path_is_relative(const char* path); +__CLOVE_EXTERN_C bool __clove_path_is_absolute(const char* path); __CLOVE_EXTERN_C void __clove_path_to_os(char* path); __CLOVE_EXTERN_C char* __clove_path_basepath(const char* path); +__CLOVE_EXTERN_C bool __clove_path_exists(const char* path); +__CLOVE_EXTERN_C char* __clove_path_to_absolute(const char* path); #pragma endregion // Path Decl #pragma region PRIVATE - Memory Decl @@ -98,6 +101,7 @@ __CLOVE_EXTERN_C void* __clove_memory_calloc(size_t size); __CLOVE_EXTERN_C void* __clove_memory_realloc(void* source, size_t size); __CLOVE_EXTERN_C bool __clove_memory_memcpy(void* dest, size_t dest_size, const void* src, size_t src_size); __CLOVE_EXTERN_C bool __clove_memory_memset(void* dest, size_t size, unsigned char value); +__CLOVE_EXTERN_C void __clove_memory_free(void* source); #define __CLOVE_MEMORY_MALLOC_TYPE_N(TYPE, COUNT) (TYPE*)__clove_memory_malloc(sizeof(TYPE) * COUNT) #define __CLOVE_MEMORY_MALLOC_TYPE(TYPE) __CLOVE_MEMORY_MALLOC_TYPE_N(TYPE, 1) @@ -146,6 +150,7 @@ __CLOVE_EXTERN_C char* __clove_string_csv_escape(const char* string); __CLOVE_EXTERN_C void __clove_string_ellipse(const char* string, size_t str_len, size_t pos, char* out, size_t out_size); __CLOVE_EXTERN_C void __clove_string_replace_char(char* path, char find, char replace); __CLOVE_EXTERN_C void __clove_string_pad_right(char* dest, size_t dest_size, size_t str_target_len); +__CLOVE_EXTERN_C int __clove_string_last_indexof(const char* source, char character); #pragma endregion // String Decl #pragma region PRIVATE - String View Decl @@ -862,13 +867,14 @@ __CLOVE_EXTERN_C void __clove_exec_suite(__clove_suite_t* suite, size_t test_cou #include void __clove_utils_empty_funct(void) { } -const char* __clove_get_exec_base_path(void) { - return __clove_exec_base_path; +const char* __clove_utils_get_exec_abs_path(void) { + return __clove_exec_abs_path; } -const char* __clove_get_exec_path(void) { - return __clove_exec_path; +const char* __clove_utils_get_exec_abs_basepath(void) { + return __clove_exec_abs_basepath; } + #pragma endregion // Utils Impl #pragma region PRIVATE - Math Impl @@ -896,7 +902,16 @@ double __clove_math_decimald(unsigned char precision) { #include #include #include -char* __clove_path_concat(const char separator, const char* path1, const char* path2) { +#include +#include + +#ifdef _WIN32 + #define __CLOVE_PATH_MAX_LEN _MAX_PATH +#else + #define __CLOVE_PATH_MAX_LEN PATH_MAX +#endif //_WIN32 + +char* __clove_path_concat(const char* path1, const char* path2, const char separator) { size_t count = __clove_string_length(path1) + 1 + __clove_string_length(path2) + 1; char* path = __CLOVE_MEMORY_CALLOC_TYPE_N(char, count); @@ -922,42 +937,109 @@ const char* __clove_path_relative(const char* abs_path, const char* base_path) { } char* __clove_path_rel_to_abs_exec_path(const char* rel_path) { - const char* base_path = __clove_get_exec_base_path(); - char* abs_path = __clove_path_concat(__CLOVE_PATH_SEPARATOR, base_path, rel_path); + const char* base_path = __clove_utils_get_exec_abs_basepath(); + char* abs_path = __clove_path_concat(base_path, rel_path, __CLOVE_PATH_SEPARATOR); return abs_path; } bool __clove_path_is_relative(const char* path) { - if (__clove_string_startswith(path, "\\")) return false; //windows - if (__clove_string_length(path) > 2 && path[1] == ':') return false; //windows + if (__clove_string_startswith(path, "\\")) return false; //windows (match the main unit) + if (__clove_string_length(path) > 2 && path[1] == ':') return false; //windows (contains unit:) if (__clove_string_startswith(path, "/")) return false; //unix or Windows return true; } +bool __clove_path_is_absolute(const char* path) { + return !__clove_path_is_relative(path); +} + void __clove_path_to_os(char* path) { __clove_string_replace_char(path, '/', __CLOVE_PATH_SEPARATOR); __clove_string_replace_char(path, '\\', __CLOVE_PATH_SEPARATOR); } -char* __clove_path_basepath(const char* a_path) { - // Find the last path separator character in the input path. - const char* last_char = a_path + __clove_string_length(a_path) - 1; - while (last_char > a_path && *last_char != '/' && *last_char != '\\') { - --last_char; - } +char* __clove_path_basepath(const char* path) { + char temp_path[__CLOVE_PATH_MAX_LEN]; + __clove_string_strcpy(temp_path, sizeof(temp_path), path); + //Remove last path separator character if any + bool last_char_is_win = __clove_string_endswith(path, "\\"); + bool last_char_is_uni = __clove_string_endswith(path, "/"); + if (last_char_is_win || last_char_is_uni) { + size_t last_index = __clove_string_length(temp_path) - 1; + temp_path[last_index] = '\0'; + } + + // Find the last path separator character in the input path. + int last_char_win = __clove_string_last_indexof(temp_path, '\\'); + int last_char_uni = __clove_string_last_indexof(temp_path, '/'); //or unix or win eventually + int last_char_index = last_char_win > last_char_uni ? last_char_win : last_char_uni; + // If there are no separators in the path, return the current directory path. - if (last_char == a_path) { + char* result = NULL; + if (last_char_index < 0) { static char dot_path[3] = { '.', __CLOVE_PATH_SEPARATOR, '\0' }; - return __clove_string_strdup(dot_path); + result = __clove_string_strdup(dot_path); + } else { + // Calculate base path length based on the position of the last path separator. + size_t base_length = (size_t)(last_char_index + 1); + char* base_path = __CLOVE_MEMORY_CALLOC_TYPE_N(char, base_length); + __clove_string_strncpy(base_path, base_length, temp_path, base_length - 1); + __clove_path_to_os(base_path); + result = base_path; } - // Calculate base path length based on the position of the last path separator. - size_t base_length = last_char - a_path; - char* base_path = __CLOVE_MEMORY_CALLOC_TYPE_N(char, base_length + 1); - __clove_string_strncpy(base_path, base_length + 1, a_path, base_length); - __clove_path_to_os(base_path); - return base_path; + return result; +} + +bool __clove_path_exists(const char* path) { + struct stat buffer; + return stat(path, &buffer) == 0; +} + +char* __clove_path_to_absolute(const char* rel_path) { + char* result = NULL; +#if _WIN32 + result = __CLOVE_MEMORY_MALLOC_TYPE_N(char, _MAX_PATH); + //if( _fullpath( full, partialPath, _MAX_PATH ) != NULL ) + _fullpath(result, rel_path, _MAX_PATH ); +#else + result = __CLOVE_MEMORY_MALLOC_TYPE_N(char, PATH_MAX); + if (__clove_path_exists(rel_path)) { + realpath(rel_path, result); // NULL + } else { + if (__clove_path_is_absolute(rel_path)) { + __clove_string_strcpy(result, PATH_MAX, rel_path); + } else { //relative + realpath(".", result); //getcwd + if (!__clove_string_endswith(result, "/")) { + __clove_string_strcat(result, PATH_MAX, "/"); + } + if (__clove_string_startswith(rel_path, "./")) { + rel_path = rel_path + 2; + } + + __clove_string_strcat(result, PATH_MAX, rel_path); + } + } + +/* + //case where rel_path not really exists on fs + //(in this case only the first subpath of the rel_path is added by realpath) + if (!__clove_string_endswith(result, rel_path)) { + if (__clove_path_is_absolute(rel_path)) { + __clove_string_strcpy(result, PATH_MAX, rel_path); + } else { //relative + realpath(".", result); + if (!__clove_string_endswith(result, "/")) { + __clove_string_strcat(result, PATH_MAX, "/"); + } + __clove_string_strcat(result, PATH_MAX, rel_path); + } + } +*/ +#endif + return result; } #pragma endregion // Path Impl @@ -1043,6 +1125,12 @@ bool __clove_memory_memcpy(void* dest, size_t dest_size, const void* src, size_t bool __clove_memory_memset(void* dest, size_t size, unsigned char value) { return memset(dest, value, size) != NULL; } + +void __clove_memory_free(void* source) +{ + free(source); +} + #pragma endregion //Memory Impl #pragma region PRIVATE - String Impl @@ -1340,6 +1428,13 @@ void __clove_string_pad_right(char* dest, size_t dest_size, size_t str_target_le __clove_memory_memset(pad_beg , pad_len, '.'); *pad_end = '\0'; } + +int __clove_string_last_indexof(const char* source, char character) { + const char* char_ptr = strrchr(source, character); + if (char_ptr == NULL) return -1; + return (int)(char_ptr - source); +} + #pragma endregion //String Impl #pragma region PRIVATE - String View Impl @@ -1545,7 +1640,7 @@ size_t __clove_stack_pop(__clove_stack_t* stack) { void __clove_stack_free(__clove_stack_t* stack) { if (!stack) return; - free(stack->items); + __clove_memory_free(stack->items); stack->items = NULL; stack->capacity = 0; stack->count = 0; @@ -1651,12 +1746,12 @@ void __clove_vector_free(__clove_vector_t* vector) { } if (vector->items) { - free(vector->items); + __clove_memory_free(vector->items); vector->items = NULL; } if (vector->swap_temp) { - free(vector->swap_temp); + __clove_memory_free(vector->swap_temp); vector->swap_temp = NULL; } vector->capacity = 0; @@ -1794,18 +1889,18 @@ void __clove_map_free(__clove_map_t* map) { while(current) { __clove_map_node_t* next = current->next; - free(current->key); + __clove_memory_free(current->key); if (map->item_dtor) { //if dtor set, means map become owner of the item (and its memory) map->item_dtor(current->value); - free(current->value); + __clove_memory_free(current->value); } - free(current); + __clove_memory_free(current); current = next; } } - free(map->hashmap); + __clove_memory_free(map->hashmap); map->hashmap = NULL; map->hashmap_size = 0; map->count = 0; @@ -2073,7 +2168,7 @@ __clove_cmdline_errno_t __clove_cmdline_handle_run_tests(__clove_cmdline_t* cmd) stream->free(stream); __clove_vector_free(&includes); __clove_vector_free(&excludes); - free(base_path_fixed); + __clove_memory_free(base_path_fixed); //Result if (run_result == 1) return __CLOVE_CMD_ERRNO_GENERIC; @@ -2158,7 +2253,7 @@ __clove_cmdline_errno_t __clove_cmdline_handle_list_tests(__clove_cmdline_t* cmd report->free(report); stream->free(stream); - free(base_path_os); + __clove_memory_free(base_path_os); __clove_vector_free(&context.suites); __clove_vector_free((__clove_vector_t*)context.includes); __clove_vector_free((__clove_vector_t*)context.excludes); @@ -2209,12 +2304,12 @@ void __clove_vector_test_ctor(void* test) { void __clove_vector_test_dtor(void* test_ptr) { __clove_test_t* test = (__clove_test_t*)test_ptr; - free(test->name); + __clove_memory_free(test->name); //See CLOVE_STRING_EQ and CLOVE_STRING_NE where string allocation happens if (test->result == __CLOVE_TEST_RESULT_FAILED && test->issue.data_type == __CLOVE_GENERIC_STRING) { - free(test->issue.expected._string); - free(test->issue.actual._string); + __clove_memory_free(test->issue.expected._string); + __clove_memory_free(test->issue.actual._string); } } #pragma endregion @@ -2243,7 +2338,7 @@ void __clove_vector_suite_ctor(void* suite_ptr) { void __clove_vector_suite_dtor(void* suite_ptr) { __clove_suite_t* suite = (__clove_suite_t*)suite_ptr; - free(suite->name); + __clove_memory_free(suite->name); __clove_vector_free(&suite->tests); } #pragma endregion // Suite Impl @@ -2448,7 +2543,7 @@ bool __clove_stream_console_has_ansi_support(__clove_stream_t* stream) { void __clove_stream_console_free(__clove_stream_t* stream) { - free(stream); + __clove_memory_free(stream); } __clove_stream_file_t* __clove_stream_file_new(const char* file_path) { @@ -2490,8 +2585,8 @@ bool __clove_stream_file_has_ansi_support(struct __clove_stream_t* _this) { void __clove_stream_file_free(__clove_stream_t* stream) { __clove_stream_file_t* _this = (__clove_stream_file_t*)stream; _this->file = NULL; - free((char*)_this->file_path); - free(_this); + __clove_memory_free((char*)_this->file_path); + __clove_memory_free(_this); } //In Memory Stream @@ -2538,7 +2633,7 @@ bool __clove_stream_memory_has_ansi_support(__clove_stream_t* stream) { void __clove_stream_memory_free(__clove_stream_t* stream) { __clove_vector_free(&((__clove_stream_memory_t*)stream)->lines); - free(stream); + __clove_memory_free(stream); } char* __clove_stream_memory_get_line(__clove_stream_memory_t* mem_stream, size_t index) { @@ -2623,7 +2718,7 @@ __clove_report_pretty_t* __clove_report_run_tests_pretty_new(__clove_stream_t* s } void __clove_report_pretty_free(__clove_report_t* report) { - free(report); + __clove_memory_free(report); } void __clove_report_pretty_start(__clove_report_t* _this, __clove_vector_t* suites, size_t test_count) { @@ -2846,8 +2941,8 @@ void __clove_report_pretty_end_test(__clove_report_t* _this, __clove_suite_t* su char* exp_escaped = __clove_string_escape(exp); char* act_escaped = __clove_string_escape(act); __clove_string_sprintf(msg, sizeof(msg), "%sexpected \"%s\" but was \"%s\"", non, exp_escaped, act_escaped); - free(exp_escaped); - free(act_escaped); + __clove_memory_free(exp_escaped); + __clove_memory_free(act_escaped); } else { char exp_short[16]; @@ -2857,8 +2952,8 @@ void __clove_report_pretty_end_test(__clove_report_t* _this, __clove_suite_t* su char* exp_escaped = __clove_string_escape(exp_short); char* act_escaped = __clove_string_escape(act_short); __clove_string_sprintf(msg, sizeof(msg), "%sexpected [%zu]\"%s\" but was [%zu]\"%s\"", non, exp_len, exp_escaped, act_len, act_escaped); - free(exp_escaped); - free(act_escaped); + __clove_memory_free(exp_escaped); + __clove_memory_free(act_escaped); } } __CLOVE_SWITCH_CASE(__CLOVE_GENERIC_PTR) { @@ -2941,7 +3036,7 @@ __clove_report_run_tests_csv_t* __clove_report_run_tests_csv_new(__clove_stream_ } void __clove_report_run_tests_csv_free(__clove_report_t* report) { - free(report); + __clove_memory_free(report); } void __clove_report_run_tests_csv_start(__clove_report_t* _this, __clove_vector_t* suites, size_t test_count) { @@ -3052,7 +3147,7 @@ void __clove_report_run_tests_csv_print_data(__clove_report_run_tests_csv_t* ins __CLOVE_SWITCH_CASE(__CLOVE_GENERIC_STRING) { char* escaped = __clove_string_csv_escape(data->_string); instance->stream->writef(instance->stream, "%s", escaped); - free(escaped); + __clove_memory_free(escaped); } __CLOVE_SWITCH_CASE(__CLOVE_GENERIC_PTR) instance->stream->writef(instance->stream, "%p", data->_ptr); @@ -3097,7 +3192,7 @@ __clove_report_json_t* __clove_report_run_tests_json_new(__clove_stream_t* strea void __clove_report_json_free(__clove_report_t* report) { __clove_report_json_t* instance = (__clove_report_json_t*)report; __clove_vector_free(&instance->cached_suites); - free(report); + __clove_memory_free(report); } void __clove_report_json_start(__clove_report_t* _this, __clove_vector_t* suites, size_t test_count) { @@ -3215,7 +3310,7 @@ void __clove_report_json_print_data(__clove_report_json_t* instance, __clove_tes __CLOVE_SWITCH_CASE(__CLOVE_GENERIC_STRING) { char* escaped = __clove_string_escape(data->_string); instance->stream->writef(instance->stream, "%s", escaped); - free(escaped); + __clove_memory_free(escaped); } __CLOVE_SWITCH_CASE(__CLOVE_GENERIC_PTR) instance->stream->writef(instance->stream, "%p", data->_ptr); @@ -3267,7 +3362,7 @@ void __clove_report_json_end_test(__clove_report_t* _this, __clove_suite_t* suit instance->stream->writef(instance->stream, "\t\t\t\t\"tests\" : {\n"); instance->suite_tests_counter = 0; - free(escaped_file); + __clove_memory_free(escaped_file); instance->is_first_suite_test = false; } @@ -3332,7 +3427,7 @@ __clove_report_list_tests_pretty_t* __clove_report_list_tests_pretty_new(__clove return _this; } void __clove_report_list_tests_pretty_free(__clove_report_list_tests_t* _this) { - free((__clove_report_list_tests_pretty_t*)_this); + __clove_memory_free((__clove_report_list_tests_pretty_t*)_this); } void __clove_report_list_tests_pretty_begin(__clove_report_list_tests_t* _this, size_t suite_count, size_t test_count) { __clove_report_list_tests_pretty_t* pretty = (__clove_report_list_tests_pretty_t*)_this; @@ -3399,7 +3494,7 @@ __clove_report_list_tests_csv_t* __clove_report_list_tests_csv_new(__clove_strea return _this; } void __clove_report_list_tests_csv_free(__clove_report_list_tests_t* _this) { - free((__clove_report_list_tests_csv_t*)_this); + __clove_memory_free((__clove_report_list_tests_csv_t*)_this); } void __clove_report_list_tests_csv_begin(__clove_report_list_tests_t* _this, size_t suite_count, size_t test_count) { __CLOVE_UNUSED_VAR(test_count); @@ -3460,7 +3555,7 @@ __clove_report_list_tests_json_t* __clove_report_list_tests_json_new(__clove_str return _this; } void __clove_report_list_tests_json_free(__clove_report_list_tests_t* _this) { - free((__clove_report_list_tests_json_t*)_this); + __clove_memory_free((__clove_report_list_tests_json_t*)_this); } void __clove_report_list_tests_json_begin(__clove_report_list_tests_t* _this, size_t suite_count, size_t test_count) { @@ -3516,7 +3611,7 @@ void __clove_report_list_tests_json_end_test(__clove_report_list_tests_t* _this, json->stream->writef(json->stream, "\t\t\t\t\"file\" : \"%s\",\n", escaped_file); json->stream->writef(json->stream, "\t\t\t\t\"tests\" : [\n"); - free(escaped_file); + __clove_memory_free(escaped_file); json->is_suite_first_test = false; } json->stream->writef(json->stream, "\t\t\t\t\t{\n"); @@ -3742,26 +3837,29 @@ int __clove_symbols_for_each_function_by_prefix(__clove_symbols_context_t* conte #include #include #include - typedef struct __clove_symbols_macos_module_t { void* handle; size_t size; //mmap handle size; intptr_t address; //module base address } __clove_symbols_macos_module_t; -intptr_t __clove_symbols_macos_image_slide(const char* path) -{ + +bool __clove_symbols_macos_image_slide(const char* abs_path, intptr_t* out_address) +{ + //NOTE: dyld image names are in absolute path. So tu properly compare, need to pass an abs_path to this function. for (uint32_t i = 0; i < _dyld_image_count(); i++) { - if (strcmp(_dyld_get_image_name(i), path) == 0) - return _dyld_get_image_vmaddr_slide(i); + if (strcmp(_dyld_get_image_name(i), abs_path) == 0) { + *out_address = _dyld_get_image_vmaddr_slide(i); + return true; + } } - return 0; + return false; } -int __clove_symbols_macos_open_module_handle(const char* module_path, __clove_symbols_macos_module_t* out_module) { +int __clove_symbols_macos_open_module_handle(const char* module_abs_path, __clove_symbols_macos_module_t* out_module) { int fd; - if ((fd = open(module_path, O_RDONLY)) < 0) { + if ((fd = open(module_abs_path, O_RDONLY)) < 0) { return 1; } @@ -3780,7 +3878,12 @@ int __clove_symbols_macos_open_module_handle(const char* module_path, __clove_sy out_module->handle = map; out_module->size = st.st_size; - out_module->address = __clove_symbols_macos_image_slide(module_path); + bool found = __clove_symbols_macos_image_slide(module_abs_path, &out_module->address); + if (!found) { + //TODO: add logging api like __clove_log_erro(frmt, args) + printf("[ERRO] cannot find image slide for: %s", module_abs_path); + return 4; + } return 0; } @@ -3801,7 +3904,7 @@ struct load_command* __clove_symbols_macos_find_command(struct mach_header_64* h } int __clove_symbols_for_each_function_by_prefix(__clove_symbols_context_t* context, __clove_symbols_function_action action) { - const char* module_path = __clove_exec_path; + const char* module_path = __clove_utils_get_exec_abs_path(); __clove_symbols_macos_module_t module; if (__clove_symbols_macos_open_module_handle(module_path, &module) != 0) { return 1; }; @@ -3964,7 +4067,7 @@ int __clove_symbols_funct_name_comparator(void* f1, void* f2) { } int __clove_symbols_for_each_function_by_prefix(__clove_symbols_context_t* context, __clove_symbols_function_action action) { - const char* module_path = __clove_exec_path; + const char* module_path = __clove_utils_get_exec_abs_path(); __clove_symbols_lixux_module_t module; if (__clove_symbols_lixux_open_module_handle(module_path, &module) != 0) { return 1; } @@ -4044,8 +4147,8 @@ int __clove_symbols_for_each_function_by_prefix(__clove_symbols_context_t* conte #pragma region PRIVATE - Run Impl #define __CLOVE_RUNNER_AUTO() \ -char* __clove_exec_path;\ -char* __clove_exec_base_path;\ +char* __clove_exec_abs_path;\ +char* __clove_exec_abs_basepath;\ __CLOVE_ASSERT_CHECK_E_DECL() \ __CLOVE_TEST_RESULT_E_DECL() \ __CLOVE_GENERIC_TYPE_E_DECL() \ @@ -4054,8 +4157,8 @@ int main(int argc, char* argv[]) {\ } int __clove_runner_auto(int argc, char* argv[]) { - __clove_exec_path = argv[0]; - __clove_exec_base_path = __clove_path_basepath(argv[0]); + __clove_exec_abs_path = __clove_path_to_absolute(argv[0]); + __clove_exec_abs_basepath = __clove_path_basepath(__clove_exec_abs_path); //argc = 5; //const char* argv2[] = {"exec", "-i", "*.ActShortThanExpForthCharDiff", "-r", "pretty"}; @@ -4083,7 +4186,8 @@ int __clove_runner_auto(int argc, char* argv[]) { __clove_vector_free(&cmd_handlers); __clove_cmdline_free(&cmdline); - free(__clove_exec_base_path); + __clove_memory_free(__clove_exec_abs_path); + __clove_memory_free(__clove_exec_abs_basepath); return cmd_result; } @@ -4175,13 +4279,13 @@ void __clove_exec_suite(__clove_suite_t* suite, size_t test_counter, size_t* pas #pragma region PUBLIC #pragma region PUBLIC - UTILS /* - * Provide the executable path + * Provide the executable absolute path */ -#define CLOVE_EXEC_PATH() __clove_get_exec_path() +#define CLOVE_EXEC_PATH() __clove_utils_get_exec_abs_path() /* - * Provide the executable base path + * Provide the executable absolute base path */ -#define CLOVE_EXEC_BASE_PATH() __clove_get_exec_base_path() +#define CLOVE_EXEC_BASE_PATH() __clove_utils_get_exec_abs_basepath() #pragma endregion //UTILS #pragma region PUBLIC - ASSERTS diff --git a/cmake/in/clove-unit-config.cmake.in b/cmake/in/clove-unit-config.cmake.in new file mode 100644 index 0000000..6d9ec93 --- /dev/null +++ b/cmake/in/clove-unit-config.cmake.in @@ -0,0 +1,5 @@ +@PACKAGE_INIT@ + +set(CLOVE_VERSION "@PROJECT_VERSION@") +include("${CMAKE_CURRENT_LIST_DIR}/clove-unit-targets.cmake") +check_required_components("@PROJECT_NAME@") \ No newline at end of file diff --git a/cmake/modules/CLoveModules.cmake b/cmake/modules/CLoveModules.cmake new file mode 100644 index 0000000..9be37d8 --- /dev/null +++ b/cmake/modules/CLoveModules.cmake @@ -0,0 +1,2 @@ +include(_ExtractVersion) +include(_JoinPaths) \ No newline at end of file diff --git a/cmake/modules/_ExtractVersion.cmake b/cmake/modules/_ExtractVersion.cmake new file mode 100644 index 0000000..0c099a3 --- /dev/null +++ b/cmake/modules/_ExtractVersion.cmake @@ -0,0 +1,9 @@ +# Extract clove version from clove-unit.h file +function(clove_get_version out_version) + set(CLOVE_VERSION_REGEX "#define __CLOVE_VERSION_.*[ \t]+(.+)") + file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/clove-unit.h" CLOVE_VERSION REGEX ${CLOVE_VERSION_REGEX}) + list(TRANSFORM CLOVE_VERSION REPLACE ${CLOVE_VERSION_REGEX} "\\1") + string(JOIN "." CLOVE_VERSION ${CLOVE_VERSION}) + set(${out_version} "${CLOVE_VERSION}" PARENT_SCOPE) +endfunction() + diff --git a/cmake/modules/_JoinPaths.cmake b/cmake/modules/_JoinPaths.cmake new file mode 100644 index 0000000..684032f --- /dev/null +++ b/cmake/modules/_JoinPaths.cmake @@ -0,0 +1,23 @@ +# This module provides function for joining paths +# known from most languages +# +# SPDX-License-Identifier: (MIT OR CC0-1.0) +# Copyright 2020 Jan Tojnar +# https://github.com/jtojnar/cmake-snips +# +# Modelled after Python’s os.path.join +# https://docs.python.org/3.7/library/os.path.html#os.path.join +# Windows not supported +function(clove_join_paths joined_path first_path_segment) + set(temp_path "${first_path_segment}") + foreach(current_segment IN LISTS ARGN) + if(NOT ("${current_segment}" STREQUAL "")) + if(IS_ABSOLUTE "${current_segment}") + set(temp_path "${current_segment}") + else() + set(temp_path "${temp_path}/${current_segment}") + endif() + endif() + endforeach() + set(${joined_path} "${temp_path}" PARENT_SCOPE) +endfunction() \ No newline at end of file diff --git a/tests/functs/src/inte/cmd_help_test.c b/tests/functs/src/inte/cmd_help_test.c index 1402d75..2eece8e 100644 --- a/tests/functs/src/inte/cmd_help_test.c +++ b/tests/functs/src/inte/cmd_help_test.c @@ -9,7 +9,7 @@ CLOVE_SUITE_SETUP() { } CLOVE_SUITE_TEARDOWN() { - if (cmd_out) free(cmd_out); + if (cmd_out) __clove_memory_free(cmd_out); } /* diff --git a/tests/functs/src/inte/cmd_invalid_test.c b/tests/functs/src/inte/cmd_invalid_test.c index 394be35..95cd768 100644 --- a/tests/functs/src/inte/cmd_invalid_test.c +++ b/tests/functs/src/inte/cmd_invalid_test.c @@ -9,7 +9,7 @@ CLOVE_SUITE_SETUP() { } CLOVE_SUITE_TEARDOWN() { - if (cmd_out) free(cmd_out); + if (cmd_out) __clove_memory_free(cmd_out); } //Note: Important for this unit test is to demostrate that with invalid params the process ends gracefully diff --git a/tests/functs/src/inte/cmd_run_test.c b/tests/functs/src/inte/cmd_run_test.c index 4f0cebc..5ddd269 100644 --- a/tests/functs/src/inte/cmd_run_test.c +++ b/tests/functs/src/inte/cmd_run_test.c @@ -13,39 +13,39 @@ CLOVE_SUITE_SETUP() { } CLOVE_SUITE_TEARDOWN() { - if (cmd_out) free(cmd_out); + if (cmd_out) __clove_memory_free(cmd_out); } CLOVE_TEST(JsonReportWithOptOonFile) { char* base_path = __clove_path_basepath(RES_PRJ01_EXEC_PATH); - char* report_path = __clove_path_concat(__CLOVE_PATH_SEPARATOR, base_path, "cmd_json_report.json"); - //file_delete(report_path); + char* report_path = __clove_path_concat(base_path, "cmd_json_report.json", __CLOVE_PATH_SEPARATOR); + //utils_file_delete(report_path); const char* cmd = cmd_fmt("\"%s\" -r json -o \"%s\"", RES_PRJ01_EXEC_PATH, report_path); int cmd_code = exec_cmd(cmd, &cmd_out); CLOVE_INT_EQ(__CLOVE_CMD_ERRNO_OK, cmd_code); - CLOVE_IS_TRUE(file_exists(report_path)); + CLOVE_IS_TRUE(utils_file_exists(report_path)); - file_delete(report_path); - free(base_path); - free(report_path); + utils_file_delete(report_path); + __clove_memory_free(base_path); + __clove_memory_free(report_path); } CLOVE_TEST(JsonReportWithOptOuputOnFile) { char* base_path = __clove_path_basepath(RES_PRJ01_EXEC_PATH); - char* report_path = __clove_path_concat(__CLOVE_PATH_SEPARATOR, base_path, "cmd_json_report.json"); - //file_delete(report_path); + char* report_path = __clove_path_concat(base_path, "cmd_json_report.json", __CLOVE_PATH_SEPARATOR); + //utils_file_delete(report_path); const char* cmd = cmd_fmt("\"%s\" -r json --output \"%s\"", RES_PRJ01_EXEC_PATH, report_path); int cmd_code = exec_cmd(cmd, &cmd_out); CLOVE_INT_EQ(__CLOVE_CMD_ERRNO_OK, cmd_code); - CLOVE_IS_TRUE(file_exists(report_path)); + CLOVE_IS_TRUE(utils_file_exists(report_path)); - file_delete(report_path); - free(base_path); - free(report_path); + utils_file_delete(report_path); + __clove_memory_free(base_path); + __clove_memory_free(report_path); } CLOVE_TEST(JsonReportWithOptOuputOnStdoutAsDefault) { @@ -216,18 +216,18 @@ CLOVE_TEST(DefaultReportIncludeOverExcludeOneTest) { CLOVE_TEST(DefaultReportWithOptOonFile) { char* base_path = __clove_path_basepath(RES_PRJ01_EXEC_PATH); - char* report_path = __clove_path_concat(__CLOVE_PATH_SEPARATOR, base_path, "cmd_console_report.txt"); - //file_delete(report_path); + char* report_path = __clove_path_concat(base_path, "cmd_console_report.txt", __CLOVE_PATH_SEPARATOR); + //utils_file_delete(report_path); const char* cmd = cmd_fmt("\"%s\" -o \"%s\"", RES_PRJ01_EXEC_PATH, report_path); int cmd_code = exec_cmd(cmd, &cmd_out); CLOVE_INT_EQ(__CLOVE_CMD_ERRNO_OK, cmd_code); - CLOVE_IS_TRUE(file_exists(report_path)); + CLOVE_IS_TRUE(utils_file_exists(report_path)); - file_delete(report_path); - free(base_path); - free(report_path); + utils_file_delete(report_path); + __clove_memory_free(base_path); + __clove_memory_free(report_path); } CLOVE_TEST(DefaultReportWithOptT) { diff --git a/tests/functs/src/inte/cmd_testlist_test.c b/tests/functs/src/inte/cmd_testlist_test.c index b9664d3..40d0b2c 100644 --- a/tests/functs/src/inte/cmd_testlist_test.c +++ b/tests/functs/src/inte/cmd_testlist_test.c @@ -9,7 +9,7 @@ CLOVE_SUITE_SETUP() { } CLOVE_SUITE_TEARDOWN() { - if (cmd_out) free(cmd_out); + if (cmd_out) __clove_memory_free(cmd_out); } /* diff --git a/tests/functs/src/inte/cmd_version_test.c b/tests/functs/src/inte/cmd_version_test.c index c2eb84b..a410136 100644 --- a/tests/functs/src/inte/cmd_version_test.c +++ b/tests/functs/src/inte/cmd_version_test.c @@ -9,7 +9,7 @@ CLOVE_SUITE_SETUP() { } CLOVE_SUITE_TEARDOWN() { - if (cmd_out) free(cmd_out); + if (cmd_out) __clove_memory_free(cmd_out); } CLOVE_TEST(RunVersionWithOptV) { diff --git a/tests/functs/src/unit/path_test.c b/tests/functs/src/unit/path_test.c index 64a10d2..f16a6f4 100644 --- a/tests/functs/src/unit/path_test.c +++ b/tests/functs/src/unit/path_test.c @@ -1,14 +1,15 @@ #define CLOVE_SUITE_NAME UNIT_PathTest -#include "clove-unit.h" +#include +#include "utils/utils.h" CLOVE_TEST(PathConcatenation) { - char* result = __clove_path_concat('/', "path/to/first", "second"); + char* result = __clove_path_concat("path/to/first", "second", '/'); CLOVE_ULLONG_EQ(20, __clove_string_length(result)); CLOVE_STRING_EQ("path/to/first/second", result); } CLOVE_TEST(PathConcatConvertingSeparator) { - char* result = __clove_path_concat('\\', "path/to/first", "second"); + char* result = __clove_path_concat("path/to/first", "second", '\\'); CLOVE_ULLONG_EQ(20, __clove_string_length(result)); CLOVE_STRING_EQ("path\\to\\first\\second", result); } @@ -17,8 +18,6 @@ CLOVE_TEST(AbsolutePathFromExecBasePath) { char* result = __clove_path_rel_to_abs_exec_path("path/to/append"); CLOVE_NOT_NULL(result); } -#include -#include CLOVE_TEST(BasePathForJustExecutable) { char expected[3] = { '.', __CLOVE_PATH_SEPARATOR, '\0' }; @@ -32,16 +31,16 @@ CLOVE_TEST(BasePathForFullPath) { char* result = __clove_path_basepath("/path/to/directory/file.txt"); CLOVE_STRING_EQ(expected, result); - free(result); + __clove_memory_free(result); } -CLOVE_TEST(BasePathForDirectory) { - char expected[] = "\\path\\to\\directory"; +CLOVE_TEST(BasePathForDirectoryEndingWithSlash) { + char expected[] = "\\path\\to"; __clove_path_to_os (expected); char* result = __clove_path_basepath("/path/to/directory/"); CLOVE_STRING_EQ(expected, result); - free(result); + __clove_memory_free(result); } CLOVE_TEST(PathToOs) { @@ -83,3 +82,47 @@ CLOVE_TEST(GetRelativePathFromAbsPath) { result = __clove_path_relative(abs_path, ""); CLOVE_STRING_EQ(abs_path, result); } + +CLOVE_TEST(ConvertUnexistentAbsToAbsolutePath) { + char* result = __clove_path_to_absolute("/abs/path/file.c"); + + #ifdef _WIN32 + const char* result_without_unit = result + 2; //e.g. c:\abs\path\file.c => \abs\path\file.c + CLOVE_STRING_EQ("\\abs\\path\\file.c", result_without_unit); + #else + CLOVE_STRING_EQ("/abs/path/file.c", result); + #endif + + __clove_memory_free(result); +} + +CLOVE_TEST(ConvertUnexistentRelToAbsolutePath) { + char* cwd_path = utils_cwd(); + char* abs_path = __clove_path_concat(cwd_path, "rel/path/file.c", __CLOVE_PATH_SEPARATOR); + + char* result = __clove_path_to_absolute("rel/path/file.c"); + CLOVE_STRING_EQ(abs_path, result); + + __clove_memory_free(result); + __clove_memory_free(cwd_path); + __clove_memory_free(abs_path); +} + +CLOVE_TEST(ConvertExistentRelToAbsolutePath) { + char* cwd_path = utils_cwd(); + char* abs_path = __clove_path_concat(cwd_path, "my/path", __CLOVE_PATH_SEPARATOR); + utils_mkdirs(abs_path); + + char* result = __clove_path_to_absolute("my/path"); + + CLOVE_STRING_EQ(abs_path, result); + + //rmdir + char* abs_path_parent = __clove_path_basepath(abs_path); + utils_rmdir(abs_path_parent); + + __clove_memory_free(result); + __clove_memory_free(cwd_path); + __clove_memory_free(abs_path); + __clove_memory_free(abs_path_parent); +} diff --git a/tests/functs/src/unit/report_csv_test.c b/tests/functs/src/unit/report_csv_test.c index 1124180..e7d55f8 100644 --- a/tests/functs/src/unit/report_csv_test.c +++ b/tests/functs/src/unit/report_csv_test.c @@ -1,7 +1,6 @@ #define CLOVE_SUITE_NAME UNIT_ReportCsvTest #include "clove-unit.h" #include "utils/utils.h" -#include "utils/domain_utils.h" static __clove_report_run_tests_csv_t* report; static __clove_stream_file_t* stream; @@ -32,7 +31,7 @@ CLOVE_TEST(EmptyReport) { base->end(base, 0, 0, 0); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "Suite,Test,Status,Duration,File,Line,Assert,Type,Expected,Actual\n" @@ -56,7 +55,7 @@ CLOVE_TEST(ReportOneSuiteWithOnePassedTest) { base->end(base, 1, 0, 0); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "Suite,Test,Status,Duration,File,Line,Assert,Type,Expected,Actual\n" @@ -80,7 +79,7 @@ CLOVE_TEST(ReportOneSuiteWithOneSkippedTest) { base->end(base, 0, 1, 0); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "Suite,Test,Status,Duration,File,Line,Assert,Type,Expected,Actual\n" @@ -107,7 +106,7 @@ CLOVE_TEST(ReportOneSuiteWithTwoTests) { base->end(base, 1, 0, 1); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "Suite,Test,Status,Duration,File,Line,Assert,Type,Expected,Actual\n" @@ -140,7 +139,7 @@ CLOVE_TEST(ReportTwoSuitesWithOnePassedTestEach) { base->end(base, 2, 0, 0); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "Suite,Test,Status,Duration,File,Line,Assert,Type,Expected,Actual\n" @@ -175,7 +174,7 @@ CLOVE_TEST(ReportOneSuiteWithOneTestFailedWithString) { base->end(base, 0, 0, 1); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "Suite,Test,Status,Duration,File,Line,Assert,Type,Expected,Actual\n" @@ -210,7 +209,7 @@ CLOVE_TEST(ReportOneSuiteWithOneTestFailedWithFail) { base->end(base, 0, 0, 1); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "Suite,Test,Status,Duration,File,Line,Assert,Type,Expected,Actual\n" diff --git a/tests/functs/src/unit/report_json_failed_test.c b/tests/functs/src/unit/report_json_failed_test.c index dcbb8c1..466f74f 100644 --- a/tests/functs/src/unit/report_json_failed_test.c +++ b/tests/functs/src/unit/report_json_failed_test.c @@ -1,7 +1,6 @@ #define CLOVE_SUITE_NAME UNIT_ReportJsonFailedTest #include "clove-unit.h" #include "utils/utils.h" -#include "utils/domain_utils.h" static __clove_report_json_t* report; static __clove_stream_file_t* stream; @@ -31,7 +30,7 @@ CLOVE_TEST(EmptyReport) { base->end(base, 0, 0, 0); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "{\n" @@ -66,7 +65,7 @@ CLOVE_TEST(ReportOneSuiteWithOnePassedTest) { base->end(base, 1, 0, 0); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "{\n" @@ -104,7 +103,7 @@ CLOVE_TEST(ReportOneSuiteWithTwoTests) { base->end(base, 1, 0, 1); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "{\n" diff --git a/tests/functs/src/unit/report_json_full_test.c b/tests/functs/src/unit/report_json_full_test.c index bdabb10..34452b0 100644 --- a/tests/functs/src/unit/report_json_full_test.c +++ b/tests/functs/src/unit/report_json_full_test.c @@ -1,7 +1,6 @@ #define CLOVE_SUITE_NAME UNIT_ReportJsonFullTest #include "clove-unit.h" #include "utils/utils.h" -#include "utils/domain_utils.h" static __clove_report_json_t* report; static __clove_stream_file_t* stream; @@ -29,7 +28,7 @@ CLOVE_TEST(EmptyReport) { base->end(base, 0, 0, 0); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "{\n" @@ -64,7 +63,7 @@ CLOVE_TEST(ReportOneSuiteWithOnePassedTest) { base->end(base, 1, 0, 0); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "{\n" @@ -107,7 +106,7 @@ CLOVE_TEST(ReportOneSuiteWithOneSkippedTest) { base->end(base, 0, 1, 0); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "{\n" @@ -154,7 +153,7 @@ CLOVE_TEST(ReportOneSuiteWithTwoTests) { base->end(base, 1, 0, 1); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "{\n" @@ -214,7 +213,7 @@ CLOVE_TEST(ReportTwoSuitesWithOnePassedTestEach) { base->end(base, 2, 0, 0); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "{\n" @@ -275,7 +274,7 @@ CLOVE_TEST(ReportOneSuiteWithOneFailAssertTest) { base->end(base, 0, 0, 1); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "{\n" @@ -332,7 +331,7 @@ CLOVE_TEST(ReportOneSuiteWithOneFailSizetAssertTest) { base->end(base, 0, 0, 1); const char* file_path = stream->file_path; - const char* actual = read_file(file_path); + const char* actual = utils_file_read(file_path); const char* expected = "{\n" diff --git a/tests/functs/src/unit/report_pretty_failures_test.c b/tests/functs/src/unit/report_pretty_failures_test.c index 44b1a6a..87b63c8 100644 --- a/tests/functs/src/unit/report_pretty_failures_test.c +++ b/tests/functs/src/unit/report_pretty_failures_test.c @@ -1,6 +1,6 @@ #define CLOVE_SUITE_NAME UNIT_ReportPrettyFailuresModeTest #include "clove-unit.h" -#include "utils/domain_utils.h" +#include "utils/utils.h" static __clove_report_pretty_t* report; static __clove_stream_memory_t* stream; diff --git a/tests/functs/src/unit/report_pretty_full_test.c b/tests/functs/src/unit/report_pretty_full_test.c index b510680..0be722b 100644 --- a/tests/functs/src/unit/report_pretty_full_test.c +++ b/tests/functs/src/unit/report_pretty_full_test.c @@ -1,6 +1,6 @@ #define CLOVE_SUITE_NAME UNIT_ReportPrettyTest #include "clove-unit.h" -#include "utils/domain_utils.h" +#include "utils/utils.h" static __clove_report_pretty_t* report; static __clove_stream_memory_t* stream; diff --git a/tests/functs/src/unit/report_pretty_skipped_test.c b/tests/functs/src/unit/report_pretty_skipped_test.c index 1aa5058..b762d95 100644 --- a/tests/functs/src/unit/report_pretty_skipped_test.c +++ b/tests/functs/src/unit/report_pretty_skipped_test.c @@ -1,6 +1,6 @@ #define CLOVE_SUITE_NAME UNIT_ReportPrettyDetailSkippedTest #include "clove-unit.h" -#include "utils/domain_utils.h" +#include "utils/utils.h" static __clove_report_pretty_t* report; static __clove_stream_memory_t* stream; diff --git a/tests/functs/src/unit/string_test.c b/tests/functs/src/unit/string_test.c index 9d87bbd..59f307c 100644 --- a/tests/functs/src/unit/string_test.c +++ b/tests/functs/src/unit/string_test.c @@ -27,7 +27,7 @@ CLOVE_TEST(StringEscaping) { const char* expected = "\\\"Hello\\nWorld\\\""; char* actual = __clove_string_escape(to_escape); CLOVE_STRING_EQ(expected, actual); - free(actual); + __clove_memory_free(actual); } CLOVE_TEST(StringStartsWith) { @@ -47,4 +47,11 @@ CLOVE_TEST(StringIsEqualsAny) { CLOVE_IS_FALSE(__clove_string_equal_any("mystring", 1, "one")); CLOVE_IS_TRUE(__clove_string_equal_any("mystring", 3, "one", "two", "mystring")); CLOVE_IS_FALSE(__clove_string_equal_any("mystring", 2, "one", "two")); +} + +CLOVE_TEST(StringLastIndexOf) { + CLOVE_INT_EQ(-1, __clove_string_last_indexof("hello_o", 'a')); + CLOVE_INT_EQ( 6, __clove_string_last_indexof("hello_o", 'o')); + CLOVE_INT_EQ( 3, __clove_string_last_indexof("hello_o", 'l')); + CLOVE_INT_EQ( 1, __clove_string_last_indexof("hello_o", 'e')); } \ No newline at end of file diff --git a/tests/functs/src/unit/stringview_test.c b/tests/functs/src/unit/stringview_test.c index de52ad2..b6a7a09 100644 --- a/tests/functs/src/unit/stringview_test.c +++ b/tests/functs/src/unit/stringview_test.c @@ -96,7 +96,7 @@ CLOVE_TEST(AsString) { char* result = __clove_string_view_as_string(&vw1); CLOVE_STRING_EQ("Hello", result); - free(result); + __clove_memory_free(result); } CLOVE_TEST(EndWithUsingOffsetOnSuffix) { diff --git a/tests/functs/src/utils/utils.c b/tests/functs/src/utils/cmd_utils.c similarity index 60% rename from tests/functs/src/utils/utils.c rename to tests/functs/src/utils/cmd_utils.c index fb3ce0b..aebefd7 100644 --- a/tests/functs/src/utils/utils.c +++ b/tests/functs/src/utils/cmd_utils.c @@ -1,15 +1,14 @@ -#include "utils.h" +#include "utils/cmd_utils.h" #include - #include #include #include #include #include -#include FILE* pipe_open(const char* cmd, const char* mode); int pipe_close(FILE* pipe); + #ifdef _WIN32 FILE* pipe_open(const char* cmd, const char* mode) { return _popen(cmd, mode); @@ -31,7 +30,7 @@ const char* cmd_fmt(const char* format, ...) { va_start(args, format); __clove_string_vsprintf(result, sizeof(result), format_ext, args); va_end(args); - free(format_ext); + __clove_memory_free(format_ext); return result; } #else @@ -93,69 +92,3 @@ int exec_cmd(const char* cmd, char** output) { int result_code = pipe_close(pipe); return result_code; } - -bool file_exists(const char* path) { - struct stat buffer; - return stat(path, &buffer) == 0; -} - -/* -bool file_exists(const char* path) { - FILE* file = __clove_file_open(path, "r"); - if (!file) return false; - fclose(file); - return true; -} - */ - -void file_delete(const char* path) { - if (file_exists(path)) - remove(path); -} - -//NOTE: Dangerous if in future will run test multithreaded -// Eventually improve with mutex or https://en.cppreference.com/w/c/atomic/atomic_flag -const char* str_fmt(const char* format, ...) { - static char result[1024]; - va_list args; - va_start(args, format); - __clove_string_vsprintf(result, sizeof(result), format, args); - va_end(args); - return result; -} - -void str_split(const char* str, char delim, __clove_vector_t* out_lines) { - __CLOVE_VECTOR_INIT(out_lines, char*); - char* source = __clove_string_strdup(str); - char delim_str[2] = {delim, '\0'}; - - #ifdef _WIN32 - char* context; - char *token = strtok_s(source, delim_str, &context); - #else - char *token = strtok(source, delim_str); - #endif //_WIN32 - - while (token != NULL) { - __CLOVE_VECTOR_ADD(out_lines, char*, token); - - #ifdef _WIN32 - token = strtok_s(NULL, delim_str, &context); - #else - token = strtok(NULL, delim_str); - #endif //_WIN32 - } -} - -char* read_file(const char* path) { - FILE* file = __clove_file_open(path, "rb"); - fseek(file, 0, SEEK_END); - size_t file_size = ftell(file); - rewind(file); - - char* result = (char*)malloc(file_size + 1); - result[file_size] = '\0'; - size_t bytes_read = fread(result, file_size, 1, file); - fclose(file); - return result; -} \ No newline at end of file diff --git a/tests/functs/src/utils/cmd_utils.h b/tests/functs/src/utils/cmd_utils.h new file mode 100644 index 0000000..5b3cc00 --- /dev/null +++ b/tests/functs/src/utils/cmd_utils.h @@ -0,0 +1,3 @@ +#pragma once +int exec_cmd(const char* cmd, char** output); +const char* cmd_fmt(const char* format, ...); diff --git a/tests/functs/src/utils/domain_utils.c b/tests/functs/src/utils/domain_utils.c index 1f7ec57..a2fbc15 100644 --- a/tests/functs/src/utils/domain_utils.c +++ b/tests/functs/src/utils/domain_utils.c @@ -1,4 +1,4 @@ -#include "domain_utils.h" +#include "utils/domain_utils.h" __clove_suite_t create_suite(const char* name) { __clove_suite_t suite; diff --git a/tests/functs/src/utils/file_utils.c b/tests/functs/src/utils/file_utils.c new file mode 100644 index 0000000..c7869d5 --- /dev/null +++ b/tests/functs/src/utils/file_utils.c @@ -0,0 +1,157 @@ +#include "file_utils.h" +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +static void _utils_os_mkdir(const char* path) { + _mkdir(path); +} + +static int _utils_os_rmdir_recurs(const char* dir) { + int dir_len = strlen(dir); + int len = dir_len + 2; // Extra space for double null termination + char* tempDir = (char*) malloc(len * sizeof(char)); + if (!tempDir) { + printf("Error: Failed to open directory: %s\n", dir); + return -1; + } + + memset(tempDir, 0, len * sizeof(char)); + __clove_memory_memcpy(tempDir, len, dir, dir_len); + + SHFILEOPSTRUCTA fileOp = { + NULL, + FO_DELETE, + tempDir, + NULL, + FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT, + false, + 0, + "" }; + + int ret = SHFileOperationA(&fileOp); + free(tempDir); + return ret; // 0 on success, non-zero on failure +} + +static char* _utils_os_cwd() { + char buffer[_MAX_PATH]; + _getcwd(buffer, sizeof(buffer)); + + char* result = __clove_string_strdup(buffer); + return result; +} + +#else +#include +#include +#include +//#include +#include +static void _utils_os_mkdir(const char* path) { + mkdir(path, 0775); +} + +static int _utils_os_rmdir_recurs(const char* dirPath) { + DIR* d = opendir(dirPath); + if (!d) { + printf("Error: Failed to open directory: %s\n", dirPath); + return -1; + } + + struct dirent *entry; + int ret = 0; + + while ((entry = readdir(d)) != NULL) { + if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { + char fullPath[PATH_MAX]; + snprintf(fullPath, sizeof(fullPath), "%s/%s", dirPath, entry->d_name); + + if (entry->d_type == DT_DIR) { + ret = _utils_os_rmdir_recurs(fullPath); + } + else { + ret = remove(fullPath); + } + + if (ret != 0) { + printf("Error: Failed to remove %s\n", fullPath); + break; // Error occurred + } + } + } + + closedir(d); + if (ret == 0 && rmdir(dirPath) != 0) { + printf("Error: Failed to remove directory: %s\n", dirPath); + return -1; + } + return 0; +} + +static char* _utils_os_cwd() { + char buffer[PATH_MAX]; + getcwd(buffer, sizeof(buffer)); + + char* result = __clove_string_strdup(buffer); + return result; +} +#endif + +char* utils_cwd() { + //eventually _getcwd (windows) and getcwd (posix) can be used + //return __clove_path_to_absolute("."); + return _utils_os_cwd(); +} + +void utils_mkdirs(char* path) { + __clove_path_to_os(path); + + char* current_path = path; + while(true) { + char* next_sep_ptr = (char*)__clove_string_strstr(current_path, __CLOVE_PATH_SEPARATOR_STR); + if (next_sep_ptr == NULL) break; + + *next_sep_ptr = '\0'; + //eventually check if path exists to avoid mkdir call + _utils_os_mkdir(path); + *next_sep_ptr = __CLOVE_PATH_SEPARATOR; + + current_path = next_sep_ptr + 1; + } +} + +void utils_rmdir(char* path) { + _utils_os_rmdir_recurs(path); +} + +char* utils_file_read(const char* path) { + FILE* file = __clove_file_open(path, "rb"); + fseek(file, 0, SEEK_END); + size_t file_size = ftell(file); + rewind(file); + + char* result = (char*)malloc(file_size + 1); + result[file_size] = '\0'; + size_t bytes_read = fread(result, file_size, 1, file); + fclose(file); + return result; +} + +bool utils_file_exists(const char* path) { + struct stat buffer; + return stat(path, &buffer) == 0; +} + +void utils_file_delete(const char* path) { + if (utils_file_exists(path)) + remove(path); +} + + diff --git a/tests/functs/src/utils/file_utils.h b/tests/functs/src/utils/file_utils.h new file mode 100644 index 0000000..a16ad57 --- /dev/null +++ b/tests/functs/src/utils/file_utils.h @@ -0,0 +1,10 @@ +#pragma once +#include + +void utils_mkdirs(char* path); +void utils_rmdir(char* path); +char* utils_cwd(); + +bool utils_file_exists(const char* path); +void utils_file_delete(const char* path); +char* utils_file_read(const char* path); \ No newline at end of file diff --git a/tests/functs/src/utils/str_utils.c b/tests/functs/src/utils/str_utils.c new file mode 100644 index 0000000..96c50dd --- /dev/null +++ b/tests/functs/src/utils/str_utils.c @@ -0,0 +1,38 @@ +#include "utils/str_utils.h" +#include +#include + +//NOTE: Dangerous if in future will run test multithreaded +// Eventually improve with mutex or https://en.cppreference.com/w/c/atomic/atomic_flag +const char* str_fmt(const char* format, ...) { + static char result[1024]; + va_list args; + va_start(args, format); + __clove_string_vsprintf(result, sizeof(result), format, args); + va_end(args); + return result; +} + +void str_split(const char* str, char delim, __clove_vector_t* out_lines) { + __CLOVE_VECTOR_INIT(out_lines, char*); + char* source = __clove_string_strdup(str); + char delim_str[2] = {delim, '\0'}; + + #ifdef _WIN32 + char* context; + char *token = strtok_s(source, delim_str, &context); + #else + char *token = strtok(source, delim_str); + #endif //_WIN32 + + while (token != NULL) { + __CLOVE_VECTOR_ADD(out_lines, char*, token); + + #ifdef _WIN32 + token = strtok_s(NULL, delim_str, &context); + #else + token = strtok(NULL, delim_str); + #endif //_WIN32 + } +} + diff --git a/tests/functs/src/utils/str_utils.h b/tests/functs/src/utils/str_utils.h new file mode 100644 index 0000000..f101360 --- /dev/null +++ b/tests/functs/src/utils/str_utils.h @@ -0,0 +1,6 @@ +#pragma once + +typedef struct __clove_vector_t __clove_vector_t; + +const char* str_fmt(const char* format, ...); +void str_split(const char* str, char delim, __clove_vector_t* out_lines); diff --git a/tests/functs/src/utils/utils.h b/tests/functs/src/utils/utils.h index 2e802fa..0ee4760 100644 --- a/tests/functs/src/utils/utils.h +++ b/tests/functs/src/utils/utils.h @@ -1,14 +1,5 @@ #pragma once -#include -#include -#include - -typedef struct __clove_vector_t __clove_vector_t; - -int exec_cmd(const char* cmd, char** output); -bool file_exists(const char* path); -void file_delete(const char* path); -const char* str_fmt(const char* format, ...); -const char* cmd_fmt(const char* format, ...); -void str_split(const char* str, char delim, __clove_vector_t* out_lines); -char* read_file(const char* path); +#include "utils/cmd_utils.h" +#include "utils/str_utils.h" +#include "utils/file_utils.h" +#include "utils/domain_utils.h" diff --git a/tests/perfs/utils/perf_generator.c b/tests/perfs/utils/perf_generator.c index f187140..bb53f68 100644 --- a/tests/perfs/utils/perf_generator.c +++ b/tests/perfs/utils/perf_generator.c @@ -55,7 +55,7 @@ int main(int argc, char* argv[]) { } fclose(file); - free(path); - free(file_path); + __clove_memory_free(path); + __clove_memory_free(file_path); return 0; } \ No newline at end of file diff --git a/tests/stricts/clove-cpp/CMakeLists.txt b/tests/stricts/clove-cpp/CMakeLists.txt index b4693da..c87c77f 100644 --- a/tests/stricts/clove-cpp/CMakeLists.txt +++ b/tests/stricts/clove-cpp/CMakeLists.txt @@ -7,7 +7,7 @@ target_include_directories(StrictCloveCpp PRIVATE ../../../) set_property(TARGET StrictCloveCpp PROPERTY CXX_STANDARD 11) -if (NOT DEFINED CLOVE_CMAKE__CPP_STRICT_WARN_AS_ERROR OR CLOVE_CMAKE__CPP_STRICT_WARN_AS_ERROR EQUAL TRUE) +if (CLOVE_CMAKE__CPP_STRICT_WARN_AS_ERROR) set_property(TARGET StrictCloveCpp PROPERTY COMPILE_WARNING_AS_ERROR ON) endif()