Default versioned API functions to earliest version for older API settings (#6280)

When a global API version is set (e.g., H5_USE_16_API), functions
introduced after that version now default to their earliest version
(version 1) instead of the latest. This prevents breakage when an
application uses an older API setting but calls functions that were
later versioned.
This commit is contained in:
Scot Breitenfeld
2026-04-07 11:06:32 -05:00
committed by GitHub
parent 00499095d6
commit cbff0315f3
6 changed files with 699 additions and 0 deletions
+36
View File
@@ -655,6 +655,42 @@ foreach (h5_test ${H5_CHECK_TESTS})
ADD_H5_EXE(${h5_test})
endforeach ()
#-- Adding test executables for API version defaulting
# Each is compiled with a different -DH5_USE_*_API and -DTEST_API_VERSION=*
# to verify that functions introduced after the configured API version
# default to their earliest version.
# The test source is auto-generated by bin/make_vers from H5vers.txt.
# Older API versions (v16-v114) require deprecated symbols to be enabled.
# NOTE: Cannot use ADD_H5_EXE here because multiple targets share one source
# file (tapi_version_default.c) with different compile definitions.
if (HDF5_ENABLE_DEPRECATED_SYMBOLS)
set (API_VERSION_TEST_NUMBERS 16 18 110 112 114 200)
else ()
set (API_VERSION_TEST_NUMBERS 200)
endif ()
foreach (api_num IN LISTS API_VERSION_TEST_NUMBERS)
set (test_name tapi_version_default_v${api_num})
add_executable (${test_name} ${HDF5_TEST_SOURCE_DIR}/tapi_version_default.c)
target_include_directories (${test_name} PRIVATE "${HDF5_SRC_INCLUDE_DIRS};${HDF5_SRC_BINARY_DIR};${HDF5_TEST_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>")
target_compile_options(${test_name} PRIVATE ${HDF5_CMAKE_C_FLAGS})
target_compile_definitions(${test_name} PRIVATE
${HDF5_TEST_COMPILE_DEFS_PRIVATE}
H5_USE_${api_num}_API
TEST_API_VERSION=${api_num}
)
if (NOT BUILD_SHARED_LIBS)
TARGET_C_PROPERTIES (${test_name} STATIC)
target_link_libraries (${test_name} PRIVATE ${HDF5_TEST_LIB_TARGET})
else ()
TARGET_C_PROPERTIES (${test_name} SHARED)
target_link_libraries (${test_name} PRIVATE ${HDF5_TEST_LIBSH_TARGET})
endif ()
set_target_properties (${test_name} PROPERTIES FOLDER test)
if (HDF5_ENABLE_FORMATTERS)
clang_format (HDF5_TEST_${test_name}_FORMAT ${test_name})
endif ()
endforeach ()
#-- Adding test for libinfo
set (GREP_RUNNER ${PROJECT_BINARY_DIR}/GrepRunner.cmake)
file (WRITE ${GREP_RUNNER} "file (STRINGS \${TEST_PROGRAM} TEST_RESULT REGEX \"SUMMARY OF THE HDF5 CONFIGURATION\")
+14
View File
@@ -915,6 +915,20 @@ if ("H5TEST-error_test" MATCHES "${HDF5_DISABLE_TESTS_REGEX}")
set_tests_properties (H5TEST-error_test PROPERTIES DISABLED true)
endif ()
#-- Adding tests for API version defaulting
# API_VERSION_TEST_NUMBERS is defined in CMakeLists.txt and already in scope
foreach (api_num IN LISTS API_VERSION_TEST_NUMBERS)
add_test (NAME H5TEST-tapi_version_default_v${api_num}
COMMAND $<TARGET_FILE:tapi_version_default_v${api_num}>
)
set_tests_properties (H5TEST-tapi_version_default_v${api_num} PROPERTIES
WORKING_DIRECTORY ${HDF5_TEST_BINARY_DIR}/H5TEST
)
if ("H5TEST-tapi_version_default_v${api_num}" MATCHES "${HDF5_DISABLE_TESTS_REGEX}")
set_tests_properties (H5TEST-tapi_version_default_v${api_num} PROPERTIES DISABLED true)
endif ()
endforeach ()
#-- Adding test for links_env
add_test (NAME H5TEST-links_env-clear-objects
COMMAND ${CMAKE_COMMAND} -E remove
+392
View File
@@ -0,0 +1,392 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the LICENSE file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Generated automatically by bin/make_vers -- do not edit */
/* Add new versioned symbols to H5vers.txt file */
/*
* Purpose: Tests that versioned API function macros default to the earliest
* version for functions introduced after the configured global API
* version. For example, with H5_USE_16_API, H5Sencode (introduced
* in v1.8) should map to H5Sencode1, not H5Sencode2.
*
* This test is compiled multiple times with different
* -DH5_USE_*_API and -DTEST_API_VERSION=* flags to verify each
* API version level.
*/
/* Include config header first to set its include guard */
#include "H5pubconf.h"
/* Clear all API version macros that may have been set by the
* global default configuration, so only the version under test
* is active when H5version.h is processed.
*/
#undef H5_USE_16_API_DEFAULT
#undef H5_USE_16_API
#undef H5_USE_18_API_DEFAULT
#undef H5_USE_18_API
#undef H5_USE_110_API_DEFAULT
#undef H5_USE_110_API
#undef H5_USE_112_API_DEFAULT
#undef H5_USE_112_API
#undef H5_USE_114_API_DEFAULT
#undef H5_USE_114_API
#undef H5_USE_200_API_DEFAULT
#undef H5_USE_200_API
/* Re-establish only the API version under test */
#if TEST_API_VERSION == 16
#define H5_USE_16_API 1
#elif TEST_API_VERSION == 18
#define H5_USE_18_API 1
#elif TEST_API_VERSION == 110
#define H5_USE_110_API 1
#elif TEST_API_VERSION == 112
#define H5_USE_112_API 1
#elif TEST_API_VERSION == 114
#define H5_USE_114_API 1
#elif TEST_API_VERSION == 200
#define H5_USE_200_API 1
#else
#error "TEST_API_VERSION not set to a valid value"
#endif
#include "h5test.h"
/*
* Helper macro: check that a _vers macro equals an expected value.
*/
#define CHECK_VERS(func_name, expected) \
do { \
if (func_name##_vers != (expected)) { \
fprintf(stderr, "FAIL: %s_vers = %d, expected %d\n", #func_name, func_name##_vers, (expected)); \
nerrors++; \
} \
} while (0)
#define CHECK_VERS_T(type_name, expected) \
do { \
if (type_name##_t_vers != (expected)) { \
fprintf(stderr, "FAIL: %s_t_vers = %d, expected %d\n", #type_name, type_name##_t_vers, \
(expected)); \
nerrors++; \
} \
} while (0)
int
main(void)
{
int nerrors = 0;
TESTING("API version defaulting for versioned functions");
#if TEST_API_VERSION == 16
printf("Configured with H5_USE_16_API\n");
CHECK_VERS(H5Acreate, 1);
CHECK_VERS(H5Aiterate, 1);
CHECK_VERS(H5Dcreate, 1);
CHECK_VERS(H5Dopen, 1);
CHECK_VERS(H5Dread_chunk, 1);
CHECK_VERS(H5Eclear, 1);
CHECK_VERS(H5Eget_auto, 1);
CHECK_VERS(H5Eprint, 1);
CHECK_VERS(H5Epush, 1);
CHECK_VERS(H5Eset_auto, 1);
CHECK_VERS(H5Ewalk, 1);
CHECK_VERS(H5Fget_info, 1);
CHECK_VERS(H5Gcreate, 1);
CHECK_VERS(H5Gopen, 1);
CHECK_VERS(H5Iregister_type, 1);
CHECK_VERS(H5Lget_info, 1);
CHECK_VERS(H5Lget_info_by_idx, 1);
CHECK_VERS(H5Literate, 1);
CHECK_VERS(H5Literate_by_name, 1);
CHECK_VERS(H5Lvisit, 1);
CHECK_VERS(H5Lvisit_by_name, 1);
CHECK_VERS(H5Oget_info, 1);
CHECK_VERS(H5Oget_info_by_idx, 1);
CHECK_VERS(H5Oget_info_by_name, 1);
CHECK_VERS(H5Ovisit, 1);
CHECK_VERS(H5Ovisit_by_name, 1);
CHECK_VERS(H5Pencode, 1);
CHECK_VERS(H5Pget_filter, 1);
CHECK_VERS(H5Pget_filter_by_id, 1);
CHECK_VERS(H5Pinsert, 1);
CHECK_VERS(H5Pregister, 1);
CHECK_VERS(H5Rdereference, 1);
CHECK_VERS(H5Rget_obj_type, 1);
CHECK_VERS(H5Sencode, 1);
CHECK_VERS(H5Tarray_create, 1);
CHECK_VERS(H5Tcommit, 1);
CHECK_VERS(H5Tdecode, 1);
CHECK_VERS(H5Tget_array_dims, 1);
CHECK_VERS(H5Topen, 1);
CHECK_VERS_T(H5E_auto, 1);
CHECK_VERS_T(H5O_info, 1);
CHECK_VERS_T(H5O_iterate, 1);
CHECK_VERS_T(H5Z_class, 1);
#elif TEST_API_VERSION == 18
printf("Configured with H5_USE_18_API\n");
CHECK_VERS(H5Acreate, 2);
CHECK_VERS(H5Aiterate, 2);
CHECK_VERS(H5Dcreate, 2);
CHECK_VERS(H5Dopen, 2);
CHECK_VERS(H5Dread_chunk, 1);
CHECK_VERS(H5Eclear, 2);
CHECK_VERS(H5Eget_auto, 2);
CHECK_VERS(H5Eprint, 2);
CHECK_VERS(H5Epush, 2);
CHECK_VERS(H5Eset_auto, 2);
CHECK_VERS(H5Ewalk, 2);
CHECK_VERS(H5Fget_info, 1);
CHECK_VERS(H5Gcreate, 2);
CHECK_VERS(H5Gopen, 2);
CHECK_VERS(H5Iregister_type, 1);
CHECK_VERS(H5Lget_info, 1);
CHECK_VERS(H5Lget_info_by_idx, 1);
CHECK_VERS(H5Literate, 1);
CHECK_VERS(H5Literate_by_name, 1);
CHECK_VERS(H5Lvisit, 1);
CHECK_VERS(H5Lvisit_by_name, 1);
CHECK_VERS(H5Oget_info, 1);
CHECK_VERS(H5Oget_info_by_idx, 1);
CHECK_VERS(H5Oget_info_by_name, 1);
CHECK_VERS(H5Ovisit, 1);
CHECK_VERS(H5Ovisit_by_name, 1);
CHECK_VERS(H5Pencode, 1);
CHECK_VERS(H5Pget_filter, 2);
CHECK_VERS(H5Pget_filter_by_id, 2);
CHECK_VERS(H5Pinsert, 2);
CHECK_VERS(H5Pregister, 2);
CHECK_VERS(H5Rdereference, 1);
CHECK_VERS(H5Rget_obj_type, 2);
CHECK_VERS(H5Sencode, 1);
CHECK_VERS(H5Tarray_create, 2);
CHECK_VERS(H5Tcommit, 2);
CHECK_VERS(H5Tdecode, 1);
CHECK_VERS(H5Tget_array_dims, 2);
CHECK_VERS(H5Topen, 2);
CHECK_VERS_T(H5E_auto, 2);
CHECK_VERS_T(H5O_info, 1);
CHECK_VERS_T(H5O_iterate, 1);
CHECK_VERS_T(H5Z_class, 2);
#elif TEST_API_VERSION == 110
printf("Configured with H5_USE_110_API\n");
CHECK_VERS(H5Acreate, 2);
CHECK_VERS(H5Aiterate, 2);
CHECK_VERS(H5Dcreate, 2);
CHECK_VERS(H5Dopen, 2);
CHECK_VERS(H5Dread_chunk, 1);
CHECK_VERS(H5Eclear, 2);
CHECK_VERS(H5Eget_auto, 2);
CHECK_VERS(H5Eprint, 2);
CHECK_VERS(H5Epush, 2);
CHECK_VERS(H5Eset_auto, 2);
CHECK_VERS(H5Ewalk, 2);
CHECK_VERS(H5Fget_info, 2);
CHECK_VERS(H5Gcreate, 2);
CHECK_VERS(H5Gopen, 2);
CHECK_VERS(H5Iregister_type, 1);
CHECK_VERS(H5Lget_info, 1);
CHECK_VERS(H5Lget_info_by_idx, 1);
CHECK_VERS(H5Literate, 1);
CHECK_VERS(H5Literate_by_name, 1);
CHECK_VERS(H5Lvisit, 1);
CHECK_VERS(H5Lvisit_by_name, 1);
CHECK_VERS(H5Oget_info, 1);
CHECK_VERS(H5Oget_info_by_idx, 1);
CHECK_VERS(H5Oget_info_by_name, 1);
CHECK_VERS(H5Ovisit, 1);
CHECK_VERS(H5Ovisit_by_name, 1);
CHECK_VERS(H5Pencode, 1);
CHECK_VERS(H5Pget_filter, 2);
CHECK_VERS(H5Pget_filter_by_id, 2);
CHECK_VERS(H5Pinsert, 2);
CHECK_VERS(H5Pregister, 2);
CHECK_VERS(H5Rdereference, 2);
CHECK_VERS(H5Rget_obj_type, 2);
CHECK_VERS(H5Sencode, 1);
CHECK_VERS(H5Tarray_create, 2);
CHECK_VERS(H5Tcommit, 2);
CHECK_VERS(H5Tdecode, 1);
CHECK_VERS(H5Tget_array_dims, 2);
CHECK_VERS(H5Topen, 2);
CHECK_VERS_T(H5E_auto, 2);
CHECK_VERS_T(H5O_info, 1);
CHECK_VERS_T(H5O_iterate, 1);
CHECK_VERS_T(H5Z_class, 2);
#elif TEST_API_VERSION == 112
printf("Configured with H5_USE_112_API\n");
CHECK_VERS(H5Acreate, 2);
CHECK_VERS(H5Aiterate, 2);
CHECK_VERS(H5Dcreate, 2);
CHECK_VERS(H5Dopen, 2);
CHECK_VERS(H5Dread_chunk, 1);
CHECK_VERS(H5Eclear, 2);
CHECK_VERS(H5Eget_auto, 2);
CHECK_VERS(H5Eprint, 2);
CHECK_VERS(H5Epush, 2);
CHECK_VERS(H5Eset_auto, 2);
CHECK_VERS(H5Ewalk, 2);
CHECK_VERS(H5Fget_info, 2);
CHECK_VERS(H5Gcreate, 2);
CHECK_VERS(H5Gopen, 2);
CHECK_VERS(H5Iregister_type, 1);
CHECK_VERS(H5Lget_info, 2);
CHECK_VERS(H5Lget_info_by_idx, 2);
CHECK_VERS(H5Literate, 2);
CHECK_VERS(H5Literate_by_name, 2);
CHECK_VERS(H5Lvisit, 2);
CHECK_VERS(H5Lvisit_by_name, 2);
CHECK_VERS(H5Oget_info, 3);
CHECK_VERS(H5Oget_info_by_idx, 3);
CHECK_VERS(H5Oget_info_by_name, 3);
CHECK_VERS(H5Ovisit, 3);
CHECK_VERS(H5Ovisit_by_name, 3);
CHECK_VERS(H5Pencode, 2);
CHECK_VERS(H5Pget_filter, 2);
CHECK_VERS(H5Pget_filter_by_id, 2);
CHECK_VERS(H5Pinsert, 2);
CHECK_VERS(H5Pregister, 2);
CHECK_VERS(H5Rdereference, 2);
CHECK_VERS(H5Rget_obj_type, 2);
CHECK_VERS(H5Sencode, 2);
CHECK_VERS(H5Tarray_create, 2);
CHECK_VERS(H5Tcommit, 2);
CHECK_VERS(H5Tdecode, 1);
CHECK_VERS(H5Tget_array_dims, 2);
CHECK_VERS(H5Topen, 2);
CHECK_VERS_T(H5E_auto, 2);
CHECK_VERS_T(H5O_info, 2);
CHECK_VERS_T(H5O_iterate, 2);
CHECK_VERS_T(H5Z_class, 2);
#elif TEST_API_VERSION == 114
printf("Configured with H5_USE_114_API\n");
CHECK_VERS(H5Acreate, 2);
CHECK_VERS(H5Aiterate, 2);
CHECK_VERS(H5Dcreate, 2);
CHECK_VERS(H5Dopen, 2);
CHECK_VERS(H5Dread_chunk, 1);
CHECK_VERS(H5Eclear, 2);
CHECK_VERS(H5Eget_auto, 2);
CHECK_VERS(H5Eprint, 2);
CHECK_VERS(H5Epush, 2);
CHECK_VERS(H5Eset_auto, 2);
CHECK_VERS(H5Ewalk, 2);
CHECK_VERS(H5Fget_info, 2);
CHECK_VERS(H5Gcreate, 2);
CHECK_VERS(H5Gopen, 2);
CHECK_VERS(H5Iregister_type, 1);
CHECK_VERS(H5Lget_info, 2);
CHECK_VERS(H5Lget_info_by_idx, 2);
CHECK_VERS(H5Literate, 2);
CHECK_VERS(H5Literate_by_name, 2);
CHECK_VERS(H5Lvisit, 2);
CHECK_VERS(H5Lvisit_by_name, 2);
CHECK_VERS(H5Oget_info, 3);
CHECK_VERS(H5Oget_info_by_idx, 3);
CHECK_VERS(H5Oget_info_by_name, 3);
CHECK_VERS(H5Ovisit, 3);
CHECK_VERS(H5Ovisit_by_name, 3);
CHECK_VERS(H5Pencode, 2);
CHECK_VERS(H5Pget_filter, 2);
CHECK_VERS(H5Pget_filter_by_id, 2);
CHECK_VERS(H5Pinsert, 2);
CHECK_VERS(H5Pregister, 2);
CHECK_VERS(H5Rdereference, 2);
CHECK_VERS(H5Rget_obj_type, 2);
CHECK_VERS(H5Sencode, 2);
CHECK_VERS(H5Tarray_create, 2);
CHECK_VERS(H5Tcommit, 2);
CHECK_VERS(H5Tdecode, 1);
CHECK_VERS(H5Tget_array_dims, 2);
CHECK_VERS(H5Topen, 2);
CHECK_VERS_T(H5E_auto, 2);
CHECK_VERS_T(H5O_info, 2);
CHECK_VERS_T(H5O_iterate, 2);
CHECK_VERS_T(H5Z_class, 2);
#elif TEST_API_VERSION == 200
printf("Configured with H5_USE_200_API\n");
CHECK_VERS(H5Acreate, 2);
CHECK_VERS(H5Aiterate, 2);
CHECK_VERS(H5Dcreate, 2);
CHECK_VERS(H5Dopen, 2);
CHECK_VERS(H5Dread_chunk, 2);
CHECK_VERS(H5Eclear, 2);
CHECK_VERS(H5Eget_auto, 2);
CHECK_VERS(H5Eprint, 2);
CHECK_VERS(H5Epush, 2);
CHECK_VERS(H5Eset_auto, 2);
CHECK_VERS(H5Ewalk, 2);
CHECK_VERS(H5Fget_info, 2);
CHECK_VERS(H5Gcreate, 2);
CHECK_VERS(H5Gopen, 2);
CHECK_VERS(H5Iregister_type, 2);
CHECK_VERS(H5Lget_info, 2);
CHECK_VERS(H5Lget_info_by_idx, 2);
CHECK_VERS(H5Literate, 2);
CHECK_VERS(H5Literate_by_name, 2);
CHECK_VERS(H5Lvisit, 2);
CHECK_VERS(H5Lvisit_by_name, 2);
CHECK_VERS(H5Oget_info, 3);
CHECK_VERS(H5Oget_info_by_idx, 3);
CHECK_VERS(H5Oget_info_by_name, 3);
CHECK_VERS(H5Ovisit, 3);
CHECK_VERS(H5Ovisit_by_name, 3);
CHECK_VERS(H5Pencode, 2);
CHECK_VERS(H5Pget_filter, 2);
CHECK_VERS(H5Pget_filter_by_id, 2);
CHECK_VERS(H5Pinsert, 2);
CHECK_VERS(H5Pregister, 2);
CHECK_VERS(H5Rdereference, 2);
CHECK_VERS(H5Rget_obj_type, 2);
CHECK_VERS(H5Sencode, 2);
CHECK_VERS(H5Tarray_create, 2);
CHECK_VERS(H5Tcommit, 2);
CHECK_VERS(H5Tdecode, 2);
CHECK_VERS(H5Tget_array_dims, 2);
CHECK_VERS(H5Topen, 2);
CHECK_VERS_T(H5E_auto, 2);
CHECK_VERS_T(H5O_info, 2);
CHECK_VERS_T(H5O_iterate, 2);
CHECK_VERS_T(H5Z_class, 2);
#else
#error "TEST_API_VERSION not set to a valid value"
#endif
if (nerrors) {
H5_FAILED();
fprintf(stderr, " %d version check%s failed\n", nerrors, nerrors > 1 ? "s" : "");
return 1;
}
PASSED();
return 0;
}