Add Asan profile, fix multiple bugs.

Added Asan profile to help catch and fix various bugs (and indeed, there
were few of them).

Additionally, fixed bhunit macro to process arguments only once.
This commit is contained in:
2025-01-29 09:19:34 +03:00
parent 47c21a2035
commit 6ede63e18f
8 changed files with 78 additions and 21 deletions

View File

@@ -5,6 +5,42 @@ project(bhlib LANGUAGES C)
set(CMAKE_C_STANDARD 90) set(CMAKE_C_STANDARD 90)
set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON)
# Asan profile
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(isMultiConfig)
if(NOT "Asan" IN_LIST CMAKE_CONFIGURATION_TYPES)
list(APPEND CMAKE_CONFIGURATION_TYPES Asan)
endif()
else()
set(allowedBuildTypes Asan Debug Release RelWithDebInfo MinSizeRel)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowedBuildTypes}")
if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE IN_LIST allowedBuildTypes)
message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
endif()
endif()
set(CMAKE_C_FLAGS_ASAN
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=address,undefined -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C compiler for Asan build type or configuration." FORCE
)
set(CMAKE_CXX_FLAGS_ASAN
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address,undefined -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C++ compiler for Asan build type or configuration." FORCE
)
set(CMAKE_EXE_LINKER_FLAGS_ASAN
"${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fsanitize=address,undefined -static-libasan" CACHE STRING
"Linker flags to be used to create executables for Asan build type." FORCE
)
set(CMAKE_SHARED_LINKER_FLAGS_ASAN
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address,undefined -static-libasan" CACHE STRING
"Linker lags to be used to create shared libraries for Asan build type." FORCE
)
# Project includes # Project includes
include(CheckIPOSupported) include(CheckIPOSupported)
include(CheckIncludeFile) include(CheckIncludeFile)
@@ -84,7 +120,7 @@ target_link_libraries(bhlib PUBLIC m)
if(MSVC) if(MSVC)
target_compile_options(bhlib PRIVATE /W4 /WX) target_compile_options(bhlib PRIVATE /W4 /WX)
else() else()
target_compile_options(bhlib PRIVATE -Wall -Wextra -Wpedantic -Werror) target_compile_options(bhlib PRIVATE -Wall -Wextra -Wpedantic -Werror -fstrict-aliasing)
endif() endif()
# Coverage # Coverage

View File

@@ -46,6 +46,9 @@ void bh_io_free(bh_io_t *io)
/* Call the IO device destruction handler */ /* Call the IO device destruction handler */
io->func(io + 1, BH_IO_DESTROY_CB, NULL, NULL); io->func(io + 1, BH_IO_DESTROY_CB, NULL, NULL);
/* Deallocate object */
free(io);
} }

View File

@@ -2,9 +2,6 @@ set(CMAKE_C_STANDARD 90)
set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF) set(CMAKE_C_EXTENSIONS OFF)
# Enable warnings and pedantics
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic")
# Enable testing # Enable testing
include(CTest) include(CTest)
enable_testing() enable_testing()
@@ -13,10 +10,20 @@ enable_testing()
file(GLOB TEST_FILES "src/*.c") file(GLOB TEST_FILES "src/*.c")
foreach(TEST_FILENAME ${TEST_FILES}) foreach(TEST_FILENAME ${TEST_FILES})
# Add test
get_filename_component(TEST_NAME ${TEST_FILENAME} NAME_WE) get_filename_component(TEST_NAME ${TEST_FILENAME} NAME_WE)
add_executable("${TEST_NAME}" ${TEST_FILENAME}) add_executable("${TEST_NAME}" ${TEST_FILENAME})
target_link_libraries("${TEST_NAME}" bhlib bhunit) target_link_libraries("${TEST_NAME}" bhlib bhunit)
add_test(NAME "${TEST_NAME}" COMMAND "${TEST_NAME}") add_test(NAME "${TEST_NAME}" COMMAND "${TEST_NAME}")
# Enable all compiler warnings
if(MSVC)
target_compile_options("${TEST_NAME}" PRIVATE /W4 /WX)
else()
target_compile_options("${TEST_NAME}" PRIVATE -Wall -Wextra -Wpedantic -Werror -fstrict-aliasing)
endif()
# Enable coverage
if(COVERAGE) if(COVERAGE)
target_compile_options("${TEST_NAME}" PRIVATE -coverage) target_compile_options("${TEST_NAME}" PRIVATE -coverage)
target_link_options("${TEST_NAME}" PRIVATE -coverage) target_link_options("${TEST_NAME}" PRIVATE -coverage)

View File

