From 1a9c40557ded06a1069214f46a09d89b2ab0b94e Mon Sep 17 00:00:00 2001 From: jhendersonHDF Date: Wed, 13 Nov 2024 22:08:07 -0600 Subject: [PATCH] Add documentation to h5test testing framework (#5094) * Add documentation to h5test testing framework * Remove header comments in h5test.c in favor of h5test.h documentation --- test/h5test.c | 624 +++++--------------------- test/h5test.h | 1157 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 1212 insertions(+), 569 deletions(-) diff --git a/test/h5test.c b/test/h5test.c index cf89f7afc2f..e3bd8997b05 100644 --- a/test/h5test.c +++ b/test/h5test.c @@ -147,19 +147,9 @@ h5_errors(hid_t estack, void H5_ATTR_UNUSED *client_data) return 0; } -/*------------------------------------------------------------------------- - * Function: h5_delete_test_file - * - * Purpose Clean up temporary test files. - * - * When a test calls h5_fixname() to get a VFD-dependent - * test file name, this function can be used to clean it up. - * - * Return: void - * - * Since this is a cleanup file, we don't care if it fails. - * - *------------------------------------------------------------------------- +/* + * Cleans up a single temporary testing file and does + * NOT close 'fapl' */ void h5_delete_test_file(const char *base_name, hid_t fapl) @@ -178,22 +168,9 @@ h5_delete_test_file(const char *base_name, hid_t fapl) } /* end h5_delete_test_file() */ -/*------------------------------------------------------------------------- - * Function: h5_delete_all_test_files - * - * Purpose Clean up temporary test files. - * - * When a test calls h5_fixname() get a VFD-dependent - * test file name, this function can be used to clean it up. - * - * This function takes an array of filenames that ends with - * a NULL string and cleans them all. - * - * Return: void - * - * Since this is a cleanup file, we don't care if it fails. - * - *------------------------------------------------------------------------- +/* + * Cleans up temporary testing files and does NOT close + * 'fapl' */ void h5_delete_all_test_files(const char *base_name[], hid_t fapl) @@ -203,16 +180,8 @@ h5_delete_all_test_files(const char *base_name[], hid_t fapl) } /* end h5_delete_all_test_files() */ -/*------------------------------------------------------------------------- - * Function: h5_cleanup - * - * Purpose: Cleanup temporary test files. - * base_name contains the list of test file names. - * The file access property list is also closed. - * - * Return: Non-zero if cleanup actions were performed; zero otherwise. - * - *------------------------------------------------------------------------- +/* + * Cleans up temporary testing files and closes 'fapl' */ int h5_cleanup(const char *base_name[], hid_t fapl) @@ -233,14 +202,8 @@ h5_cleanup(const char *base_name[], hid_t fapl) return retval; } /* end h5_cleanup() */ -/*------------------------------------------------------------------------- - * Function: h5_restore_err - * - * Purpose: Restore the default error handler. - * - * Return: N/A - * - *------------------------------------------------------------------------- +/* + * Restores HDF5's default error handler function */ void h5_restore_err(void) @@ -251,19 +214,8 @@ h5_restore_err(void) err_func = NULL; } -/*------------------------------------------------------------------------- - * Function: h5_test_init - * - * Purpose: Performs any special actions before the test begins. - * - * NOTE: This function should normally only be called once - * in a given test, usually at the beginning of main(). It - * is intended for use in the single-file unit tests, not - * testhdf5. - * - * Return: void - * - *------------------------------------------------------------------------- +/* + * Performs test framework initialization */ void h5_test_init(void) @@ -281,24 +233,9 @@ h5_test_init(void) TestExpress_g = h5_get_testexpress(); } /* end h5_test_init() */ -/*------------------------------------------------------------------------- - * Function: h5_fixname - * - * Purpose: Create a file name from a file base name like `test' and - * return it through the FULLNAME (at most SIZE characters - * counting the null terminator). The full name is created by - * prepending the contents of HDF5_PREFIX (separated from the - * base name by a slash) and appending a file extension based on - * the driver supplied, resulting in something like - * `ufs:/u/matzke/test.h5'. - * - * Return: Success: The FULLNAME pointer. - * - * Failure: NULL if BASENAME or FULLNAME is the null - * pointer or if FULLNAME isn't large enough for - * the result. - * - *------------------------------------------------------------------------- +/* + * Creates a VFD-dependent filename from a base filename + * without a suffix and a File Access Property List */ char * h5_fixname(const char *base_name, hid_t fapl, char *fullname, size_t size) @@ -306,21 +243,10 @@ h5_fixname(const char *base_name, hid_t fapl, char *fullname, size_t size) return (h5_fixname_real(base_name, fapl, ".h5", fullname, size, false, false)); } -/*------------------------------------------------------------------------- - * Function: h5_fixname_superblock - * - * Purpose: Like h5_fixname() but returns the name of the file you'd - * open to find the superblock. Useful for when you have to - * open a file with open(2) but the h5_fixname() string - * contains stuff like format strings. - * - * Return: Success: The FULLNAME pointer. - * - * Failure: NULL if BASENAME or FULLNAME is the null - * pointer or if FULLNAME isn't large enough for - * the result. - * - *------------------------------------------------------------------------- +/* + * Creates a VFD-dependent filename for a superblock file + * from a base filename without a suffix and a File Access + * Property List */ char * h5_fixname_superblock(const char *base_name, hid_t fapl_id, char *fullname, size_t size) @@ -328,18 +254,10 @@ h5_fixname_superblock(const char *base_name, hid_t fapl_id, char *fullname, size return (h5_fixname_real(base_name, fapl_id, ".h5", fullname, size, false, true)); } -/*------------------------------------------------------------------------- - * Function: h5_fixname_no_suffix - * - * Purpose: Same as h5_fixname but with no suffix appended - * - * Return: Success: The FULLNAME pointer. - * - * Failure: NULL if BASENAME or FULLNAME is the null - * pointer or if FULLNAME isn't large enough for - * the result. - * - *------------------------------------------------------------------------- +/* + * Creates a VFD-dependent filename without a suffix from a + * base filename without a suffix and a File Access Property + * List */ char * h5_fixname_no_suffix(const char *base_name, hid_t fapl, char *fullname, size_t size) @@ -347,21 +265,9 @@ h5_fixname_no_suffix(const char *base_name, hid_t fapl, char *fullname, size_t s return (h5_fixname_real(base_name, fapl, NULL, fullname, size, false, false)); } -/*------------------------------------------------------------------------- - * Function: h5_fixname_printf - * - * Purpose: Same as h5_fixname but returns a filename that can be passed - * through a printf-style function once before being passed to the file - * driver. Basically, replaces all % characters used by the file - * driver with %%. - * - * Return: Success: The FULLNAME pointer. - * - * Failure: NULL if BASENAME or FULLNAME is the null - * pointer or if FULLNAME isn't large enough for - * the result. - * - *------------------------------------------------------------------------- +/* + * Creates a VFD-dependent printf-style filename from a base + * filename without a suffix and a File Access Property List */ char * h5_fixname_printf(const char *base_name, hid_t fapl, char *fullname, size_t size) @@ -618,20 +524,8 @@ h5_fixname_real(const char *base_name, hid_t fapl, const char *_suffix, char *fu return fullname; } -/*------------------------------------------------------------------------- - * Function: h5_rmprefix - * - * Purpose: This "removes" the MPIO driver prefix part of the file name - * by returning a pointer that points at the non-prefix component - * part of the file name. E.g., - * Input Return - * pfs:/scratch1/dataX /scratch1/dataX - * /scratch2/dataY /scratch2/dataY - * Note that there is no change to the original file name. - * - * Return: Success: a pointer at the non-prefix part. - * - *------------------------------------------------------------------------- +/* + * "Removes" a ':'-delimited prefix from a filename */ H5_ATTR_PURE const char * h5_rmprefix(const char *filename) @@ -646,17 +540,10 @@ h5_rmprefix(const char *filename) return (ret_ptr); } -/*------------------------------------------------------------------------- - * Function: h5_fileaccess - * - * Purpose: Returns a file access template which is the default template - * but with a file driver, VOL connector, or libver bound set - * according to a constant or environment variable - * - * Return: Success: A file access property list - * Failure: H5I_INVALID_HID - * - *------------------------------------------------------------------------- +/* + * Creates and returns a File Access Property List that + * may have a modified File Driver and/or library version + * bounds setting */ hid_t h5_fileaccess(void) @@ -682,17 +569,10 @@ h5_fileaccess(void) return H5I_INVALID_HID; } /* end h5_fileaccess() */ -/*------------------------------------------------------------------------- - * Function: h5_fileaccess_flags - * - * Purpose: Returns a file access template which is the default template - * but with a file driver, VOL connector, or libver bound set - * according to a constant or environment variable - * - * Return: Success: A file access property list - * Failure: H5I_INVALID_HID - * - *------------------------------------------------------------------------- +/* + * Creates and returns a File Access Property List that + * may have a modified File Driver and/or library version + * bounds setting, according to the specified flags */ hid_t h5_fileaccess_flags(unsigned flags) @@ -718,16 +598,10 @@ h5_fileaccess_flags(unsigned flags) return H5I_INVALID_HID; } /* end h5_fileaccess_flags() */ -/*------------------------------------------------------------------------- - * Function: h5_get_vfd_fapl - * - * Purpose: Sets the file driver for a FAPL according to the value - * specified in the environment variable "HDF5_DRIVER" or - * "HDF5_TEST_DRIVER". - * - * Return: Non-negative on success/Negative on failure - * - *------------------------------------------------------------------------- +/* + * Modifies the File Driver set on the given File + * Access Property List according to the HDF5_DRIVER + * or HDF5_TEST_DRIVER environment variables */ herr_t h5_get_vfd_fapl(hid_t fapl) @@ -952,16 +826,10 @@ h5_get_vfd_fapl(hid_t fapl) return -1; } /* end h5_get_vfd_fapl() */ -/*------------------------------------------------------------------------- - * Function: h5_get_libver_fapl - * - * Purpose: Sets the library version bounds for a FAPL according to the - * value in the constant or environment variable "HDF5_LIBVER_BOUNDS". - * - * Return: Success: 0 - * Failure: -1 - * - *------------------------------------------------------------------------- +/* + * Modifies the library version bounds set on the given + * File Access Property List according to the HDF5_LIBVER_BOUNDS + * environment variable */ herr_t h5_get_libver_fapl(hid_t fapl) @@ -1012,23 +880,7 @@ h5_get_libver_fapl(hid_t fapl) } /* end h5_get_libver_fapl() */ /* - * Returns the current TestExpress functionality setting. - * Valid values returned are as follows: - * - * 0: Exhaustive run - * Tests should take as long as necessary - * 1: Full run. Default value if H5_TEST_EXPRESS_LEVEL_DEFAULT - * and the HDF5TestExpress environment variable are not defined - * Tests should take no more than 30 minutes - * 2: Quick run - * Tests should take no more than 10 minutes - * 3: Smoke test. - * Default if the HDF5TestExpress environment variable is set to - * a value other than 0-3 - * Tests should take less than 1 minute - * - * If the value returned is > 1, then test programs should - * skip some tests so that they complete sooner. + * Returns the current TestExpress functionality level */ int h5_get_testexpress(void) @@ -1070,10 +922,7 @@ h5_get_testexpress(void) } /* - * Sets the level of express testing to the given value. Negative - * values are set to the default TestExpress setting (1). Values - * larger than the highest TestExpress setting (3) are set to the - * highest TestExpress setting. + * Sets the TextExpress functionality level */ void h5_set_testexpress(int new_val) @@ -1086,14 +935,8 @@ h5_set_testexpress(int new_val) TestExpress_g = new_val; } -/*------------------------------------------------------------------------- - * Function: h5_no_hwconv - * - * Purpose: Turn off hardware data type conversions. - * - * Return: void - * - *------------------------------------------------------------------------- +/* + * Temporarily turns off hardware data type conversions */ void h5_no_hwconv(void) @@ -1101,14 +944,9 @@ h5_no_hwconv(void) H5Tunregister(H5T_PERS_HARD, NULL, (hid_t)-1, (hid_t)-1, NULL); } -/*------------------------------------------------------------------------- - * Function: h5_show_hostname - * - * Purpose: Show hostname. Show process ID if in MPI environment. - * - * Return: void - * - *------------------------------------------------------------------------- +/* + * Prints out hostname(1)-like information, MPI process + * IDs and/or thread IDs */ void h5_show_hostname(void) @@ -1310,15 +1148,8 @@ h5_dump_info_object(MPI_Info info) } #endif /* H5_HAVE_PARALLEL */ -/*------------------------------------------------------------------------- - * Function: h5_get_file_size - * - * Purpose: Get the current size of a file (in bytes) - * - * Return: Success: Size of file in bytes - * Failure: -1 - * - *------------------------------------------------------------------------- +/* + * Gets the current size of a file (in bytes) */ /* Disable warning for "format not a string literal" here -QAK */ /* @@ -1482,18 +1313,9 @@ h5_get_file_size(const char *filename, hid_t fapl) H5_GCC_CLANG_DIAG_ON("format-nonliteral") #ifdef H5_HAVE_FILTER_SZIP - -/*------------------------------------------------------------------------- - * Function: h5_szip_can_encode - * - * Purpose: Retrieve the filter config flags for szip, tell if - * encoder is available. - * - * Return: 1: decode+encode is enabled - * 0: only decode is enabled - * -1: other - * - *------------------------------------------------------------------------- +/* + * Determines whether the library's SZIP filter has encoding/decoding + * functionality enabled. */ int h5_szip_can_encode(void) @@ -1524,23 +1346,10 @@ h5_szip_can_encode(void) #endif /* H5_HAVE_FILTER_SZIP */ #ifdef H5_HAVE_PARALLEL -/*------------------------------------------------------------------------- - * Function: getenv_all - * - * Purpose: Used to get the environment that the root MPI task has. - * name specifies which environment variable to look for - * val is the string to which the value of that environment - * variable will be copied. - * - * NOTE: The pointer returned by this function is only - * valid until the next call to getenv_all and the data - * stored there must be copied somewhere else before any - * further calls to getenv_all take place. - * - * Return: pointer to a string containing the value of the environment variable - * NULL if the variable doesn't exist in task 'root's environment. - * - *------------------------------------------------------------------------- +/* + * Retrieves the value of an environment variable and broadcasts + * it to other MPI processes to ensure all processes see the same + * value */ char * getenv_all(MPI_Comm comm, int root, const char *name) @@ -1607,20 +1416,8 @@ getenv_all(MPI_Comm comm, int root, const char *name) #endif -/*------------------------------------------------------------------------- - * Function: h5_make_local_copy - * - * Purpose: Make copy of file. Some tests write to data files under that - * are under version control. Those tests should make a copy of - * the versioned file and write to the copy. This function - * prepends srcdir to the name of the file to be copied and uses - * the name of the copy as is. - * - * Return: Success: 0 - * - * Failure: -1 - * - *------------------------------------------------------------------------- +/* + * Makes a byte-for-byte copy of a file */ int h5_make_local_copy(const char *origfilename, const char *local_copy_name) @@ -1692,20 +1489,12 @@ h5_verify_cached_stabs_cb(hid_t oid, const char H5_ATTR_UNUSED *name, const H5O_ return SUCCEED; } /* end h5_verify_cached_stabs_cb() */ -/*------------------------------------------------------------------------- - * Function: h5_verify_cached_stabs - * - * Purpose: Verifies that all groups in every file in base_name have - * their symbol table information cached (if present, and if - * the parent group also uses a symbol table). Does not - * check that the root group's symbol table information is - * cached in the superblock. - * - * Return: Success: 0 - * - * Failure: -1 - * - *------------------------------------------------------------------------- +/* + * Checks a list of files to ensure that groups in those files + * have their symbol table information cached, if present and + * if their parent group also uses a symbol table. Does not + * check that the root group's symbol table information is + * cached in the superblock. */ herr_t h5_verify_cached_stabs(const char *base_name[], hid_t fapl) @@ -1751,26 +1540,8 @@ h5_verify_cached_stabs(const char *base_name[], hid_t fapl) return -1; } -/*------------------------------------------------------------------------- - * Function: h5_send_message - * - * Purpose: Sends the specified signal. - * - * In terms of this test framework, a signal consists of a file - * on disk. Since there are multiple processes that need to - * communicate with each other, they do so by writing and - * reading signal files on disk, the names and contents of - * which are used to inform a process about when it can - * proceed and what it should do next. - * - * This function writes a signal file. The first argument is - * the name of the signal file, and the second and third - * arguments are the contents of the first two lines of the - * signal file. The last two arguments may be NULL. - * - * Return: void - * - *------------------------------------------------------------------------- +/* + * "Sends" a message to another testing process using a temporary file */ void h5_send_message(const char *send, const char *arg1, const char *arg2) @@ -1799,29 +1570,8 @@ h5_send_message(const char *send, const char *arg1, const char *arg2) rename(TMP_SIGNAL_FILE, send); } /* h5_send_message() */ -/*------------------------------------------------------------------------- - * Function: h5_wait_message - * - * Purpose: Waits for the specified signal. - * - * In terms of this test framework, a signal consists of a file - * on disk. Since there are multiple processes that need to - * communicate with each other, they do so by writing and - * reading signal files on disk, the names and contents of - * which are used to inform a process about when it can - * proceed and what it should do next. - * - * This function continuously attempts to read the specified - * signal file from disk, and only continues once it has - * successfully done so (i.e., only after another process has - * called the "h5_send_message" function to write the signal file). - * This function will then immediately remove the file (i.e., - * to indicate that it has been received and can be reused), - * and then exits, allowing the calling function to continue. - * - * Return: void - * - *------------------------------------------------------------------------- +/* + * Waits for a message from another testing process to be available */ herr_t h5_wait_message(const char *waitfor) @@ -1962,25 +1712,9 @@ static const H5FD_class_t H5FD_dummy_g = { H5FD_FLMAP_DICHOTOMY /* fl_map */ }; -/*------------------------------------------------------------------------- - * Function: h5_get_dummy_vfd_class() - * - * Purpose: Returns a disposable, generally non-functional, - * VFD class struct. - * - * In some of the test code, we need a disposable VFD but - * we don't want to mess with the real VFDs and we also - * don't have access to the internals of the real VFDs (which - * use static globals and functions) to easily duplicate - * them (e.g.: for testing VFD ID handling). - * - * This API call will return a pointer to a VFD class that - * can be used to construct a test VFD using H5FDregister(). - * - * Return: Success: A pointer to a VFD class struct - * Failure: NULL - * - *------------------------------------------------------------------------- +/* + * Returns a disposable, generally non-functional, + * VFD class struct. */ H5FD_class_t * h5_get_dummy_vfd_class(void) @@ -2002,25 +1736,9 @@ h5_get_dummy_vfd_class(void) return NULL; } /* h5_get_dummy_vfd_class */ -/*------------------------------------------------------------------------- - * Function: h5_get_dummy_vol_class() - * - * Purpose: Returns a disposable, generally non-functional, - * VOL class struct. - * - * In some of the test code, we need a disposable VOL connector - * but we don't want to mess with the real VFDs and we also - * don't have access to the internals of the real VOL connectors - * (which use static globals and functions) to easily duplicate - * them (e.g.: for testing VOL connector ID handling). - * - * This API call will return a pointer to a VOL class that - * can be used to construct a test VOL using H5VLregister_connector(). - * - * Return: Success: A pointer to a VOL class struct - * Failure: NULL - * - *------------------------------------------------------------------------- +/* + * Returns a disposable, generally non-functional, + * VOL class struct. */ H5VL_class_t * h5_get_dummy_vol_class(void) @@ -2045,14 +1763,9 @@ h5_get_dummy_vol_class(void) return NULL; } /* h5_get_dummy_vol_class */ -/*------------------------------------------------------------------------- - * Function: h5_get_version_string - * - * Purpose: Get the string that corresponds to the libvery version bound. - * - * Return: The string - * - *------------------------------------------------------------------------- +/* + * Get the canonical string that corresponds to the + * given library version bound */ H5_ATTR_PURE const char * h5_get_version_string(H5F_libver_t libver) @@ -2060,15 +1773,8 @@ h5_get_version_string(H5F_libver_t libver) return (LIBVER_NAMES[libver]); } /* end of h5_get_version_string */ -/*------------------------------------------------------------------------- - * Function: h5_compare_file_bytes() - * - * Purpose: Helper function to compare two files byte-for-byte - * - * Return: Success: 0, if files are identical - * Failure: -1, if files differ - * - *------------------------------------------------------------------------- +/* + * Performs a byte-for-byte comparison between two files */ int h5_compare_file_bytes(char *f1name, char *f2name) @@ -2196,16 +1902,8 @@ H5_get_srcdir(void) return (NULL); } /* end H5_get_srcdir() */ -/*------------------------------------------------------------------------- - * Function: h5_duplicate_file_by_bytes - * - * Purpose: Duplicate a file byte-for-byte at filename/path 'orig' - * to a new (or replaced) file at 'dest'. - * - * Return: Success: 0, completed successfully - * Failure: -1 - * - *------------------------------------------------------------------------- +/* + * Makes a byte-for-byte copy of a file */ int h5_duplicate_file_by_bytes(const char *orig, const char *dest) @@ -2263,16 +1961,8 @@ h5_duplicate_file_by_bytes(const char *orig, const char *dest) return ret_value; } /* end h5_duplicate_file_by_bytes() */ -/*------------------------------------------------------------------------- - * Function: h5_check_if_file_locking_enabled - * - * Purpose: Checks if file locking is enabled on this file system. - * - * Return: SUCCEED/FAIL - * are_enabled will be false if file locking is disabled on - * the file system of if there were errors. - * - *------------------------------------------------------------------------- +/* + * Checks if file locking is enabled on this file system. */ herr_t h5_check_if_file_locking_enabled(bool *is_enabled) @@ -2321,20 +2011,9 @@ h5_check_if_file_locking_enabled(bool *is_enabled) return FAIL; } /* end h5_check_if_file_locking_enabled() */ -/*------------------------------------------------------------------------- - * Function: h5_check_file_locking_env_var - * - * Purpose: Checks if the HDF5_USE_FILE_LOCKING file locking - * environment variable is set and parses its value if so. - * - * If the environment variable is not set, both `use_locks` - * and `ignore_disabled_locks` will be set to FAIL to indicate - * this. Otherwise, they will each be set appropriately based - * on the setting for the environment variable. - * - * Return: Nothing - * - *------------------------------------------------------------------------- +/* + * Checks if the HDF5_USE_FILE_LOCKING file locking + * environment variable is set and parses its value if so. */ void h5_check_file_locking_env_var(htri_t *use_locks, htri_t *ignore_disabled_locks) @@ -2364,34 +2043,10 @@ h5_check_file_locking_env_var(htri_t *use_locks, htri_t *ignore_disabled_locks) } } -/*------------------------------------------------------------------------- - * Function: h5_using_native_vol - * - * Purpose: Checks if the VOL connector being used is (or the VOL - * connector stack being used resolves to) the native VOL - * connector. Either or both of fapl_id and obj_id may be - * provided, but checking of obj_id takes precedence. - * H5I_INVALID_HID should be specified for the parameter that - * is not provided. - * - * obj_id must be the ID of an HDF5 object that is accessed - * with the VOL connector to check. If obj_id is provided, the - * entire VOL connector stack is checked to see if it resolves - * to the native VOL connector. If only fapl_id is provided, - * only the top-most VOL connector set on fapl_id is checked - * against the native VOL connector. - * - * The HDF5_VOL_CONNECTOR environment variable is not checked - * here, as that only overrides the setting for the default - * File Access Property List, which may not be the File Access - * Property List used for accessing obj_id. There is also - * complexity in determining whether the connector stack - * resolves to the native VOL connector when the only - * information available is a string. - * - * Return: Non-negative on success/Negative on failure - * - *------------------------------------------------------------------------- +/* + * Checks if the VOL connector being used is (or the VOL + * connector stack being used resolves to) the native VOL + * connector. */ herr_t h5_using_native_vol(hid_t fapl_id, hid_t obj_id, bool *is_native_vol) @@ -2444,15 +2099,9 @@ h5_using_native_vol(hid_t fapl_id, hid_t obj_id, bool *is_native_vol) return ret_value; } -/*------------------------------------------------------------------------- - * Function: h5_get_test_driver_name - * - * Purpose: Checks the HDF5_DRIVER and HDF5_TEST_DRIVER environment - * variables to see if a driver name has been set for testing. - * - * Return: Driver name if set/NULL otherwise - * - *------------------------------------------------------------------------- +/* + * Checks the HDF5_DRIVER and HDF5_TEST_DRIVER environment + * variables to see if a driver name has been set for testing. */ const char * h5_get_test_driver_name(void) @@ -2469,17 +2118,9 @@ h5_get_test_driver_name(void) return H5_DEFAULT_VFD_NAME; } -/*------------------------------------------------------------------------- - * Function: h5_using_default_driver - * - * Purpose: Checks if the specified VFD name matches the library's - * default VFD. If `drv_name` is NULL, the HDF5_DRIVER and - * HDF5_TEST_DRIVER environment variables are checked instead - * (if set). - * - * Return: true/false - * - *------------------------------------------------------------------------- +/* + * Checks if the specified VFD name matches the library's + * default VFD. */ bool h5_using_default_driver(const char *drv_name) @@ -2497,19 +2138,9 @@ h5_using_default_driver(const char *drv_name) return ret_val; } -/*------------------------------------------------------------------------- - * Function: h5_using_parallel_driver - * - * Purpose: Checks if the current VFD set on the given FAPL is a - * parallel-enabled VFD (The MPI I/O VFD, for example). - * - * This is mostly useful for avoiding tests that use features - * which are not currently supported for parallel HDF5, such - * as writing of VL or region reference datatypes. - * - * Return: Non-negative on success/Negative on failure - * - *------------------------------------------------------------------------- +/* + * Checks if the current VFD set on the given FAPL is a + * parallel-enabled VFD (The MPI I/O VFD, for example). */ herr_t h5_using_parallel_driver(hid_t fapl_id, bool *driver_is_parallel) @@ -2535,24 +2166,9 @@ h5_using_parallel_driver(hid_t fapl_id, bool *driver_is_parallel) return ret_value; } -/*------------------------------------------------------------------------- - * Function: h5_driver_is_default_vfd_compatible - * - * Purpose: Checks if the current VFD set on the given FAPL creates a - * file that is compatible with the default VFD. Some examples - * are the core and MPI I/O drivers. Some counterexamples are - * the multi and family drivers, which split the HDF5 file - * into several different files. - * - * This routine is helpful for skipping tests that use - * pre-generated files. VFDs that create files which aren't - * compatible with the default VFD will generally not be able - * to open these pre-generated files and those particular - * tests will fail. - * - * Return: Non-negative on success/Negative on failure - * - *------------------------------------------------------------------------- +/* + * Checks if the current VFD set on the given FAPL creates a + * file that is compatible with the default VFD. */ herr_t h5_driver_is_default_vfd_compatible(hid_t fapl_id, bool *default_vfd_compatible) @@ -2578,31 +2194,9 @@ h5_driver_is_default_vfd_compatible(hid_t fapl_id, bool *default_vfd_compatible) return ret_value; } /* end h5_driver_is_default_vfd_compatible() */ -/*------------------------------------------------------------------------- - * Function: h5_driver_uses_multiple_files - * - * Purpose: Checks if the specified VFD name matches a driver that - * stores data using multiple files. - * - * The following flags can be used to control what types of - * drivers are checked for by this routine: - * - * H5_EXCLUDE_MULTIPART_DRIVERS - This flag excludes any - * drivers which store data using multiple files which, - * together, make up a single logical file. These are - * drivers like the split, multi and family drivers. - * - * H5_EXCLUDE_NON_MULTIPART_DRIVERS - This flag excludes any - * drivers which store data using multiple files which are - * separate logical files. The splitter driver is an example - * of this type of driver. - * - * Eventually, this should become a VFD feature flag so this - * check is less fragile. - * - * Return: true/false - * - *------------------------------------------------------------------------- +/* + * Checks if the specified VFD name matches a driver that + * stores data using multiple files. */ bool h5_driver_uses_multiple_files(const char *drv_name, unsigned flags) diff --git a/test/h5test.h b/test/h5test.h index 006b56e1b11..90a4e2aee2f 100644 --- a/test/h5test.h +++ b/test/h5test.h @@ -215,77 +215,1126 @@ extern "C" { #define h5_free_const(mem) free((void *)(uintptr_t)mem) #endif -/* Generally useful testing routines */ -H5TEST_DLL int h5_cleanup(const char *base_name[], hid_t fapl); -H5TEST_DLL char *h5_fixname(const char *base_name, hid_t fapl, char *fullname, size_t size); -H5TEST_DLL char *h5_fixname_superblock(const char *base_name, hid_t fapl, char *fullname, size_t size); -H5TEST_DLL char *h5_fixname_no_suffix(const char *base_name, hid_t fapl, char *fullname, size_t size); -H5TEST_DLL char *h5_fixname_printf(const char *base_name, hid_t fapl, char *fullname, size_t size); -H5TEST_DLL hid_t h5_fileaccess(void); -H5TEST_DLL hid_t h5_fileaccess_flags(unsigned flags); -H5TEST_DLL void h5_no_hwconv(void); -H5TEST_DLL const char *h5_rmprefix(const char *filename); -H5TEST_DLL void h5_restore_err(void); -H5TEST_DLL void h5_show_hostname(void); -H5TEST_DLL h5_stat_size_t h5_get_file_size(const char *filename, hid_t fapl); -H5TEST_DLL int h5_make_local_copy(const char *origfilename, const char *local_copy_name); -H5TEST_DLL herr_t h5_verify_cached_stabs(const char *base_name[], hid_t fapl); -H5TEST_DLL H5FD_class_t *h5_get_dummy_vfd_class(void); -H5TEST_DLL H5VL_class_t *h5_get_dummy_vol_class(void); -H5TEST_DLL const char *h5_get_version_string(H5F_libver_t libver); -H5TEST_DLL int h5_compare_file_bytes(char *fname1, char *fname2); -H5TEST_DLL int h5_duplicate_file_by_bytes(const char *orig, const char *dest); -H5TEST_DLL herr_t h5_check_if_file_locking_enabled(bool *are_enabled); -H5TEST_DLL void h5_check_file_locking_env_var(htri_t *use_locks, htri_t *ignore_disabled_locks); -H5TEST_DLL herr_t h5_using_native_vol(hid_t fapl_id, hid_t obj_id, bool *is_native_vol); -H5TEST_DLL const char *h5_get_test_driver_name(void); -H5TEST_DLL bool h5_using_default_driver(const char *drv_name); -H5TEST_DLL herr_t h5_using_parallel_driver(hid_t fapl_id, bool *driver_is_parallel); -H5TEST_DLL herr_t h5_driver_is_default_vfd_compatible(hid_t fapl_id, bool *default_vfd_compatible); -H5TEST_DLL bool h5_driver_uses_multiple_files(const char *drv_name, unsigned flags); - -/* Random number functions that don't modify the underlying rand/random state. - * These use rand_r with a state pointer under the hood. The state is always - * initialized to the same value so that each process in the parallel tests - * always gets the same sequence. - */ -H5TEST_DLL int h5_local_rand(void); -H5TEST_DLL void h5_local_srand(unsigned int seed); +/* Extern global variables */ +H5TEST_DLLVAR size_t n_tests_run_g; +H5TEST_DLLVAR size_t n_tests_passed_g; +H5TEST_DLLVAR size_t n_tests_failed_g; +H5TEST_DLLVAR size_t n_tests_skipped_g; +H5TEST_DLLVAR uint64_t vol_cap_flags_g; + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Performs test framework initialization + * + * \return nothing + * + * \details h5_test_init() performs test initialization actions, such as + * setting the TestExpress level setting, and should be called + * toward the beginning of the main() function in a test program. + * + */ +H5TEST_DLL void h5_test_init(void); -/* Functions that will replace components of a FAPL */ +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Restores HDF5's default error handling function + * + * \return nothing + * + * \details h5_restore_err() restores HDF5's default error handling function + * after its temporary replacement by h5_test_init(), which sets the + * error handling function to its own error handling callback + * function instead of the default function. + * + * \see h5_test_init() + * + */ +H5TEST_DLL void h5_restore_err(void); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Returns the current TestExpress level setting + * + * \return Returns the current TestExpress level setting + * + * \details h5_get_testexpress() returns the current TestExpress level + * setting, which determines whether a test program should expedite + * testing by skipping some tests. If the TestExpress level has not + * yet been set, it will be initialized to the default value + * (currently level 1, unless overridden at configuration time). The + * different TestExpress level settings have the following meanings: + * + * + 0 - Tests should take as long as necessary + * + 1 - Tests should take no more than 30 minutes + * + 2 - Tests should take no more than 10 minutes + * + 3 (or higher) - Tests should take no more than 1 minute + * + * If the TestExpress level setting is not yet initialized, this + * function will first set a local variable to the value of the + * #H5_TEST_EXPRESS_LEVEL_DEFAULT macro, if it has been defined. If + * the environment variable "HDF5TestExpress" is defined, its value + * will override the local variable's value. Acceptable values for + * the environment variable are the strings "0", "1" and "2"; any + * other string will cause the variable to be set to the value 3. + * Once the value for the local variable has been determined, + * h5_get_testexpress() returns that value. + * + * \see h5_set_testexpress() + * + */ +H5TEST_DLL int h5_get_testexpress(void); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Sets the current TestExpress level setting + * + * \param[in] new_val The new level to set the TestExpress setting to + * + * \return nothing + * + * \details h5_set_testexpress() sets the current TestExpress level setting + * to the value specified in \p new_val. If \p new_val is negative, + * the TestExpress level is set to the default value (currently + * level 1, unless overridden at configuration time). If \p new_val + * is greater than the highest TestExpress level (3), it is set to + * the highest TestExpress level. + * + * \see h5_get_testexpress() + * + */ +H5TEST_DLL void h5_set_testexpress(int new_val); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Creates a File Access Property List for use in tests + * + * \return \hid_t{file access property list} + * + * \details h5_fileaccess() is a wrapper function around h5_get_vfd_fapl() + * and h5_get_libver_fapl() which creates and returns a File Access + * Property List that has potentially been configured with a + * non-default file driver and library version bounds setting. + * Calling h5_fileaccess() is the primary way that tests should + * obtain a File Access Property List to use, unless the usage of + * non-default VFDs would be problematic for that test. + * + * \see h5_fileaccess_flags(), h5_get_vfd_fapl(), h5_get_libver_fapl() + * + */ +H5TEST_DLL hid_t h5_fileaccess(void); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Creates a File Access Property List for use in tests + * + * \param[in] flags Flags controlling which parts of the created File Access + * Property List will be modified + * + * \return \hid_t{file access property list} + * + * \details h5_fileaccess_flags() is a counterpart to h5_fileaccess() which + * allows the caller to specify which parts of the File Access + * Property List should be modified after it is created. \p flags + * may be specified as one of the following macro values: + * + * #H5_FILEACCESS_VFD - specifies that the file driver of the FAPL + * should be modified + * #H5_FILEACCESS_LIBVER - specifies that the library version bounds + * setting of the FAPL should be modified + * + * \p flags can also be specified as a bit-wise OR of these values, + * in which case behavior is equivalent to h5_fileaccess(). + * + * \see h5_fileaccess(), h5_get_vfd_fapl(), h5_get_libver_fapl() + * + */ +H5TEST_DLL hid_t h5_fileaccess_flags(unsigned flags); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Modifies the Virtual File Driver set on a File Access Property List + * + * \param[in] fapl_id File Access Property List to modify + * + * \return \herr_t + * + * \details h5_get_vfd_fapl() modifies the File Access Property List + * specified in \p fapl_id by setting a new Virtual File Driver on + * it with default configuration values. The Virtual File Driver to + * be used is chosen according to the value set for either the + * HDF5_DRIVER or HDF5_TEST_DRIVER environment variable, with + * preference given to HDF5_DRIVER. These environment variables may + * be set to one of the following strings: + * + * + "sec2" - Default sec2 driver; no extra configuration supplied + * + "stdio" - C STDIO driver; no configuration supplied + * + "core" - In-memory driver; 1MiB increment size and backing + * store enabled + * + "core_paged" - In-memory driver; 1MiB increment size and + * backing store enabled; write tracking enabled + * and 4KiB page size + * + "split" - Multi driver with the file's metadata being placed + * into a file with a ".meta" suffix and the file's raw + * data being placed into a file with a ".raw" suffix + * + "multi" - Multi driver with the file data being placed into + * several different files with the suffixes "m.h5" + * (metadata), "s.h5" (superblock, userblock and driver + * info data), "b.h5" (b-tree data), "r.h5" (dataset raw + * data), "g.h5" (global heap data), "l.h5" (local heap + * data) and "o.h5" (object header data) + * + "family" - Family driver with a family file size of 100MiB and + * with a default File Access Property List used for + * accessing the family file members. A different + * family file size can be specified in the environment + * variable as an integer value of bytes separated from + * the string "family" with whitespace, e.g. + * "family 52428800" would specify a family file size + * of 50MiB. + * + "log" - Log driver using stderr for output, with the + * #H5FD_LOG_LOC_IO and #H5FD_LOG_ALLOC flags set and 0 + * for the buffer size. A different set of flags may be + * specified for the driver as an integer value + * (corresponding to a bit-wise OR of flags) separated + * from the string "log" with whitespace, e.g. "log 14" + * would equate to the flag #H5FD_LOG_LOC_IO}. + * + "direct" - Direct driver with a 4KiB block size, a 32KiB copy + * buffer size and a 1KiB memory alignment setting. If + * the direct driver is not enabled when HDF5 is built, + * h5_get_vfd_fapl() will return an error. + * + "splitter" - Splitter driver using the default (sec2) VFD for + * both the read/write and write-only channels, an + * empty log file path and set to not ignore errors + * on the write-only channel + * + "onion" - support not currently implemented; will cause + * h5_get_vfd_fapl() to return an error. + * + "subfiling" - Subfiling driver with a default configuration of + * 1 I/O concentrator per node, a 32MiB stripe size + * and using the IOC driver with 4 worker threads. + * MPI_COMM_WORLD and MPI_INFO_NULL are used for the + * MPI parameters. + * + "mpio" - MPI I/O driver with MPI_COMM_WORLD and MPI_INFO_NULL + * used for the MPI parameters. + * + "mirror" - support not currently implemented; will cause + * h5_get_vfd_fapl() to return an error. + * + "hdfs" - support not currently implemented; will cause + * h5_get_vfd_fapl() to return an error. + * + "ros3" - support not currently implemented; will cause + * h5_get_vfd_fapl() to return an error. + * + * Other values for the environment variables will cause + * h5_get_vfd_fapl() to return an error. + * + */ H5TEST_DLL herr_t h5_get_vfd_fapl(hid_t fapl_id); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Modifies the Library Version bounds set on a File Access Property + * List + * + * \param[in] fapl_id File Access Property List to modify + * + * \return \herr_t + * + * \details h5_get_libver_fapl() modifies the File Access Property List + * specified in \p fapl_id by setting library version bound values + * on it according to the value set for the HDF5_LIBVER_BOUNDS + * environment variable. Currently, the only valid value for this + * environment variable is the string "latest", which will cause + * this function to set the low and high version bounds both to + * #H5F_LIBVER_LATEST. Other values for the environment variable + * will cause this function to fail and return a negative value. + * + */ H5TEST_DLL herr_t h5_get_libver_fapl(hid_t fapl_id); -/* fapl must be closed by caller */ -H5TEST_DLL void h5_delete_test_file(const char *base_name, hid_t fapl); +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Cleans up temporary testing files + * + * \param[in] base_name Array of filenames, without suffixes, to clean up + * \param[in] fapl File Access Property List to use when deleting files + * + * \return Non-zero if cleanup actions were performed; zero otherwise. + * + * \details h5_cleanup() is used to clean up temporary testing files created + * by a test program. \p base_name is an array of filenames, without + * suffixes, which should be cleaned up. The last entry in + * \p base_name must be NULL. For each filename specified in + * \p base_name, h5_cleanup() will generate a VFD-dependent filename + * with h5_fixname() according to the given File Access Property List + * \p fapl, then call H5Fdelete() on the resulting filename. \p fapl + * will be closed after all files are deleted. If the environment + * variable HDF5_NOCLEANUP has been defined, this function will have + * no effect and \p fapl will be left open. + * + * \see h5_fixname() + * + */ +H5TEST_DLL int h5_cleanup(const char *base_name[], hid_t fapl); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Cleans up temporary testing files + * + * \param[in] base_name Array of filenames, without suffixes, to clean up + * \param[in] fapl File Access Property List to use when deleting files + * + * \return nothing + * + * \details h5_delete_all_test_files() is used to clean up temporary testing + * files created by a test program. \p base_name is an array of + * filenames, without suffixes, which should be cleaned up. The last + * entry in \p base_name must be NULL. For each filename specified in + * \p base_name, this function will generate a VFD-dependent filename + * with h5_fixname() according to the given File Access Property List + * \p fapl, then call H5Fdelete() on the resulting filename. \p fapl + * will NOT be closed after all files are deleted and must be + * closed by the caller. h5_delete_all_test_files() always performs + * file cleanup, regardless of if the HDF5_NOCLEANUP environment + * variable has been defined. + * + * \see h5_fixname() + * + */ H5TEST_DLL void h5_delete_all_test_files(const char *base_name[], hid_t fapl); -/* Performs any special actions before the test begins, - * including resetting the library by closing it */ -H5TEST_DLL void h5_test_init(void); +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Cleans up a single temporary testing file + * + * \param[in] base_name Filename, without a suffix, to clean up + * \param[in] fapl File Access Property List to use when deleting the file + * + * \return nothing + * + * \details h5_delete_test_file() is used to clean up a single temporary + * testing file created by a test program. \p base_name is a + * filename, without a suffix, which should be cleaned up. This + * function will generate a VFD-dependent filename with h5_fixname() + * according to the given File Access Property List \p fapl, then + * call H5Fdelete() on the resulting filename. \p fapl will + * NOT be closed after the file is deleted and must be + * closed by the caller. h5_delete_test_file() always performs + * file cleanup, regardless of if the HDF5_NOCLEANUP environment + * variable has been defined. + * + * \see h5_fixname() + * + */ +H5TEST_DLL void h5_delete_test_file(const char *base_name, hid_t fapl); -/* Functions that deal with expediting testing */ -H5TEST_DLL int h5_get_testexpress(void); -H5TEST_DLL void h5_set_testexpress(int new_val); +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Creates a VFD-dependent filename from a base filename without a + * suffix and a File Access Property List + * + * \param[in] base_name Filename, without a suffix, to use as a base when + * creating the resulting filename + * \param[in] fapl File Access Property List to use when creating the + * resulting filename + * \param[out] fullname Buffer to store the resulting filename in + * \param[in] size Size in bytes of the \p fullname output buffer + * + * \return A pointer to the resulting filename on success; NULL otherwise + * + * \details Given a base filename without a suffix, \p base_name, and a File + * Access Property List, \p fapl, h5_fixname() generates a filename + * according to the configuration set on \p fapl. The resulting + * filename is copied to \p fullname, which is \p size bytes in + * size, including space for the NUL terminator. + * + * h5_fixname() is the primary way that tests should create + * filenames, as it accounts for the possibility of a test being run + * with a non-default Virtual File Driver that may require a + * specialized filename (e.g., the family driver). It also allows + * tests to easily output test files to a different directory by + * setting the HDF5_PREFIX (for serial tests) or HDF5_PARAPREFIX + * (for parallel tests) environment variable. When one of these + * environment variables is set, the contents of the variable are + * prepended to the resulting filename and separated from the + * base filename with a slash. + * + */ +H5TEST_DLL char *h5_fixname(const char *base_name, hid_t fapl, char *fullname, size_t size); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Creates a VFD-dependent filename for a superblock file from a base + * filename without a suffix and a File Access Property List + * + * \param[in] base_name Filename, without a suffix, to use as a base when + * creating the resulting filename + * \param[in] fapl File Access Property List to use when creating the + * resulting filename + * \param[out] fullname Buffer to store the resulting filename in + * \param[in] size Size in bytes of the \p fullname output buffer + * + * \return A pointer to the resulting filename on success; NULL otherwise + * + * \details Given a base filename without a suffix, \p base_name, and a File + * Access Property List, \p fapl, h5_fixname_superblock() generates + * a filename according to the configuration set on \p fapl. The + * resulting filename is copied to \p fullname, which is \p size + * bytes in size, including space for the NUL terminator. + * + * h5_fixname_superblock() is similar to h5_fixname(), but it + * generates the filename that would need to be opened to find the + * logical HDF5 file's superblock. It is useful for when a file is + * to be opened with open(2) but the h5_fixname() string contains + * stuff like format strings. + * + * \see h5_fixname() + * + */ +H5TEST_DLL char *h5_fixname_superblock(const char *base_name, hid_t fapl, char *fullname, size_t size); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Creates a VFD-dependent filename without a suffix from a base + * filename without a suffix and a File Access Property List + * + * \param[in] base_name Filename, without a suffix, to use as a base when + * creating the resulting filename + * \param[in] fapl File Access Property List to use when creating the + * resulting filename + * \param[out] fullname Buffer to store the resulting filename in + * \param[in] size Size in bytes of the \p fullname output buffer + * + * \return A pointer to the resulting filename on success; NULL otherwise + * + * \details Given a base filename without a suffix, \p base_name, and a File + * Access Property List, \p fapl, h5_fixname_no_suffix() generates + * a filename according to the configuration set on \p fapl. The + * resulting filename is copied to \p fullname, which is \p size + * bytes in size, including space for the NUL terminator. + * + * h5_fixname_no_suffix() is similar to h5_fixname(), but generates + * a filename that has no suffix, where the filename from + * h5_fixname() would typically have ".h5". This function is mostly + * useful for getting a new base filename that has been specialized + * according to the VFD set on \p fapl. + * + * \see h5_fixname() + * + */ +H5TEST_DLL char *h5_fixname_no_suffix(const char *base_name, hid_t fapl, char *fullname, size_t size); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Creates a VFD-dependent printf-style filename from a base filename + * without a suffix and a File Access Property List + * + * \param[in] base_name Filename, without a suffix, to use as a base when + * creating the resulting filename + * \param[in] fapl File Access Property List to use when creating the + * resulting filename + * \param[out] fullname Buffer to store the resulting filename in + * \param[in] size Size in bytes of the \p fullname output buffer + * + * \return A pointer to the resulting filename on success; NULL otherwise + * + * \details Given a base filename without a suffix, \p base_name, and a File + * Access Property List, \p fapl, h5_fixname_printf() generates + * a filename according to the configuration set on \p fapl. The + * resulting filename is copied to \p fullname, which is \p size + * bytes in size, including space for the NUL terminator. + * + * h5_fixname_printf() is similar to h5_fixname(), but generates + * a filename that can be passed through a printf-style function to + * obtain the final, processed filename. Essentially, this function + * replaces all % characters that would be used by a file driver + * with %%. + * + * \see h5_fixname() + * + */ +H5TEST_DLL char *h5_fixname_printf(const char *base_name, hid_t fapl, char *fullname, size_t size); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Temporarily turn off hardware datatype conversion pathways during + * testing + * + * \return nothing + * + * \details h5_no_hwconv() temporarily turns off hardware datatype + * conversions in HDF5 during testing by calling H5Tunregister() to + * unregister all the hard conversion pathways. This is useful for + * verifying that datatype conversions for different datatypes still + * work correctly when emulated by the library. + * + */ +H5TEST_DLL void h5_no_hwconv(void); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief "Removes" a ':'-delimited prefix from a filename + * + * \param[in] filename The filename to remove a ':'-delimited prefix from + * + * \return Adjusted pointer into original \p filename buffer + * + * \details h5_rmprefix() "removes" a ':'-delimited prefix from a filename by + * simply searching for the first occurrence of ':' and returning a + * pointer into \p filename just past that occurrence. No actual + * changes are made to the \p filename buffer. + * + * For example, + * + * Input Return + * pfs:/scratch1/dataX /scratch1/dataX + * /scratch2/dataY /scratch2/dataY + * + */ +H5TEST_DLL const char *h5_rmprefix(const char *filename); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Prints out hostname(1)-like information + * + * \return nothing + * + * \details h5_show_hostname() prints out hostname(1)-like information to + * stdout. It also prints out each MPI process' rank value if HDF5 + * is built with parallel functionality enabled and MPI is + * initialized. Otherwise, if HDF5 is built with thread-safe + * functionality enabled and MPI is not initialized or HDF5 is not + * built with parallel functionality enabled, it also prints out + * thread ID values. + * + */ +H5TEST_DLL void h5_show_hostname(void); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Calculates the size of a given file in bytes + * + * \param[in] filename The filename of the file to retrieve the size of + * \param[in] fapl File Access Property List to use when accessing the file + * + * \return The size of the file in bytes + * + * \details h5_get_file_size() returns the size in bytes of the file with the + * given filename \p filename. A File Access Property List specified + * for \p fapl will modify how the file size is calculated. If + * H5P_DEFAULT is passed for \p fapl, stat(2) or the platform + * equivalent is used to determine the file size. Otherwise, the + * calculation depends on the file driver set on \p fapl. For + * example, a FAPL setup with the MPI I/O driver will cause + * h5_get_file_size() to use MPI_File_get_size(), while a FAPL setup + * with the family driver will cause h5_get_file_size() to sum the + * sizes of each of the family files in the overall logical file. + * + */ +H5TEST_DLL h5_stat_size_t h5_get_file_size(const char *filename, hid_t fapl); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Creates a byte-for-byte copy of a file + * + * \param[in] origfilename The filename of the file to make a copy of + * \param[in] local_copy_name The filename for the resulting file that is + * created + * + * \return Non-negative on success; negative on failure + * + * \details Given a file with the filename \p origfilename, + * h5_make_local_copy() makes a byte-for-byte copy of the file, which + * is then named \p local_copy_name, using POSIX I/O. This function + * is useful for making copies of test files that are under version + * control. Tests should make a copy of the original file and then + * operate on the copy. + * + */ +H5TEST_DLL int h5_make_local_copy(const char *origfilename, const char *local_copy_name); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Creates a byte-for-byte copy of a file + * + * \param[in] orig The filename of the file to make a copy of + * \param[in] dest The filename for the resulting file that is created + * + * \return Non-negative on success; negative on failure + * + * \details Given a file with the filename \p orig, + * h5_duplicate_file_by_bytes() makes a byte-for-byte copy of the + * file, which is then named \p dest, using C stdio functions. This + * function is useful for making copies of test files that are under + * version control. Tests should make a copy of the original file + * and then operate on the copy. + * + */ +H5TEST_DLL int h5_duplicate_file_by_bytes(const char *orig, const char *dest); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Performs a byte-for-byte comparison between two files + * + * \param[in] fname1 The filename of the first file for comparison + * \param[in] fname2 The filename of the second file for comparison + * + * \return 0 if the files are identical; non-zero otherwise + * + * \details h5_compare_file_bytes() performs a byte-for-byte comparison + * between two files, \p fname1 and \p fname2. + * + */ +H5TEST_DLL int h5_compare_file_bytes(char *fname1, char *fname2); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Checks a list of files to ensure that groups in those files have + * their symbol table information cached, if present and if their + * parent group also uses a symbol table. + * + * \param[in] base_name Array of filenames, without suffixes, to check + * \param[in] fapl File Access Property List to use when checking files + * + * \return \herr_t + * + * \details h5_verify_cached_stabs() verifies that all groups in a set of + * files have their symbol table information cached, if present and + * if their parent group also uses a symbol table. This function + * does not check that the root group's symbol table information is + * cached in the superblock. \p base_name is an array of filenames + * without suffixes, where the last entry must be NULL. \p fapl is + * the File Access Property List used to open each of the files in + * \p base_name. + * + */ +H5TEST_DLL herr_t h5_verify_cached_stabs(const char *base_name[], hid_t fapl); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Returns a "dummy" VFD class for use in testing + * + * \return On success, returns a pointer to a generally non-functional + * "dummy" VFD class which must be freed by the caller with free(); + * on failure, returns NULL + * + * \details h5_get_dummy_vfd_class() allocates and returns a pointer to a + * "dummy" Virtual File Driver class which is generally + * non-functional. The caller must free the returned pointer with + * free() once it is no longer needed. + * + * In some of the test code, we need a disposable VFD but we don't + * want to mess with the real VFDs and we also don't have access to + * the internals of the real VFDs (which use static globals and + * functions) to easily duplicate them (e.g.: for testing VFD ID + * handling). + * + * This API call will return a pointer to a VFD class that can be + * used to construct a test VFD using H5FDregister(). + * + */ +H5TEST_DLL H5FD_class_t *h5_get_dummy_vfd_class(void); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Returns a "dummy" VOL class for use in testing + * + * \return On success, returns a pointer to a generally non-functional + * "dummy" VOL class which must be freed by the caller with free(); + * on failure, returns NULL + * + * \details h5_get_dummy_vol_class() allocates and returns a pointer to a + * "dummy" Virtual Object Layer connector class which is generally + * non-functional. The caller must free the returned pointer with + * free() once it is no longer needed. + * + * In some of the test code, we need a disposable VOL connector but + * we don't want to mess with the real VFDs and we also don't have + * access to the internals of the real VOL connectors (which use + * static globals and functions) to easily duplicate them (e.g.: for + * testing VOL connector ID handling). + * + * This API call will return a pointer to a VOL class that can be + * used to construct a test VOL using H5VLregister_connector(). + * + */ +H5TEST_DLL H5VL_class_t *h5_get_dummy_vol_class(void); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Translates a given library version bound value into a canonical + * string. + * + * \param[in] libver The library version bound value to translate into a + * canonical string + * + * \return A pointer to a string for the canonical name of the given library + * bound version + * + * \details h5_get_version_string() translates a given library bound version, + * \p libver, into a pointer to a canonical string value which is + * returned. For example, specifying the version H5F_LIBVER_V114 + * would return a pointer to a string "v114". + * + */ +H5TEST_DLL const char *h5_get_version_string(H5F_libver_t libver); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Determines whether file locking is enabled on the system + * + * \param[out] are_enabled Boolean value for whether file locking is enabled + * on the system + * + * \return \herr_t + * + * \details h5_check_if_file_locking_enabled() checks if file locking is + * enabled on the system by creating a temporary file and calling + * flock() or the platform equivalent on it. If this function + * succeeds and \p are_enabled is set to true, file locking is + * enabled on the system. Otherwise, it should be assumed the file + * locking is not enabled or is problematic. + * + */ +H5TEST_DLL herr_t h5_check_if_file_locking_enabled(bool *are_enabled); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Parses the HDF5_USE_FILE_LOCKING environment variable + * + * \param[out] use_locks Tri-value for whether file locking should be used + * \param[out] ignore_disabled_locks Tri-value for whether failures should + * be ignored when attempting to use file + * locking + * + * \return nothing + * + * \details h5_check_file_locking_env_var() parses the value of the + * HDF5_USE_FILE_LOCKING environment variable, if set, and returns + * whether or not file locking should be used and whether or not + * failures should be ignored when attempting to use file locking on + * a system where it is disabled. + * + * When this function returns, \p use_locks is set to one of the + * following values: + * + * true - file locking should be used + * false - file locking should not be used + * FAIL - the HDF5_USE_FILE_LOCKING environment variable was not + * set + * + * When this function returns, \p ignore_disabled_locks is set to + * one of the following values: + * + * true - failures should be ignored when attempting to use file + * locking + * false - failures should NOT be ignored when attempting to use + * file locking + * FAIL - the HDF5_USE_FILE_LOCKING environment variable was not + * set or file locking was specified to not be used + * + */ +H5TEST_DLL void h5_check_file_locking_env_var(htri_t *use_locks, htri_t *ignore_disabled_locks); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Check if the VOL connector being used for testing is (or the VOL + * connector stack being used resolves to) the library's native VOL + * connector + * + * \param[in] fapl_id File Access Property List to use when checking for + * native VOL connector usage + * \param[in] obj_id ID of an HDF5 object to use when checking for native + * VOL connector usage + * \param[out] is_native_vol Boolean value for whether the native VOL + * connector is being used + * + * \return \herr_t + * + * \details h5_using_native_vol() checks if the VOL connector being used for + * testing is (or the VOL connector stack being used resolves to) + * the native VOL connector. Either or both of \p fapl_id and + * \p obj_id may be provided, but checking of \p obj_id takes + * precedence. #H5I_INVALID_HID should be specified for the + * parameter that is not provided, if any. + * + * \p obj_id must be the ID of an HDF5 object that is accessed with + * the VOL connector to check. If \p obj_id is provided, the entire + * VOL connector stack is checked to see if it resolves to the + * native VOL connector. If only \p fapl_id is provided, only the + * top-most VOL connector set on \p fapl_id is checked against the + * native VOL connector. + * + * The HDF5_VOL_CONNECTOR environment variable is not checked here, + * as that only overrides the setting for the default File Access + * Property List, which may not be the File Access Property List + * used for accessing \p obj_id. There is also complexity in + * determining whether the connector stack resolves to the native + * VOL connector when the only information available is a string. + * + */ +H5TEST_DLL herr_t h5_using_native_vol(hid_t fapl_id, hid_t obj_id, bool *is_native_vol); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Returns a pointer to the name of the VFD being used for testing + * + * \return A pointer to the name of the VFD being used for testing + * + * \details h5_get_test_driver_name() returns a pointer to the name of the + * VFD being used for testing. If the environment variable + * HDF5_DRIVER or HDF5_TEST_DRIVER has been set, the value set for + * that variable is returned, with preference given to the + * HDF5_DRIVER environment variable if both are set. Otherwise, the + * name of the library's default VFD is returned. + * + */ +H5TEST_DLL const char *h5_get_test_driver_name(void); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Determines whether the given VFD name matches the name of the + * library's default VFD. + * + * \param[in] drv_name Name of the VFD to check against the library's + * default VFD name + * + * \return True if the given VFD name matches the name of the library's + * default VFD; false otherwise + * + * \details h5_using_default_driver() determines whether a given VFD name, + * \p drv_name, matches the name of the library's default VFD. If + * \p drv_name is NULL, h5_get_test_driver_name() is first used to + * obtain the name of the VFD being used for testing. + * + * \see h5_get_test_driver_name() + * + */ +H5TEST_DLL bool h5_using_default_driver(const char *drv_name); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Determines whether the VFD set on the given File Access Property + * List is a parallel-enabled VFD. + * + * \param[in] fapl_id File Access Property List to use when checking for a + * parallel-enabled VFD + * \param[out] driver_is_parallel Boolean value for whether the VFD set on + * \p fapl_id is a parallel-enabled VFD + * + * \return \herr_t + * + * \details h5_using_parallel_driver() checks if the VFD set on \p fapl_id + * is a parallel-enabled VFD that supports MPI. A VFD must have set + * the H5FD_FEAT_HAS_MPI feature flag to be considered as a + * parallel-enabled VFD. \p fapl_id may be H5P_DEFAULT. + * + */ +H5TEST_DLL herr_t h5_using_parallel_driver(hid_t fapl_id, bool *driver_is_parallel); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Determines whether the VFD set on the given File Access Property + * List creates files that are compatible with the library's default + * VFD. + * + * \param[in] fapl_id File Access Property List to use when checking for a + * VFD that is compatible with the library's default VFD + * \param[out] default_vfd_compatible Boolean value for whether the VFD set + * on \p fapl_id is compatible with the + * library's default VFD + * + * \return \herr_t + * + * \details h5_driver_is_default_vfd_compatible() checks if the VFD set on + * \p fapl_id creates files that are compatible with the library's + * default VFD. For example, the core and MPI I/O drivers create + * files that are compatible with the library's default VFD, while + * the multi and family drivers do not since they split the HDF5 + * file into several different files. This check is helpful for + * skipping tests that use pre-generated testing files. VFDs that + * create files which aren't compatible with the default VFD will + * generally not be able to open these pre-generated files and those + * particular tests will fail. + * + */ +H5TEST_DLL herr_t h5_driver_is_default_vfd_compatible(hid_t fapl_id, bool *default_vfd_compatible); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Determines whether the VFD with the given name matches the name of + * a VFD which stores data using multiple files. + * + * \param[in] drv_name Name of the VFD to check + * \param[in] flags Bitfield of flags controlling how specific the check for + * usage of multiple files is + * + * \return True if the VFD with the given name matches a VFD which stores + * data using multiple files; false otherwise + * + * \details h5_driver_uses_multiple_files() checks if the given VFD name, + * \p drv_name, matches the name of a VFD which stores data using + * multiple files, according to the specified \p flags. If + * \p drv_name is NULL, h5_get_test_driver_name() is called to + * obtain the name of the VFD in use before making the comparison. + * The values for \p flags are as follows: + * + * + H5_EXCLUDE_MULTIPART_DRIVERS - If specified, this flag excludes + * any drivers which store data using multiple files which, + * together, make up a single logical file. These are drivers like + * the split, multi and family drivers. + * + H5_EXCLUDE_NON_MULTIPART_DRIVERS - If specified, this flag + * excludes any drivers which store data using multiple files + * which are separate logical files. The splitter driver is an + * example of this type of driver. + * + * \see h5_get_test_driver_name() + * + */ +H5TEST_DLL bool h5_driver_uses_multiple_files(const char *drv_name, unsigned flags); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Returns a random integer value; analogous to rand(). + * + * \return A random integer value + * + * \details h5_local_rand() is a counterpart for rand() which doesn't modify + * the underlying C/POSIX library rand/random state, as this can + * cause spurious test failures. The state is always initialized to + * the same value so that each process in the parallel tests always + * gets the same sequence. This function is adapted from the example + * code in the POSIX.1-2001 standard. + * + */ +H5TEST_DLL int h5_local_rand(void); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Seeds the random number sequence for h5_local_rand(); analogous to + * srand(). + * + * \param[in] seed Value to use for seeding h5_local_rand()'s random number + * sequence + * + * \return nothing + * + * \details h5_local_srand() seeds the random number sequence generated by + * h5_local_rand(). + * + * \see h5_local_rand() + * + */ +H5TEST_DLL void h5_local_srand(unsigned int seed); #ifdef H5_HAVE_FILTER_SZIP +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Determines whether the library's SZIP filter has encoding/decoding + * functionality enabled. + * + * \return 1 if both encoding and decoding are enabled; 0 if only decoding + * is enabled; negative if only encoding is enabled or if neither + * encoding or decoding are enabled + * + * \details h5_szip_can_encode() returns a value that indicates whether or + * not the library's SZIP filter has encoding/decoding enabled. + * + */ H5TEST_DLL int h5_szip_can_encode(void); #endif /* H5_HAVE_FILTER_SZIP */ #ifdef H5_HAVE_PARALLEL -H5TEST_DLL int h5_set_info_object(void); -H5TEST_DLL void h5_dump_info_object(MPI_Info info); +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Parses the HDF5_MPI_INFO environment variable to create and setup + * an MPI Info object for use in parallel testing + * + * \return 0 on success; non-zero on failure + * + * \details h5_set_info_object() parses the HDF5_MPI_INFO environment + * variable for ";"-delimited key=value pairs and sets them on the + * h5_io_info_g MPI Info global variable for later use by testing. + * + */ +H5TEST_DLL int h5_set_info_object(void); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Prints out the key-value pairs in an MPI Info object + * + * \param[in] info MPI Info object to dump the contents of + * + * \return nothing + * + * \details h5_dump_info_object() iterates through all the keys set on the + * MPI info object, \p info, and prints out each key-value pair to + * stdout. + * + */ +H5TEST_DLL void h5_dump_info_object(MPI_Info info); + +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Retrieves the value of an environment variable and broadcasts it to + * other MPI processes to ensure all processes see the same value + * + * \param[in] comm MPI communicator object to use for collective operations + * \param[in] root MPI rank value to get the value of the environment + * variable on and to broadcast the value from + * \param[in] name Name of the environment variable to retrieve the value of + * + * \return A pointer to the value of the environment variable if that + * environment variable is set; NULL otherwise + * + * \details getenv_all() retrieves the value of the environment variable + * \p name, if set, on the MPI process with rank value \p root on + * the MPI Communicator \p comm, then broadcasts the result to other + * MPI processes in \p comm. This function is collective across the + * MPI Communicator specified in \p comm. If MPI is not initialized, + * this function simply calls getenv(name) and returns a pointer to + * the result. + * + * Note: the pointer returned by this function is only valid + * until the next call to getenv_all() and the data stored there + * must be copied somewhere else before any further calls to + * getenv_all() take place. + * + */ H5TEST_DLL char *getenv_all(MPI_Comm comm, int root, const char *name); #endif -/* Extern global variables */ -H5TEST_DLLVAR size_t n_tests_run_g; -H5TEST_DLLVAR size_t n_tests_passed_g; -H5TEST_DLLVAR size_t n_tests_failed_g; -H5TEST_DLLVAR size_t n_tests_skipped_g; -H5TEST_DLLVAR uint64_t vol_cap_flags_g; +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief "Sends" a message to another testing process using a temporary file + * + * \param[in] file Name of the temporary file to be created + * \param[in] arg1 First argument to be written to the temporary file + * \param[in] arg2 Second argument to be written to the temporary file + * + * \return nothing + * + * \details h5_send_message() facilitates inter-process communication in + * tests by "sending" a message to another process using a temporary + * file. \p file is the name of the temporary file to be created. + * \p arg1 and \p arg2 are strings to be written to the first and + * second lines of the file, respectively, and may both be NULL. + * + * When there are multiple test processes that need to communicate + * with each other, they do so by writing and reading signal files + * on disk, the names and contents of which are used to inform a + * process about when it can proceed and what it should do next. + * + * \see h5_wait_message() + * + */ +H5TEST_DLL void h5_send_message(const char *file, const char *arg1, const char *arg2); -H5TEST_DLL void h5_send_message(const char *file, const char *arg1, const char *arg2); +/** + * -------------------------------------------------------------------------- + * \ingroup H5TEST + * + * \brief Waits for a message from another testing process to be available + * + * \param[in] file Name of the temporary file to read + * + * \return \herr_t + * + * \details h5_wait_message() facilitates inter-process communication in + * tests by waiting until a temporary file written by the + * h5_send_message() function is available for reading. \p file is + * the name of the file being waited on and should match the + * filename provided to h5_send_message(). This function repeatedly + * attempts to open a file with the given filename until it is + * either successful or times out. The temporary file is removed + * once it has been successfully opened. + * + * When there are multiple test processes that need to communicate + * with each other, they do so by writing and reading signal files + * on disk, the names and contents of which are used to inform a + * process about when it can proceed and what it should do next. + * + * \see h5_send_message() + * + */ H5TEST_DLL herr_t h5_wait_message(const char *file); #ifdef __cplusplus