From 60669dc91fce0b3e0c250ec4fe19e6e890622ef9 Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Fri, 9 Jan 2026 16:23:34 +0100 Subject: [PATCH 1/3] migrate api_test to criterion --- .gitignore | 3 + .vscode/settings.json | 5 ++ CMakeLists.txt | 16 +++--- README.md | 10 ++++ cmake/FindCriterion.cmake | 100 +++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 9 +++ api_test.c => tests/api_test.c | 58 +++++++------------ 7 files changed, 157 insertions(+), 44 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 cmake/FindCriterion.cmake create mode 100644 tests/CMakeLists.txt rename api_test.c => tests/api_test.c (74%) diff --git a/.gitignore b/.gitignore index 7fd7729..052d80b 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ Makefile api_test ccos_disk_tool + +build/ +.cache/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e61237d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "clangd.arguments": [ + "--compile-commands-dir=build" + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e872e3c..50fa187 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,14 @@ cmake_minimum_required(VERSION 3.10) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + project(ccos_disk_tool) set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${SOURCE_DIR}) +option(CCOS_ENABLE_TESTS "Build and run tests (Criterion)" OFF) + add_library(ccos_api STATIC ${SOURCE_DIR}/string_utils.h ${SOURCE_DIR}/string_utils.c @@ -26,10 +30,8 @@ add_executable(ccos_disk_tool TARGET_LINK_LIBRARIES(ccos_disk_tool ccos_api) -project(api_test) - -add_executable(api_test - ${SOURCE_DIR}/api_test.c - ) - -TARGET_LINK_LIBRARIES(api_test ccos_api) +if(CCOS_ENABLE_TESTS) + include(CTest) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/README.md b/README.md index 87c3560..416aaa2 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,16 @@ OPTIONS: -l, --in-place Write changes to the original image ``` +## Tests + +To run the tests, execute these commands: + +```bash +cmake -S . -B build -DCCOS_ENABLE_TESTS=ON +cmake --build build --parallel +ctest --test-dir build --output-on-failure +``` + ## Examples ### Working with bubble memory images or other non-standard images diff --git a/cmake/FindCriterion.cmake b/cmake/FindCriterion.cmake new file mode 100644 index 0000000..cf8d8d4 --- /dev/null +++ b/cmake/FindCriterion.cmake @@ -0,0 +1,100 @@ +# This file is licensed under the WTFPL version 2 -- you can see the full +# license over at http://www.wtfpl.net/txt/copying/ +# +# Find Criterion. +# +# Module defines the following imported library: +# Criterion::Criterion +# +# Module defines the following result variables: +# Criterion_FOUND - True if the Criterion library has been found +# Criterion_INCLUDE_DIRS - Include directories needed to use Criterion +# Criterion_LIBRARIES - Libraries needed to link to Criterion +# Criterion_VERSION - The version of the Criterion which was found +# +# Cache variables: +# Criterion_INCLUDE_DIR - The directory containing criterion/criterion.h +# Criterion_LIBRARY - The path to the Criterion library +# +# Example usage: +# find_package(Criterion) +# target_link_libraries(foo PRIVATE Criterion::Criterion) + +set(_criterionReason "") + +# Try pkg-config. +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Criterion QUIET criterion) +endif() + +find_path( + Criterion_INCLUDE_DIR + criterion/criterion.h + HINTS ${PC_Criterion_INCLUDE_DIRS} + DOC "The directory containing criterion/criterion.h" +) +mark_as_advanced(Criterion_INCLUDE_DIR) + +if(NOT Criterion_INCLUDE_DIR) + string(APPEND _criterionReason "criterion/criterion.h not found. ") +endif() + +find_library( + Criterion_LIBRARY + NAMES criterion libcriterion + HINTS ${PC_Criterion_LIBRARY_DIRS} + DOC "The path to the Criterion library" +) +mark_as_advanced(Criterion_LIBRARY) + +if(NOT Criterion_LIBRARY) + string(APPEND _criterionReason "Criterion library (libcriterion) not found. ") +endif() + +# Get Criterion version from pkg-config if available. Conditional check ensures +# that Criterion found by pkg-config is the one found by the find_path() and +# find_library(). +if(PC_Criterion_VERSION AND Criterion_INCLUDE_DIR IN_LIST PC_Criterion_INCLUDE_DIRS) + set(Criterion_VERSION ${PC_Criterion_VERSION}) +endif() + +include(FindPackageHandleStandardArgs) +# Handle the REQUIRED, QUIET, and version-related arguments of find_package(). +find_package_handle_standard_args( + Criterion + REQUIRED_VARS Criterion_LIBRARY Criterion_INCLUDE_DIR + VERSION_VAR Criterion_VERSION + HANDLE_VERSION_RANGE + REASON_FAILURE_MESSAGE "${_criterionReason}" +) + +unset(_criterionReason) + +if(NOT Criterion_FOUND) + return() +endif() + +set(Criterion_INCLUDE_DIRS ${Criterion_INCLUDE_DIR}) +set(Criterion_LIBRARIES ${Criterion_LIBRARY}) + +if(NOT TARGET Criterion::Criterion) + if(IS_ABSOLUTE "${Criterion_LIBRARY}") + add_library(Criterion::Criterion UNKNOWN IMPORTED) + set_target_properties( + Criterion::Criterion + PROPERTIES IMPORTED_LOCATION "${Criterion_LIBRARY}" + ) + else() + add_library(Criterion::Criterion INTERFACE IMPORTED) + set_target_properties( + Criterion::Criterion + PROPERTIES IMPORTED_LIBNAME "${Criterion_LIBRARY}" + ) + endif() + + set_target_properties( + Criterion::Criterion + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Criterion_INCLUDE_DIRS}" + ) +endif() \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..507e0c8 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,9 @@ +find_package(Criterion REQUIRED) + +add_executable(ccos_tests + ${CMAKE_CURRENT_LIST_DIR}/api_test.c + ) + +target_link_libraries(ccos_tests PRIVATE ccos_api Criterion::Criterion) + +add_test(NAME ccos_tests COMMAND ccos_tests) diff --git a/api_test.c b/tests/api_test.c similarity index 74% rename from api_test.c rename to tests/api_test.c index 81b48c6..3b404f1 100644 --- a/api_test.c +++ b/tests/api_test.c @@ -2,23 +2,15 @@ // Created by kirill on 04.06.2020. // +#include + #include #include -#include -#include - -#define __STR(X) #X -#define STR(X) __STR(X) -#define ASSERT(CONDITION) \ - do { \ - if (!(CONDITION)) { \ - fprintf(stderr, "%s:%d: \"%s\" Failed!\n", __FUNCTION__, __LINE__, STR(CONDITION)); \ - return -1; \ - } \ - } while (0) +#include +#include -uint8_t test_inode_data[] = { +static const uint8_t test_inode_data[] = { 0x98U, 0x00U, 0x00U, 0x00U, 0x84U, 0xD0U, 0x00U, 0x00U, 0x15U, 0x47U, 0x52U, 0x69U, 0x44U, 0x50U, 0x61U, 0x69U, 0x6EU, 0x74U, 0x7EU, 0x52U, 0x75U, 0x6EU, 0x20U, 0x43U, 0x61U, 0x6EU, 0x76U, 0x61U, 0x73U, 0x7EU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, @@ -52,43 +44,35 @@ uint8_t test_inode_data[] = { 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0x00U, 0x00U, 0x00U, 0x00U}; -int check_image_test() { +Test(ccos_image, check_image) { uint8_t data[0x200] = {0}; - ASSERT(ccos_check_image(data) == 0); + cr_assert_eq(ccos_check_image(data), 0); data[0] = 'I'; data[1] = 'M'; data[2] = 'D'; data[3] = ' '; - ASSERT(ccos_check_image(data) == -1); + cr_assert_eq(ccos_check_image(data), -1); memset(data, 0, 0x200); data[0] = 0xEB; data[2] = 0x90; *((uint16_t *)(&data[0x1FE])) = 0xAA55; - ASSERT(ccos_check_image(data) == -1); - return 0; + cr_assert_eq(ccos_check_image(data), -1); } -int ccos_get_file_version_test() { - ccos_inode_t inode = *((ccos_inode_t *)&test_inode_data); +Test(ccos_image, get_file_version) { + ccos_inode_t inode; + memcpy(&inode, test_inode_data, sizeof(inode)); version_t version = ccos_get_file_version(&inode); - ASSERT(version.major == 3); - ASSERT(version.minor == 1); - ASSERT(version.patch == 5); - return 0; + cr_assert_eq(version.major, 3); + cr_assert_eq(version.minor, 1); + cr_assert_eq(version.patch, 5); } -int ccos_get_file_name_test() { - ccos_inode_t inode = *((ccos_inode_t *)&test_inode_data); +Test(ccos_image, get_file_name) { + ccos_inode_t inode; + memcpy(&inode, test_inode_data, sizeof(inode)); short_string_t *name = ccos_get_file_name(&inode); - ASSERT(name->length == 21); - ASSERT(!strncmp(name->data, "GRiDPaint~Run Canvas~", name->length)); - return 0; -} - -int main() { - ASSERT(check_image_test() == 0); - ASSERT(ccos_get_file_version_test() == 0); - ASSERT(ccos_get_file_name_test() == 0); - printf("All tests completed!\n"); - return 0; + cr_assert_not_null(name); + cr_assert_eq(name->length, 21); + cr_assert_eq(strncmp(name->data, "GRiDPaint~Run Canvas~", name->length), 0); } From 8ca1fc8bb71059f785457da60d4a79c98fd687be Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Fri, 9 Jan 2026 16:38:44 +0100 Subject: [PATCH 2/3] enable EXPORT_COMPILE_COMMANDS by default --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50fa187..cf4a0af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.10) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") project(ccos_disk_tool) From 138436bf6b9103a23cd70cf0107fb1862ace3b53 Mon Sep 17 00:00:00 2001 From: Valerii Klachkov Date: Sat, 10 Jan 2026 11:58:47 +0100 Subject: [PATCH 3/3] update README.md --- README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 416aaa2..16e8454 100644 --- a/README.md +++ b/README.md @@ -43,9 +43,20 @@ OPTIONS: -l, --in-place Write changes to the original image ``` -## Tests +## Build -To run the tests, execute these commands: +To build the project, run the following commands: + +```bash +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build --parallel +``` + +After building, the compiled binary will be located at `build/ccos_disk_tool`. + +## Run Tests + +To run the tests, use the following commands: ```bash cmake -S . -B build -DCCOS_ENABLE_TESTS=ON @@ -53,6 +64,8 @@ cmake --build build --parallel ctest --test-dir build --output-on-failure ``` +Tests depend on the [Criterion](https://github.com/Snaipe/Criterion) library, which must be installed before running the tests. + ## Examples ### Working with bubble memory images or other non-standard images