diff --git a/bin/make_vers b/bin/make_vers index 888520edfb7..e3ee884cbd5 100755 --- a/bin/make_vers +++ b/bin/make_vers @@ -433,6 +433,19 @@ sub parse_line ($) { $curr_sym_number++; } + # For API versions earlier than the function's introduction, + # default to the earliest version (version 1) for maximum compatibility + my $intro_vers = $vers_list[0]; + foreach my $hash_vers (@versions) { + if ($hash_vers < $intro_vers) { + if ($line_type == 1) { + $api_vers_to_function_vers{$hash_vers}{$name} = 1; + } else { + $api_vers_to_type_vers{$hash_vers}{$name} = 1; + } + } + } + # Store the number of symbol versions in a hash table, indexed by the name if ($line_type == 1) { $functions{$name} = $#vers_list + 1; @@ -519,6 +532,160 @@ sub create_doxygen_cmake ($) { close CMAKE; } +############################################################################## +# Create the generated test file for verifying API version defaulting +# +sub create_test ($) { + my $prefix = shift; # Get the prefix for the source file (e.g., "src/") + my $file = "tapi_version_default.c"; + + # Output to test directory (relative to src/) + my $test_dir = $prefix; + $test_dir =~ s/src\/?$/test\//; + + # Validate the substitution succeeded + if ($test_dir eq $prefix && $prefix ne "") { + die "create_test: prefix '$prefix' does not end in 'src/' -- cannot derive test directory"; + } + + # Create test directory if it doesn't exist + if ($test_dir ne "" && ! -d $test_dir) { + mkdir $test_dir or die "unable to create directory: $test_dir"; + } + + # Open new test file + open TEST, ">${test_dir}${file}" or die "unable to create test file: ${test_dir}${file}"; + + # Print copyright and warning + print_copyright(*TEST); + print_warning(*TEST); + + # Print test description + print TEST "/*\n"; + print TEST " * Purpose: Tests that versioned API function macros default to the earliest\n"; + print TEST " * version for functions introduced after the configured global API\n"; + print TEST " * version. For example, with H5_USE_16_API, H5Sencode (introduced\n"; + print TEST " * in v1.8) should map to H5Sencode1, not H5Sencode2.\n"; + print TEST " *\n"; + print TEST " * This test is compiled multiple times with different\n"; + print TEST " * -DH5_USE_*_API and -DTEST_API_VERSION=* flags to verify each\n"; + print TEST " * API version level.\n"; + print TEST " */\n"; + + # Emit preamble that clears all global API version defaults. + # When the project is configured with a default API version (e.g., + # HDF5_DEFAULT_API_VERSION=v16), H5pubconf.h defines H5_USE_16_API_DEFAULT, + # which causes H5version.h to activate H5_USE_16_API. If the test also + # defines -DH5_USE_200_API, both blocks would be active and the earliest + # one wins (setting everything to version 1). To isolate each test to + # exactly one API version, we include H5pubconf.h first (setting its + # include guard), then #undef all API version macros, and re-establish + # only the version under test before including the rest of the headers. + print TEST "/* Include config header first to set its include guard */\n"; + print TEST "#include \"H5pubconf.h\"\n\n"; + print TEST "/* Clear all API version macros that may have been set by the\n"; + print TEST " * global default configuration, so only the version under test\n"; + print TEST " * is active when H5version.h is processed.\n"; + print TEST " */\n"; + foreach my $api_vers (@versions) { + print TEST "#undef H5_USE_${api_vers}_API_DEFAULT\n"; + print TEST "#undef H5_USE_${api_vers}_API\n"; + } + print TEST "\n"; + print TEST "/* Re-establish only the API version under test */\n"; + my $first_preamble = 1; + foreach my $api_vers (@versions) { + if ($first_preamble) { + print TEST "#if TEST_API_VERSION == $api_vers\n"; + $first_preamble = 0; + } + else { + print TEST "#elif TEST_API_VERSION == $api_vers\n"; + } + print TEST " #define H5_USE_${api_vers}_API 1\n"; + } + print TEST "#else\n"; + print TEST " #error \"TEST_API_VERSION not set to a valid value\"\n"; + print TEST "#endif\n\n"; + + print TEST "#include \"h5test.h\"\n\n"; + + # Print CHECK_VERS macro for functions + print TEST "/*\n"; + print TEST " * Helper macro: check that a _vers macro equals an expected value.\n"; + print TEST " */\n"; + print TEST "#define CHECK_VERS(func_name, expected) \\\n"; + print TEST " do { \\\n"; + print TEST " if (func_name##_vers != (expected)) { \\\n"; + print TEST " fprintf(stderr, \"FAIL: %s_vers = %d, expected %d\\n\", \\\n"; + print TEST " #func_name, func_name##_vers, (expected)); \\\n"; + print TEST " nerrors++; \\\n"; + print TEST " } \\\n"; + print TEST " } while (0)\n\n"; + + # Print CHECK_VERS_T macro for typedefs + print TEST "#define CHECK_VERS_T(type_name, expected) \\\n"; + print TEST " do { \\\n"; + print TEST " if (type_name##_t_vers != (expected)) { \\\n"; + print TEST " fprintf(stderr, \"FAIL: %s_t_vers = %d, expected %d\\n\", \\\n"; + print TEST " #type_name, type_name##_t_vers, (expected)); \\\n"; + print TEST " nerrors++; \\\n"; + print TEST " } \\\n"; + print TEST " } while (0)\n\n"; + + # Print main function + print TEST "int\n"; + print TEST "main(void)\n"; + print TEST "{\n"; + print TEST " int nerrors = 0;\n\n"; + print TEST " TESTING(\"API version defaulting for versioned functions\");\n\n"; + + # Generate test sections for each API version + my $first = 1; + foreach my $api_vers (@versions) { + if ($first) { + print TEST "#if TEST_API_VERSION == $api_vers\n"; + $first = 0; + } + else { + print TEST "#elif TEST_API_VERSION == $api_vers\n"; + } + print TEST " printf(\"Configured with H5_USE_${api_vers}_API\\n\");\n\n"; + + # Print checks for all functions at this API version + for my $name (sort keys %{$api_vers_to_function_vers{$api_vers}}) { + my $expected = $api_vers_to_function_vers{$api_vers}{$name}; + print TEST " CHECK_VERS($name, $expected);\n"; + } + print TEST "\n"; + + # Print checks for all typedefs at this API version + for my $name (sort keys %{$api_vers_to_type_vers{$api_vers}}) { + my $expected = $api_vers_to_type_vers{$api_vers}{$name}; + print TEST " CHECK_VERS_T($name, $expected);\n"; + } + print TEST "\n"; + } + + # Close the #if/#elif chain + print TEST "#else\n"; + print TEST "#error \"TEST_API_VERSION not set to a valid value\"\n"; + print TEST "#endif\n\n"; + + # Print result checking and return + print TEST " if (nerrors) {\n"; + print TEST " H5_FAILED();\n"; + print TEST " fprintf(stderr, \" %d version check%s failed\\n\", nerrors, nerrors > 1 ? \"s\" : \"\");\n"; + print TEST " return 1;\n"; + print TEST " }\n\n"; + print TEST " PASSED();\n"; + print TEST " return 0;\n"; + print TEST "}\n"; + + # Close test file + close TEST; +} + ############################################################################## # Read symbol version file (given as command-line argument) in and process it # into internal data structures, then create header files. @@ -551,5 +718,7 @@ for $file (@ARGV) { create_public($prefix); print "Generating 'doxygen/H5version_doxygen.cmake'\n"; create_doxygen_cmake($prefix); + print "Generating 'test/tapi_version_default.c'\n"; + create_test($prefix); } diff --git a/release_docs/CHANGELOG.md b/release_docs/CHANGELOG.md index 13aa32ce1c1..4397a7aba9c 100644 --- a/release_docs/CHANGELOG.md +++ b/release_docs/CHANGELOG.md @@ -65,6 +65,10 @@ We would like to thank the many HDF5 community members who contributed to this r ## Library +### Versioned API functions now default to earliest version for older API settings + + When a global API compatibility version is set (e.g., `H5_USE_16_API`), functions introduced after that version previously defaulted to their latest version, which could break applications. For example, an application using `H5_USE_16_API` that called `H5Sencode()` (introduced in 1.8, versioned in 1.12) would get `H5Sencode2()` instead of `H5Sencode1()`, potentially causing compilation or runtime failures. Versioned functions now default to their earliest (version 1) variant when the configured API level predates the function's introduction, providing maximum compatibility. See issue [#6278](https://github.com/HDFGroup/hdf5/issues/6278). + ## Parallel Library ## Fortran Library diff --git a/src/H5version.h b/src/H5version.h index 92206293022..536f3dbeffd 100644 --- a/src/H5version.h +++ b/src/H5version.h @@ -84,6 +84,10 @@ #define H5Dopen_vers 1 #endif /* !defined(H5Dopen_vers) */ +#if !defined(H5Dread_chunk_vers) + #define H5Dread_chunk_vers 1 +#endif /* !defined(H5Dread_chunk_vers) */ + #if !defined(H5Eclear_vers) #define H5Eclear_vers 1 #endif /* !defined(H5Eclear_vers) */ @@ -108,6 +112,10 @@ #define H5Ewalk_vers 1 #endif /* !defined(H5Ewalk_vers) */ +#if !defined(H5Fget_info_vers) + #define H5Fget_info_vers 1 +#endif /* !defined(H5Fget_info_vers) */ + #if !defined(H5Gcreate_vers) #define H5Gcreate_vers 1 #endif /* !defined(H5Gcreate_vers) */ @@ -116,6 +124,58 @@ #define H5Gopen_vers 1 #endif /* !defined(H5Gopen_vers) */ +#if !defined(H5Iregister_type_vers) + #define H5Iregister_type_vers 1 +#endif /* !defined(H5Iregister_type_vers) */ + +#if !defined(H5Lget_info_vers) + #define H5Lget_info_vers 1 +#endif /* !defined(H5Lget_info_vers) */ + +#if !defined(H5Lget_info_by_idx_vers) + #define H5Lget_info_by_idx_vers 1 +#endif /* !defined(H5Lget_info_by_idx_vers) */ + +#if !defined(H5Literate_vers) + #define H5Literate_vers 1 +#endif /* !defined(H5Literate_vers) */ + +#if !defined(H5Literate_by_name_vers) + #define H5Literate_by_name_vers 1 +#endif /* !defined(H5Literate_by_name_vers) */ + +#if !defined(H5Lvisit_vers) + #define H5Lvisit_vers 1 +#endif /* !defined(H5Lvisit_vers) */ + +#if !defined(H5Lvisit_by_name_vers) + #define H5Lvisit_by_name_vers 1 +#endif /* !defined(H5Lvisit_by_name_vers) */ + +#if !defined(H5Oget_info_vers) + #define H5Oget_info_vers 1 +#endif /* !defined(H5Oget_info_vers) */ + +#if !defined(H5Oget_info_by_idx_vers) + #define H5Oget_info_by_idx_vers 1 +#endif /* !defined(H5Oget_info_by_idx_vers) */ + +#if !defined(H5Oget_info_by_name_vers) + #define H5Oget_info_by_name_vers 1 +#endif /* !defined(H5Oget_info_by_name_vers) */ + +#if !defined(H5Ovisit_vers) + #define H5Ovisit_vers 1 +#endif /* !defined(H5Ovisit_vers) */ + +#if !defined(H5Ovisit_by_name_vers) + #define H5Ovisit_by_name_vers 1 +#endif /* !defined(H5Ovisit_by_name_vers) */ + +#if !defined(H5Pencode_vers) + #define H5Pencode_vers 1 +#endif /* !defined(H5Pencode_vers) */ + #if !defined(H5Pget_filter_vers) #define H5Pget_filter_vers 1 #endif /* !defined(H5Pget_filter_vers) */ @@ -140,6 +200,10 @@ #define H5Rget_obj_type_vers 1 #endif /* !defined(H5Rget_obj_type_vers) */ +#if !defined(H5Sencode_vers) + #define H5Sencode_vers 1 +#endif /* !defined(H5Sencode_vers) */ + #if !defined(H5Tarray_create_vers) #define H5Tarray_create_vers 1 #endif /* !defined(H5Tarray_create_vers) */ @@ -148,6 +212,10 @@ #define H5Tcommit_vers 1 #endif /* !defined(H5Tcommit_vers) */ +#if !defined(H5Tdecode_vers) + #define H5Tdecode_vers 1 +#endif /* !defined(H5Tdecode_vers) */ + #if !defined(H5Tget_array_dims_vers) #define H5Tget_array_dims_vers 1 #endif /* !defined(H5Tget_array_dims_vers) */ @@ -164,6 +232,14 @@ #define H5E_auto_t_vers 1 #endif /* !defined(H5E_auto_t_vers) */ +#if !defined(H5O_info_t_vers) + #define H5O_info_t_vers 1 +#endif /* !defined(H5O_info_t_vers) */ + +#if !defined(H5O_iterate_t_vers) + #define H5O_iterate_t_vers 1 +#endif /* !defined(H5O_iterate_t_vers) */ + #if !defined(H5Z_class_t_vers) #define H5Z_class_t_vers 1 #endif /* !defined(H5Z_class_t_vers) */ @@ -192,6 +268,10 @@ #define H5Dopen_vers 2 #endif /* !defined(H5Dopen_vers) */ +#if !defined(H5Dread_chunk_vers) + #define H5Dread_chunk_vers 1 +#endif /* !defined(H5Dread_chunk_vers) */ + #if !defined(H5Eclear_vers) #define H5Eclear_vers 2 #endif /* !defined(H5Eclear_vers) */ @@ -276,6 +356,10 @@ #define H5Ovisit_by_name_vers 1 #endif /* !defined(H5Ovisit_by_name_vers) */ +#if !defined(H5Pencode_vers) + #define H5Pencode_vers 1 +#endif /* !defined(H5Pencode_vers) */ + #if !defined(H5Pget_filter_vers) #define H5Pget_filter_vers 2 #endif /* !defined(H5Pget_filter_vers) */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7ee9dd28b5d..ec2bace9bc0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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};$<$:${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\") diff --git a/test/CMakeTests.cmake b/test/CMakeTests.cmake index e954e137b0c..91d387f102e 100644 --- a/test/CMakeTests.cmake +++ b/test/CMakeTests.cmake @@ -917,6 +917,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 $ + ) + 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 diff --git a/test/tapi_version_default.c b/test/tapi_version_default.c new file mode 100644 index 00000000000..b14393093f0 --- /dev/null +++ b/test/tapi_version_default.c @@ -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; +}