From ca41a29b8bb19f0240eac0f872a7b958fb1f5f19 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 5 Sep 2024 08:04:37 +0200 Subject: [PATCH 1/6] clar: stop passing a timezone to gettimeofday(3P) According to gettimeofday(3P), passing a non-NULL timezone pointer to the function is unspecified behaviour. This is also being warned about by compilers when compiling with strict C90 standard and without most of the extensions. Adapt the code accordingly. --- clar.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clar.c b/clar.c index cef0f02..e593bb1 100644 --- a/clar.c +++ b/clar.c @@ -271,9 +271,7 @@ static double clar_time_diff(clar_time *start, clar_time *end) static void clar_time_now(clar_time *out) { - struct timezone tz; - - gettimeofday(out, &tz); + gettimeofday(out, NULL); } static double clar_time_diff(clar_time *start, clar_time *end) From a0d59872603c54b527e93b403533266daeb1e06c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 5 Sep 2024 10:59:30 +0200 Subject: [PATCH 2/6] clar: drop use of unportable PRIuZ/PRIxZ formatters The formatting directives PRIuZ and PRIxZ are not portable across platforms and cause issues on Windows. Stop using them and instead use PRIuMAX and PRIxMAX, which are portable. --- clar.c | 20 ++++---------------- clar/print.h | 4 ++-- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/clar.c b/clar.c index e593bb1..02e8db9 100644 --- a/clar.c +++ b/clar.c @@ -13,6 +13,7 @@ #include #include #include +#include /* required for sandboxing */ #include @@ -61,13 +62,6 @@ # define p_snprintf snprintf # endif -# ifndef PRIuZ -# define PRIuZ "Iu" -# endif -# ifndef PRIxZ -# define PRIxZ "Ix" -# endif - # if defined(_MSC_VER) || (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) typedef struct stat STAT_T; # else @@ -78,12 +72,6 @@ # include # define _MAIN_CC # define p_snprintf snprintf -# ifndef PRIuZ -# define PRIuZ "zu" -# endif -# ifndef PRIxZ -# define PRIxZ "zx" -# endif typedef struct stat STAT_T; #endif @@ -102,7 +90,7 @@ fixture_path(const char *base, const char *fixture_name); struct clar_error { const char *file; const char *function; - size_t line_number; + uintmax_t line_number; const char *error_msg; char *description; @@ -796,8 +784,8 @@ void clar__assert_equal( } } } - else if (!strcmp("%"PRIuZ, fmt) || !strcmp("%"PRIxZ, fmt)) { - size_t sz1 = va_arg(args, size_t), sz2 = va_arg(args, size_t); + else if (!strcmp("%"PRIuMAX, fmt) || !strcmp("%"PRIxMAX, fmt)) { + uintmax_t sz1 = va_arg(args, uintmax_t), sz2 = va_arg(args, uintmax_t); is_equal = (sz1 == sz2); if (!is_equal) { int offset = p_snprintf(buf, sizeof(buf), fmt, sz1); diff --git a/clar/print.h b/clar/print.h index c17e2f6..c145b40 100644 --- a/clar/print.h +++ b/clar/print.h @@ -21,7 +21,7 @@ static void clar_print_clap_error(int num, const struct clar_report *report, con { printf(" %d) Failure:\n", num); - printf("%s::%s [%s:%"PRIuZ"]\n", + printf("%s::%s [%s:%"PRIuMAX"]\n", report->suite, report->test, error->file, @@ -136,7 +136,7 @@ static void clar_print_tap_ontest(const char *suite_name, const char *test_name, printf(" at:\n"); printf(" file: '"); print_escaped(error->file); printf("'\n"); - printf(" line: %" PRIuZ "\n", error->line_number); + printf(" line: %" PRIuMAX "\n", error->line_number); printf(" function: '%s'\n", error->function); printf(" ---\n"); From e3fb2fe717b2d5dbff5f115becb1f95b383bdc60 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 5 Sep 2024 07:44:01 +0200 Subject: [PATCH 3/6] cmake: wire up initial support The project uses a Makefile as the build system for the test executable. This makes it hard to build and test on Windows via MSVC. Introduce support for CMake. --- .gitignore | 1 + CMakeLists.txt | 25 +++++++++++++++++++++++++ test/CMakeLists.txt | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 test/CMakeLists.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84c048a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3cdcdc9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.25.0) + +project(clar LANGUAGES C) + +option(BUILD_TESTS "Build test executable" ON) + +add_library(clar INTERFACE) +target_sources(clar INTERFACE + clar.c + clar.h + clar/fixtures.h + clar/fs.h + clar/print.h + clar/sandbox.h + clar/summary.h +) +set_target_properties(clar PROPERTIES + C_STANDARD 90 + C_STANDARD_REQUIRED ON + C_EXTENSIONS OFF +) + +if(BUILD_TESTS) + add_subdirectory(test) +endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..9a26f5b --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,41 @@ +find_package(Python COMPONENTS Interpreter REQUIRED) + +add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/clar.suite" + COMMAND "${Python_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/generate.py" --output "${CMAKE_CURRENT_BINARY_DIR}" + DEPENDS main.c sample.c + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +) + +add_executable(clar_test) +set_target_properties(clar_test PROPERTIES + C_STANDARD 90 + C_STANDARD_REQUIRED ON + C_EXTENSIONS OFF +) + +# MSVC generates all kinds of warnings. We may want to fix these in the future +# and then unconditionally treat warnings as errors. +if (NOT MSVC) + set_target_properties(clar_test PROPERTIES + COMPILE_WARNING_AS_ERROR ON + ) +endif() + +target_sources(clar_test PRIVATE + main.c + sample.c + "${CMAKE_CURRENT_BINARY_DIR}/clar.suite" +) +target_compile_definitions(clar_test PRIVATE + CLAR_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/" + _DARWIN_C_SOURCE + _POSIX_C_SOURCE=200809L +) +target_compile_options(clar_test PRIVATE + $,/W4,-Wall> +) +target_include_directories(clar_test PRIVATE + "${CMAKE_SOURCE_DIR}" + "${CMAKE_CURRENT_BINARY_DIR}" +) +target_link_libraries(clar_test clar) From f255c0b0da22816c901d84e21ef552fa139bd0d0 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 5 Sep 2024 07:45:19 +0200 Subject: [PATCH 4/6] ci: convert to use CMake Convert the CI to use CMake instead of Makefiles. This will allow us to wire up support for Windows in a subsequent commit. --- .github/workflows/ci.yml | 6 ++++-- CMakeLists.txt | 9 ++++++--- test/CMakeLists.txt | 4 ++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b1ac2de..ea05f05 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,5 +19,7 @@ jobs: uses: actions/checkout@v2 - name: Build run: | - cd test - make + mkdir build + cd build + cmake .. + cmake --build . diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cdcdc9..12d4af1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.25.0) +cmake_minimum_required(VERSION 3.16..3.29) project(clar LANGUAGES C) @@ -20,6 +20,9 @@ set_target_properties(clar PROPERTIES C_EXTENSIONS OFF ) -if(BUILD_TESTS) - add_subdirectory(test) +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + include(CTest) + if(BUILD_TESTING) + add_subdirectory(test) + endif() endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9a26f5b..4c9012d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,7 +2,7 @@ find_package(Python COMPONENTS Interpreter REQUIRED) add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/clar.suite" COMMAND "${Python_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/generate.py" --output "${CMAKE_CURRENT_BINARY_DIR}" - DEPENDS main.c sample.c + DEPENDS main.c sample.c clar_test.h WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" ) @@ -15,7 +15,7 @@ set_target_properties(clar_test PROPERTIES # MSVC generates all kinds of warnings. We may want to fix these in the future # and then unconditionally treat warnings as errors. -if (NOT MSVC) +if(NOT MSVC) set_target_properties(clar_test PROPERTIES COMPILE_WARNING_AS_ERROR ON ) From 5d8969b6e8576e94aa0d4c2518d3fbe0d114c90a Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 5 Sep 2024 07:47:44 +0200 Subject: [PATCH 5/6] ci: run on Windows Now that we have wired up support for CMake it is trivial to also compile the test binary on Windows. Wire this up. --- .github/workflows/ci.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea05f05..0065843 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,9 +10,19 @@ jobs: build: strategy: matrix: - os: [ ubuntu-latest, macos-latest ] + platform: + - os: ubuntu-latest + generator: Unix Makefiles + - os: macos-latest + generator: Unix Makefiles + - os: windows-latest + generator: Visual Studio 17 2022 + - os: windows-latest + generator: MSYS Makefiles + - os: windows-latest + generator: MinGW Makefiles - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.platform.os }} steps: - name: Check out @@ -21,5 +31,5 @@ jobs: run: | mkdir build cd build - cmake .. + cmake .. -G "${{matrix.platform.generator}}" cmake --build . From 7426a25d9c2cf6fb855c2bac1ce9e0d6212504d8 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 5 Sep 2024 07:46:45 +0200 Subject: [PATCH 6/6] test: drop superseded Makefile The Makefile in "test/" has been responsible for building the "clar_test" executable as a sort of smoke test. Now that we have introduced support for CMake it has been superseded. Remove it. --- test/.gitignore | 4 ---- test/Makefile | 39 --------------------------------------- 2 files changed, 43 deletions(-) delete mode 100644 test/.gitignore delete mode 100644 test/Makefile diff --git a/test/.gitignore b/test/.gitignore deleted file mode 100644 index a477d0c..0000000 --- a/test/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -clar.suite -.clarcache -clar_test -*.o diff --git a/test/Makefile b/test/Makefile deleted file mode 100644 index 93c6b2a..0000000 --- a/test/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright (c) Vicent Marti. All rights reserved. -# -# This file is part of clar, distributed under the ISC license. -# For full terms see the included COPYING file. -# - -# -# Set up the path to the clar sources and to the fixtures directory -# -# The fixture path needs to be an absolute path so it can be used -# even after we have chdir'ed into the test directory while testing. -# -CURRENT_MAKEFILE := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) -TEST_DIRECTORY := $(abspath $(dir $(CURRENT_MAKEFILE))) -CLAR_PATH := $(dir $(TEST_DIRECTORY)) -CLAR_FIXTURE_PATH := $(TEST_DIRECTORY)/resources/ - -CFLAGS=-g -I.. -I. -Wall -DCLAR_FIXTURE_PATH=\"$(CLAR_FIXTURE_PATH)\" - -.PHONY: clean - -# list the objects that go into our test -objects = main.o sample.o - -# build the test executable itself -clar_test: $(objects) clar_test.h clar.suite $(CLAR_PATH)clar.c - $(CC) $(CFLAGS) -o $@ "$(CLAR_PATH)clar.c" $(objects) - -# test object files depend on clar macros -$(objects) : $(CLAR_PATH)clar.h - -# build the clar.suite file of test metadata -clar.suite: - python "$(CLAR_PATH)generate.py" . - -# remove all generated files -clean: - $(RM) -rf *.o clar.suite .clarcache clar_test clar_test.dSYM