@@ -121,7 +121,7 @@ static int check_normal(void)
BH_VERIFY(bh_io_read(io, buffer, 5, &actual) == BH_OK); BH_VERIFY(bh_io_read(io, buffer, 5, &actual) == BH_OK);
BH_VERIFY(actual == 5); BH_VERIFY(actual == 5);
BH_VERIFY(memcmp(buffer, "67890", 5) == 0); BH_VERIFY(memcmp(buffer, "67890", 5) == 0);
bh_io_close(io); bh_io_free(io);
/* Check operations for read and write access */ /* Check operations for read and write access */
BH_VERIFY((io = bh_file_new(FILENAME1)) != NULL); BH_VERIFY((io = bh_file_new(FILENAME1)) != NULL);
@@ -226,7 +226,7 @@ static int check_truncate(void)
BH_VERIFY(bh_io_seek(io, 0, BH_IO_SEEK_SET) == BH_OK); BH_VERIFY(bh_io_seek(io, 0, BH_IO_SEEK_SET) == BH_OK);
BH_VERIFY(bh_io_read(io, buffer, sizeof(buffer), &actual) == BH_OK); BH_VERIFY(bh_io_read(io, buffer, sizeof(buffer), &actual) == BH_OK);
BH_VERIFY(actual == 0); BH_VERIFY(actual == 0);
bh_io_close(io); bh_io_free(io);
/* Check operations for read and write access */ /* Check operations for read and write access */
BH_VERIFY((io = bh_file_new(FILENAME1)) != NULL); BH_VERIFY((io = bh_file_new(FILENAME1)) != NULL);
@@ -321,7 +321,7 @@ static int check_exist(void)
BH_VERIFY(bh_io_read(io, buffer, 5, &actual) == BH_OK); BH_VERIFY(bh_io_read(io, buffer, 5, &actual) == BH_OK);
BH_VERIFY(actual == 5); BH_VERIFY(actual == 5);
BH_VERIFY(memcmp(buffer, "67890", 5) == 0); BH_VERIFY(memcmp(buffer, "67890", 5) == 0);
bh_io_close(io); bh_io_free(io);
/* Check operations for read and write access */ /* Check operations for read and write access */
BH_VERIFY((io = bh_file_new(FILENAME1)) != NULL); BH_VERIFY((io = bh_file_new(FILENAME1)) != NULL);

View File

@@ -157,7 +157,7 @@ static int lookup(void)
BH_VERIFY(bh_hashmap_at(hashmap, BH_INT2PTR(i * 4), NULL) == BH_OK); BH_VERIFY(bh_hashmap_at(hashmap, BH_INT2PTR(i * 4), NULL) == BH_OK);
BH_VERIFY(bh_hashmap_at(hashmap, BH_INT2PTR(i * 4), &value) == BH_OK); BH_VERIFY(bh_hashmap_at(hashmap, BH_INT2PTR(i * 4), &value) == BH_OK);
BH_VERIFY(BH_PTR2INT(value) == i); BH_VERIFY(BH_PTR2INT(value) == (int)i);
} }
/* Lookup non-existing elements */ /* Lookup non-existing elements */

View File

@@ -25,5 +25,5 @@ target_include_directories(bhunit PUBLIC include)
if(MSVC) if(MSVC)
target_compile_options(bhunit PRIVATE /W4 /WX) target_compile_options(bhunit PRIVATE /W4 /WX)
else() else()
target_compile_options(bhunit PRIVATE -Wall -Wextra -Wpedantic -Werror) target_compile_options(bhunit PRIVATE -Wall -Wextra -Wpedantic -Werror -fstrict-aliasing)
endif() endif()

View File

@@ -2,27 +2,38 @@
#define BH_UNIT_H #define BH_UNIT_H
#include <stdio.h> #include <stdio.h>
#include <math.h>
typedef int (*bh_unit_cb_t)(void); typedef int (*bh_unit_cb_t)(void);
#define BH_VERIFY(e) \ #define BH_VERIFY(e) \
do { if (!(e)) { \ do { \
if (!(e)) { \
printf("%s:%d\t%s\n", __FILE__, __LINE__, #e); \ printf("%s:%d\t%s\n", __FILE__, __LINE__, #e); \
return -1; \ return -1; \
} } while(0) } \
} while(0)
#define BH_FAIL(msg) \ #define BH_FAIL(msg) \
do { printf("%s:%d\t%s\n", __FILE__, __LINE__, msg); \ do { \
return -1; } while(0) printf("%s:%d\t%s\n", __FILE__, __LINE__, msg); \
return -1; \
} while(0)
#define BH_VERIFY_DELTA(x, y, e) \ #define BH_VERIFY_DELTA(x, y, e) \
do { if ((((x)>(y))?((x)-(y)):((y)-(x)))>(e)) { \ do { \
printf("%s:%d\t%s\n", __FILE__, __LINE__, #x " == " #y); \ double BH_VERIFY_DELTA = (x)-(y); \
if (BH_VERIFY_DELTA < 0.0) \
BH_VERIFY_DELTA = -BH_VERIFY_DELTA; \
if (BH_VERIFY_DELTA > (e)) { \
printf("%s:%d\t%s (differs by %f)\n", __FILE__, __LINE__, #x " == " #y, BH_VERIFY_DELTA); \
return -1; \ return -1; \
} \
} while(0) } while(0)
void bh_unit_add(const char *name, bh_unit_cb_t func); void bh_unit_add(const char *name, bh_unit_cb_t func);
int bh_unit_run(void); int bh_unit_run(void);