diff options
author | jhendersonHDF <jhenderson@hdfgroup.org> | 2023-05-02 19:52:39 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-02 19:52:39 (GMT) |
commit | f8a1b3ceec485829ccdd3034ef2be68029f1a66e (patch) | |
tree | 5563ca3059b8cbda43f7f1e0ffedf7985f71a4bc /testpar/API/H5_api_file_test_parallel.c | |
parent | 41fd8e66a9f837a1adf36a0253e29440d82ff522 (diff) | |
download | hdf5-f8a1b3ceec485829ccdd3034ef2be68029f1a66e.zip hdf5-f8a1b3ceec485829ccdd3034ef2be68029f1a66e.tar.gz hdf5-f8a1b3ceec485829ccdd3034ef2be68029f1a66e.tar.bz2 |
Add initial version of HDF5 API tests (#2877)
Diffstat (limited to 'testpar/API/H5_api_file_test_parallel.c')
-rw-r--r-- | testpar/API/H5_api_file_test_parallel.c | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/testpar/API/H5_api_file_test_parallel.c b/testpar/API/H5_api_file_test_parallel.c new file mode 100644 index 0000000..20fb2ba --- /dev/null +++ b/testpar/API/H5_api_file_test_parallel.c @@ -0,0 +1,367 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5_api_file_test_parallel.h" + +static int test_create_file(void); +static int test_open_file(void); +static int test_split_comm_file_access(void); + +/* + * The array of parallel file tests to be performed. + */ +static int (*par_file_tests[])(void) = { + test_create_file, + test_open_file, + test_split_comm_file_access, +}; + +/* + * A test to ensure that a file can be created in parallel. + */ +#define FILE_CREATE_TEST_FILENAME "test_file_parallel.h5" +static int +test_create_file(void) +{ + hid_t file_id = H5I_INVALID_HID; + hid_t fapl_id = H5I_INVALID_HID; + + TESTING("H5Fcreate"); + + /* Make sure the connector supports the API functions being tested */ + if (!(vol_cap_flags_g & H5VL_CAP_FLAG_FILE_BASIC)) { + SKIPPED(); + HDprintf(" API functions for basic file aren't supported with this connector\n"); + return 0; + } + + if ((fapl_id = create_mpi_fapl(MPI_COMM_WORLD, MPI_INFO_NULL, TRUE)) < 0) + TEST_ERROR; + + if ((file_id = H5Fcreate(FILE_CREATE_TEST_FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0) { + H5_FAILED(); + HDprintf(" couldn't create file '%s'\n", FILE_CREATE_TEST_FILENAME); + goto error; + } + + if (H5Pclose(fapl_id) < 0) + TEST_ERROR; + if (H5Fclose(file_id) < 0) + TEST_ERROR; + + PASSED(); + + return 0; + +error: + H5E_BEGIN_TRY + { + H5Pclose(fapl_id); + H5Fclose(file_id); + } + H5E_END_TRY; + + return 1; +} + +/* + * A test to ensure that a file can be opened in parallel. + */ +static int +test_open_file(void) +{ + hid_t file_id = H5I_INVALID_HID; + hid_t fapl_id = H5I_INVALID_HID; + + TESTING_MULTIPART("H5Fopen"); + + /* Make sure the connector supports the API functions being tested */ + if (!(vol_cap_flags_g & H5VL_CAP_FLAG_FILE_BASIC)) { + SKIPPED(); + HDprintf(" API functions for basic file aren't supported with this connector\n"); + return 0; + } + + TESTING_2("test setup"); + + if ((fapl_id = create_mpi_fapl(MPI_COMM_WORLD, MPI_INFO_NULL, TRUE)) < 0) + TEST_ERROR; + + PASSED(); + + BEGIN_MULTIPART + { + PART_BEGIN(H5Fopen_rdonly) + { + TESTING_2("H5Fopen in read-only mode"); + + if ((file_id = H5Fopen(H5_api_test_parallel_filename, H5F_ACC_RDONLY, fapl_id)) < 0) { + H5_FAILED(); + HDprintf(" unable to open file '%s' in read-only mode\n", H5_api_test_parallel_filename); + PART_ERROR(H5Fopen_rdonly); + } + + PASSED(); + } + PART_END(H5Fopen_rdonly); + + if (file_id >= 0) { + H5E_BEGIN_TRY + { + H5Fclose(file_id); + } + H5E_END_TRY; + file_id = H5I_INVALID_HID; + } + + PART_BEGIN(H5Fopen_rdwrite) + { + TESTING_2("H5Fopen in read-write mode"); + + if ((file_id = H5Fopen(H5_api_test_parallel_filename, H5F_ACC_RDWR, fapl_id)) < 0) { + H5_FAILED(); + HDprintf(" unable to open file '%s' in read-write mode\n", H5_api_test_parallel_filename); + PART_ERROR(H5Fopen_rdwrite); + } + + PASSED(); + } + PART_END(H5Fopen_rdwrite); + + if (file_id >= 0) { + H5E_BEGIN_TRY + { + H5Fclose(file_id); + } + H5E_END_TRY; + file_id = H5I_INVALID_HID; + } + + /* + * XXX: SWMR open flags + */ + } + END_MULTIPART; + + TESTING_2("test cleanup"); + + if (H5Pclose(fapl_id) < 0) + TEST_ERROR; + + PASSED(); + + return 0; + +error: + H5E_BEGIN_TRY + { + H5Pclose(fapl_id); + H5Fclose(file_id); + } + H5E_END_TRY; + + return 1; +} + +/* + * Tests file access by a communicator other than MPI_COMM_WORLD. + * + * Splits MPI_COMM_WORLD into two groups, where one (even_comm) contains + * the original processes of even ranks. The other (odd_comm) contains + * the original processes of odd ranks. Processes in even_comm create a + * file, then close it, using even_comm. Processes in old_comm just do + * a barrier using odd_comm. Then they all do a barrier using MPI_COMM_WORLD. + * If the file creation and close does not do correct collective action + * according to the communicator argument, the processes will freeze up + * sooner or later due to MPI_Barrier calls being mixed up. + */ +#define SPLIT_FILE_COMM_TEST_FILE_NAME "split_comm_file.h5" +static int +test_split_comm_file_access(void) +{ + MPI_Comm comm; + MPI_Info info = MPI_INFO_NULL; + hid_t file_id = H5I_INVALID_HID; + hid_t fapl_id = H5I_INVALID_HID; + int is_old; + int newrank; + int err_occurred = 0; + + TESTING("file access with a split communicator"); + + /* Make sure the connector supports the API functions being tested */ + if (!(vol_cap_flags_g & H5VL_CAP_FLAG_FILE_BASIC)) { + SKIPPED(); + HDprintf(" API functions for basic file aren't supported with this connector\n"); + return 0; + } + + /* set up MPI parameters */ + MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); + is_old = mpi_rank % 2; + if (MPI_SUCCESS != MPI_Comm_split(MPI_COMM_WORLD, is_old, mpi_rank, &comm)) { + H5_FAILED(); + HDprintf(" failed to split communicator!\n"); + goto error; + } + MPI_Comm_rank(comm, &newrank); + + if (is_old) { + /* odd-rank processes */ + if (MPI_SUCCESS != MPI_Barrier(comm)) { + err_occurred = 1; + goto access_end; + } + } + else { + /* even-rank processes */ + int sub_mpi_rank; /* rank in the sub-comm */ + + MPI_Comm_rank(comm, &sub_mpi_rank); + + /* setup file access template */ + if ((fapl_id = create_mpi_fapl(comm, info, TRUE)) < 0) { + err_occurred = 1; + goto access_end; + } + + /* create the file collectively */ + if ((file_id = H5Fcreate(SPLIT_FILE_COMM_TEST_FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0) { + H5_FAILED(); + HDprintf(" couldn't create file '%s'\n", SPLIT_FILE_COMM_TEST_FILE_NAME); + err_occurred = 1; + goto access_end; + } + + /* close the file */ + if (H5Fclose(file_id) < 0) { + H5_FAILED(); + HDprintf(" failed to close file '%s'\n", SPLIT_FILE_COMM_TEST_FILE_NAME); + err_occurred = 1; + goto access_end; + } + + /* delete the test file */ + if (H5Fdelete(SPLIT_FILE_COMM_TEST_FILE_NAME, fapl_id) < 0) { + H5_FAILED(); + HDprintf(" failed to delete file '%s'\n", SPLIT_FILE_COMM_TEST_FILE_NAME); + err_occurred = 1; + goto access_end; + } + + /* Release file-access template */ + if (H5Pclose(fapl_id) < 0) { + err_occurred = 1; + goto access_end; + } + } +access_end: + + /* Get the collective results about whether an error occurred */ + if (MPI_SUCCESS != MPI_Allreduce(MPI_IN_PLACE, &err_occurred, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD)) { + H5_FAILED(); + HDprintf(" MPI_Allreduce failed\n"); + goto error; + } + + if (err_occurred) { + H5_FAILED(); + HDprintf(" an error occurred on only some ranks during split-communicator file access! - " + "collectively failing\n"); + goto error; + } + + if (MPI_SUCCESS != MPI_Comm_free(&comm)) { + H5_FAILED(); + HDprintf(" MPI_Comm_free failed\n"); + goto error; + } + + if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD)) { + H5_FAILED(); + HDprintf(" MPI_Barrier on MPI_COMM_WORLD failed\n"); + goto error; + } + + PASSED(); + + return 0; + +error: + H5E_BEGIN_TRY + { + H5Pclose(fapl_id); + H5Fclose(file_id); + } + H5E_END_TRY; + + return 1; +} + +/* + * Cleanup temporary test files + */ +static void +cleanup_files(void) +{ + hid_t fapl_id = H5I_INVALID_HID; + + if ((fapl_id = create_mpi_fapl(MPI_COMM_WORLD, MPI_INFO_NULL, TRUE)) < 0) { + if (MAINPROCESS) + HDprintf(" failed to create FAPL for deleting test files\n"); + return; + } + + H5Fdelete(FILE_CREATE_TEST_FILENAME, fapl_id); + + /* The below file is deleted as part of the test */ + /* H5Fdelete(SPLIT_FILE_COMM_TEST_FILE_NAME, H5P_DEFAULT); */ + + if (H5Pclose(fapl_id) < 0) { + if (MAINPROCESS) + HDprintf(" failed to close FAPL used for deleting test files\n"); + return; + } +} + +int +H5_api_file_test_parallel(void) +{ + size_t i; + int nerrors; + + if (MAINPROCESS) { + HDprintf("**********************************************\n"); + HDprintf("* *\n"); + HDprintf("* API Parallel File Tests *\n"); + HDprintf("* *\n"); + HDprintf("**********************************************\n\n"); + } + + for (i = 0, nerrors = 0; i < ARRAY_LENGTH(par_file_tests); i++) { + nerrors += (*par_file_tests[i])() ? 1 : 0; + + if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD)) { + if (MAINPROCESS) + HDprintf(" MPI_Barrier() failed!\n"); + } + } + + if (MAINPROCESS) { + HDprintf("\n"); + HDprintf("Cleaning up testing files\n"); + } + + cleanup_files(); + + return nerrors; +} |