diff options
author | Dana Robinson <derobins@hdfgroup.org> | 2020-08-15 21:20:18 (GMT) |
---|---|---|
committer | Dana Robinson <derobins@hdfgroup.org> | 2020-08-15 21:20:18 (GMT) |
commit | c638d93f3e660ce669a36e50a02473aac126953d (patch) | |
tree | b39f5688adc827da7d000aaa5a5264d29c2ee919 /test | |
parent | 8e7c24f5148e91335bf744583a6a407014014391 (diff) | |
parent | e9305abf48426f265d7ec3ae54538e3ded8889ea (diff) | |
download | hdf5-c638d93f3e660ce669a36e50a02473aac126953d.zip hdf5-c638d93f3e660ce669a36e50a02473aac126953d.tar.gz hdf5-c638d93f3e660ce669a36e50a02473aac126953d.tar.bz2 |
Merge pull request #2770 in HDFFV/hdf5 from ~DEROBINS/hdf5_der:1_10_normalization to hdf5_1_10
* commit 'e9305abf48426f265d7ec3ae54538e3ded8889ea':
Fixes missing chunk_info entry in CMake files
Even more normalization with develop
More normalizations with develop
Misc normalizations with develop
Normalization of perform directory with develop
Brings monotonic timer changes from develop
Brings Mirror VFD to 1.10 from develop
Brings splitter VFD from develop
Brings file locking changes from develop
Diffstat (limited to 'test')
81 files changed, 5511 insertions, 328 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8e553d0..1911903 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -173,6 +173,11 @@ set (cache_image_SOURCES ${HDF5_TEST_SOURCE_DIR}/genall5.c ) +set(mirror_vfd_SOURCES + ${HDF5_TEST_SOURCE_DIR}/mirror_vfd.c + ${HDF5_TEST_SOURCE_DIR}/genall5.c +) + set (ttsafe_SOURCES ${HDF5_TEST_SOURCE_DIR}/ttsafe.c ${HDF5_TEST_SOURCE_DIR}/ttsafe_dcreate.c @@ -206,7 +211,7 @@ set (H5_TESTS page_buffer dtypes dsets - chunk_info + chunk_info # compression lib link cmpd_dset filter_fail extend @@ -235,6 +240,7 @@ set (H5_TESTS ros3 s3comms hdfs + mirror_vfd ntypes dangle dtransform @@ -250,6 +256,7 @@ set (H5_TESTS cork swmr thread_id # special link + timer ) macro (ADD_H5_EXE file) @@ -267,11 +274,13 @@ macro (ADD_H5_EXE file) endmacro () set (H5_TESTS_MULTIPLE + chunk_info direct_chunk testhdf5 cache_image ttsafe thread_id # special link + mirror_vfd ) # Only build single source tests here foreach (h5_test ${H5_TESTS}) @@ -284,6 +293,19 @@ endforeach () ### M U L T I P L E S O U R C E T E S T S ### ############################################################################## ######### Also special handling of link libs ############# +#-- Adding test for chunk_info +add_executable (chunk_info ${HDF5_TEST_SOURCE_DIR}/chunk_info.c) +target_compile_options(chunk_info PRIVATE "${HDF5_CMAKE_C_FLAGS}") +target_include_directories (chunk_info PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};${HDF5_TEST_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") +if (NOT BUILD_SHARED_LIBS) + TARGET_C_PROPERTIES (chunk_info STATIC) + target_link_libraries (chunk_info PRIVATE ${HDF5_TEST_LIB_TARGET} ${LINK_COMP_LIBS}) +else () + TARGET_C_PROPERTIES (chunk_info SHARED) + target_link_libraries (chunk_info PRIVATE ${HDF5_TEST_LIBSH_TARGET} ${LINK_COMP_LIBS}) +endif () +set_target_properties (chunk_info PROPERTIES FOLDER test) + #-- Adding test for direct_chunk add_executable (direct_chunk ${HDF5_TEST_SOURCE_DIR}/direct_chunk.c) target_compile_options(direct_chunk PRIVATE "${HDF5_CMAKE_C_FLAGS}") @@ -362,6 +384,18 @@ else () endif () set_target_properties (thread_id PROPERTIES FOLDER test) +#-- Adding test for mirror_vfd +add_executable (mirror_vfd ${mirror_vfd_SOURCES}) +target_include_directories (mirror_vfd PRIVATE "${HDF5_SRC_DIR};${HDF5_BINARY_DIR};$<$<BOOL:${HDF5_ENABLE_PARALLEL}>:${MPI_C_INCLUDE_DIRS}>") +if (NOT BUILD_SHARED_LIBS) + TARGET_C_PROPERTIES (mirror_vfd STATIC) + target_link_libraries (mirror_vfd PRIVATE ${HDF5_TEST_LIB_TARGET}) +else () + TARGET_C_PROPERTIES (mirror_vfd SHARED) + target_link_libraries (mirror_vfd PRIVATE ${HDF5_TEST_LIBSH_TARGET}) +endif () +set_target_properties (mirror_vfd PROPERTIES FOLDER test) + ############################################################################## ### A D D I T I O N A L T E S T S ### ############################################################################## diff --git a/test/CMakeTests.cmake b/test/CMakeTests.cmake index 800bfb6..4e14067 100644 --- a/test/CMakeTests.cmake +++ b/test/CMakeTests.cmake @@ -446,6 +446,10 @@ set (test_CLEANFILES vds_swmr_src_*.h5 tmp_vds_env/vds_src_2.h5 direct_chunk.h5 + splitter*.h5 + splitter.log + mirror_rw/* + mirror_wo/* ) # Remove any output file left over from previous test run diff --git a/test/Makefile.am b/test/Makefile.am index f60f55c..7e1cd4b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -33,9 +33,11 @@ AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_builddir)/src # testvdsswmr.sh: vds_swmr* # testabort_fail.sh: filenotclosed.c and del_many_dense_attrs.c # test_filter_plugin.sh: filter_plugin.c +# test_mirror.sh: mirror_vfd ../utils/mirror_vfd/* # test_usecases.sh: use_append_chunk, use_append_mchunks, use_disable_mdc_flushes TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh testexternal_env.sh \ - testswmr.sh testvds_env.sh testvdsswmr.sh testflushrefresh.sh test_usecases.sh testabort_fail.sh + testswmr.sh testvds_env.sh testvdsswmr.sh testflushrefresh.sh test_usecases.sh testabort_fail.sh \ + test_mirror.sh SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) \ external_env$(EXEEXT) filenotclosed$(EXEEXT) del_many_dense_attrs$(EXEEXT) \ flushrefresh$(EXEEXT) use_append_chunk$(EXEEXT) use_append_mchunks$(EXEEXT) use_disable_mdc_flushes$(EXEEXT) \ @@ -63,7 +65,7 @@ TEST_PROG= testhdf5 \ flush1 flush2 app_ref enum set_extent ttsafe enc_dec_plist \ enc_dec_plist_cross_platform getname vfd ros3 s3comms hdfs ntypes \ dangle dtransform reserved cross_read freespace mf vds file_image \ - unregister cache_logging cork swmr thread_id + unregister cache_logging cork swmr thread_id timer # List programs to be built when testing here. # error_test and err_compat are built at the same time as the other tests, but executed by testerror.sh. @@ -78,16 +80,18 @@ TEST_PROG= testhdf5 \ # swmr_* files (besides swmr.c) are used by testswmr.sh. # vds_swmr_* files are used by testvdsswmr.sh # vds_env is used by testvds_env.sh +# mirror_vfd is used by test_mirror.sh # 'make check' doesn't run them directly, so they are not included in TEST_PROG. # Also build testmeta, which is used for timings test. It builds quickly, # and this lets automake keep all its test programs in one place. check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version \ testmeta accum_swmr_reader atomic_writer atomic_reader external_env \ links_env filenotclosed del_many_dense_attrs flushrefresh \ - use_append_chunk use_append_mchunks use_disable_mdc_flushes \ + use_append_chunk use_append_chunk_mirror use_append_mchunks use_disable_mdc_flushes \ swmr_generator swmr_start_write swmr_reader swmr_writer swmr_remove_reader \ swmr_remove_writer swmr_addrem_writer swmr_sparse_reader swmr_sparse_writer \ - swmr_check_compat_vfd vds_env vds_swmr_gen vds_swmr_reader vds_swmr_writer + swmr_check_compat_vfd vds_env vds_swmr_gen vds_swmr_reader vds_swmr_writer \ + mirror_vfd if HAVE_SHARED_CONDITIONAL check_PROGRAMS+= filter_plugin endif @@ -137,6 +141,7 @@ LDADD=libh5test.la $(LIBHDF5) ttsafe_SOURCES=ttsafe.c ttsafe_dcreate.c ttsafe_error.c ttsafe_cancel.c \ ttsafe_acreate.c ttsafe_attr_vlen.c cache_image_SOURCES=cache_image.c genall5.c +mirror_vfd_SOURCES=mirror_vfd.c genall5.c VFD_LIST = sec2 stdio core core_paged split multi family if DIRECT_VFD_CONDITIONAL @@ -201,7 +206,8 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offse flushrefresh_VERIFICATION_DONE atomic_data accum_swmr_big.h5 ohdr_swmr.h5 \ test_swmr*.h5 cache_logging.h5 cache_logging.out vds_swmr.h5 vds_swmr_src_*.h5 \ swmr[0-2].h5 swmr_writer.out swmr_writer.log.* swmr_reader.out.* swmr_reader.log.* \ - tbogus.h5.copy cache_image_test.h5 direct_chunk.h5 + tbogus.h5.copy cache_image_test.h5 direct_chunk.h5 \ + splitter*.h5 splitter.log mirror_rw mirror_ro # Sources for testhdf5 executable testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \ @@ -211,11 +217,13 @@ testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \ # Sources for Use Cases use_append_chunk_SOURCES=use_append_chunk.c use_common.c +use_append_chunk_mirror_SOURCES=use_append_chunk_mirror.c use_common.c use_append_mchunks_SOURCES=use_append_mchunks.c use_common.c use_disable_mdc_flushes_SOURCES=use_disable_mdc_flushes.c # Temporary files. DISTCLEANFILES=testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh test_filter_plugin.sh \ - testexternal_env.sh testswmr.sh testvds_env.sh testvdsswmr.sh test_usecases.sh testflushrefresh.sh testabort_fail.sh + testexternal_env.sh testswmr.sh testvds_env.sh testvdsswmr.sh test_usecases.sh testflushrefresh.sh \ + testabort_fail.sh test_mirror.sh include $(top_srcdir)/config/conclude.am diff --git a/test/SWMR_UseCase_UG.txt b/test/SWMR_UseCase_UG.txt index 18d4927..1e3d1e6 100644 --- a/test/SWMR_UseCase_UG.txt +++ b/test/SWMR_UseCase_UG.txt @@ -6,8 +6,8 @@ case program and explain how to run them. 2.1. Author and Dates: - Version 2: By Albert Cheng (acheng@hdfgroup.org), 2013/06/18. - Version 1: By Albert Cheng (acheng@hdfgroup.org), 2013/06/01. + Version 2: By Albert Cheng, 2013/06/18. + Version 1: By Albert Cheng, 2013/06/01. %%%%Use Case 1.7%%%% diff --git a/test/app_ref.c b/test/app_ref.c index a4853fa..c1735fa 100644 --- a/test/app_ref.c +++ b/test/app_ref.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Neil Fortner <nfortne2@hdfgroup.org> + * Programmer: Neil Fortner * Thursday, August 14, 2008 * * Purpose: Tests closing the library after reference counts have been @@ -12,9 +12,9 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Wednesday, April 8, 1998 - * Modified: Albert Cheng <acheng@hdfgroup.org> + * Modified: Albert Cheng * September 11, 2010 */ /* @@ -803,10 +803,10 @@ main (int ac, char **av) /* Choose random # seed */ seed = (unsigned long)HDtime(NULL); -#ifdef QAK +#if 0 /* seed = (unsigned long)1155438845; */ HDfprintf(stderr, "Random # seed was: %lu\n", seed); -#endif /* QAK */ +#endif HDsrandom((unsigned)seed); /* run VFD-specific test */ diff --git a/test/bittests.c b/test/bittests.c index 046528a..6f236d6 100644 --- a/test/bittests.c +++ b/test/bittests.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Tuesday, June 16, 1998 * * Purpose: Tests functions in H5Tbit.c diff --git a/test/btree2.c b/test/btree2.c index fb18048..b95c595 100644 --- a/test/btree2.c +++ b/test/btree2.c @@ -11,7 +11,7 @@ * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> +/* Programmer: Quincey Koziol * Tuesday, February 1, 2005 */ #include "h5test.h" @@ -26,7 +26,7 @@ /* Other private headers that this test requires */ #include "H5CXprivate.h" /* API Contexts */ -#include "H5Iprivate.h" /* Virtual Object Layer */ +#include "H5Iprivate.h" /* Identifiers */ const char *FILENAME[] = { "btree2", diff --git a/test/cache.c b/test/cache.c index 49bb303..10e7bf6 100644 --- a/test/cache.c +++ b/test/cache.c @@ -28146,7 +28146,6 @@ check_auto_cache_resize_aux_fcns(unsigned paged) * Return: void * * Programmer: Mike McGreevy - * <mamcgree@hdfgroup.org> * 12/16/08 * * Modifications: diff --git a/test/cache_api.c b/test/cache_api.c index 1e1a2c9..d6ea7e2 100644 --- a/test/cache_api.c +++ b/test/cache_api.c @@ -1664,7 +1664,7 @@ init_invalid_configs(void) { configs[13].lower_hr_threshold = 1.00000001f; /* 14 -- increment too small */ - configs[14].increment = H5_DOUBLE(0.999999999999); + configs[14].increment = 0.999999999999; /* 15 -- invalid flash_incr_mode */ configs[15].flash_incr_mode = (enum H5C_cache_flash_incr_mode)-1; @@ -1697,7 +1697,7 @@ init_invalid_configs(void) { /* 23 -- decrement too big */ configs[23].decr_mode = H5C_decr__threshold; - configs[23].decrement = H5_DOUBLE(1.0000000001); + configs[23].decrement = 1.0000000001; /* 24 -- epochs_before_eviction too small */ configs[24].epochs_before_eviction = 0; @@ -1709,13 +1709,13 @@ init_invalid_configs(void) { configs[26].empty_reserve = -0.0000000001f; /* 27 -- empty_reserve too big */ - configs[27].empty_reserve = H5_DOUBLE(1.00000000001); + configs[27].empty_reserve = 1.00000000001; /* 28 -- upper_hr_threshold too small */ configs[28].upper_hr_threshold = -0.000000001f; /* 29 -- upper_hr_threshold too big */ - configs[29].upper_hr_threshold = H5_DOUBLE(1.00000001); + configs[29].upper_hr_threshold = 1.00000001; /* 30 -- upper_hr_threshold <= lower_hr_threshold */ configs[30].lower_hr_threshold = 0.9f; diff --git a/test/cache_tagging.c b/test/cache_tagging.c index 57b5d5c..aaf7d9a 100644 --- a/test/cache_tagging.c +++ b/test/cache_tagging.c @@ -439,7 +439,9 @@ check_file_creation_tags(hid_t fcpl_id, int type) { /* Variable Declarations */ hid_t fid = -1; /* File Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose test outout */ +#endif /* NDEBUG */ /* end debugging functions */ haddr_t root_tag = 0; haddr_t sbe_tag = 0; @@ -520,7 +522,9 @@ check_file_open_tags(hid_t fcpl, int type) { /* Variable Declarations */ hid_t fid = -1; /* File Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ haddr_t root_tag; /* Root Group Tag */ haddr_t sbe_tag; /* Sblock Extension Tag */ @@ -627,7 +631,9 @@ check_group_creation_tags(void) /* Variable Declarations */ hid_t fid = -1; /* File Identifier */ hid_t gid = -1; /* Group Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ haddr_t root_tag = HADDR_UNDEF; /* Root Group Tag */ haddr_t g_tag; /* Group Tag */ @@ -722,7 +728,9 @@ check_multi_group_creation_tags(void) /* Variable Declarations */ hid_t fid = -1; /* File Identifier */ hid_t gid = -1; /* Group Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ char gname[16]; /* group name buffer */ int i = 0; /* iterator */ hid_t fapl = -1; /* File access prop list */ @@ -850,7 +858,9 @@ check_link_iteration_tags(void) hid_t fid = -1; /* File Identifier */ hid_t sid = -1; /* Group Identifier */ hid_t did = -1; /* Group Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ int i = 0; /* iterator */ haddr_t root_tag = 0; /* Root Group Tag Value */ char dsetname[500]; /* Name of dataset */ @@ -964,7 +974,9 @@ check_dense_attribute_tags(void) hid_t sid = -1; /* Group Identifier */ hid_t did = -1; /* Group Identifier */ hid_t dcpl = -1; /* Group Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ int i = 0; /* iterator */ hid_t fapl = -1; /* File access property list */ haddr_t d_tag = 0; /* Dataset tag value */ @@ -1144,7 +1156,9 @@ check_group_open_tags(void) /* Variable Declarations */ hid_t fid = -1; /* File Identifier */ hid_t gid = -1; /* Group Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file output */ +#endif /* NDEBUG */ /* end debugging functions */ haddr_t root_tag = HADDR_UNDEF; haddr_t g_tag; @@ -1247,7 +1261,9 @@ check_attribute_creation_tags(hid_t fcpl, int type) hid_t aid = -1; /* Attribute Identifier */ hid_t gid = -1; /* Group Identifier */ hid_t sid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ haddr_t root_tag = 0; /* Root group tag */ haddr_t g_tag = 0; hsize_t dims1[2] = {DIMS, DIMS}; /* dimensions */ @@ -1376,7 +1392,9 @@ check_attribute_open_tags(hid_t fcpl, int type) hid_t aid = -1; /* Attribute Identifier */ hid_t gid = -1; /* Group Identifier */ hid_t sid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ haddr_t root_tag = 0; haddr_t g_tag = 0; hsize_t dims1[2] = {DIMS, DIMS}; /* dimensions */ @@ -1507,7 +1525,9 @@ check_attribute_rename_tags(hid_t fcpl, int type) hid_t gid = -1; /* Group Identifier */ hid_t aid = -1; /* Attribute Identifier */ hid_t sid = -1; /* Dataset Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ int *data = NULL; /* data buffer */ int i,j,k = 0; /* iterators */ haddr_t root_tag = 0; @@ -1686,7 +1706,9 @@ check_attribute_delete_tags(hid_t fcpl, int type) hid_t gid = -1; /* Group Identifier */ hid_t aid = -1; /* Attribute Identifier */ hid_t sid = -1; /* Dataset Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ int *data = NULL; /* data buffer */ int i,j,k = 0; /* iterators */ haddr_t root_tag = 0; @@ -1843,7 +1865,9 @@ check_dataset_creation_tags(hid_t fcpl, int type) hid_t fid = -1; /* File Identifier */ hid_t did = -1; /* Dataset Identifier */ hid_t sid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ hid_t dcpl = -1; /* dataset creation pl */ hsize_t cdims[2] = {1,1}; /* chunk dimensions */ int fillval = 0; @@ -1970,7 +1994,9 @@ check_dataset_creation_earlyalloc_tags(hid_t fcpl, int type) hid_t fid = -1; /* File Identifier */ hid_t did = -1; /* Dataset Identifier */ hid_t sid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ hid_t dcpl = -1; /* dataset creation pl */ hsize_t cdims[2] = {1,1}; /* chunk dimensions */ int fillval = 0; @@ -2101,7 +2127,9 @@ check_dataset_open_tags(void) hid_t fid = -1; /* File Identifier */ hid_t did = -1; /* Dataset Identifier */ hid_t sid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ hid_t dcpl = -1; /* dataset creation pl */ hsize_t cdims[2] = {1,1}; /* chunk dimensions */ int fillval = 0; @@ -2221,7 +2249,9 @@ check_dataset_write_tags(void) hid_t fid = -1; /* File Identifier */ hid_t did = -1; /* Dataset Identifier */ hid_t sid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ hid_t dcpl = -1; /* dataset creation pl */ hsize_t cdims[2] = {1,1}; /* chunk dimensions */ int fillval = 0; @@ -2357,7 +2387,9 @@ check_attribute_write_tags(hid_t fcpl, int type) hid_t gid = -1; /* Group Identifier */ hid_t aid = -1; /* Attribute Identifier */ hid_t sid = -1; /* Dataset Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ int *data = NULL; /* data buffer */ int i,j,k = 0; /* iterators */ haddr_t root_tag = 0; @@ -2504,7 +2536,9 @@ check_dataset_read_tags(void) hid_t fid = -1; /* File Identifier */ hid_t did = -1; /* Dataset Identifier */ hid_t sid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ hid_t dcpl = -1; /* dataset creation pl */ hsize_t cdims[2] = {1,1}; /* chunk dimensions */ int fillval = 0; @@ -2635,7 +2669,9 @@ check_dataset_size_retrieval(void) hid_t fid = -1; /* File Identifier */ hid_t did = -1; /* Dataset Identifier */ hid_t sid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ hid_t dcpl = -1; /* dataset creation pl */ hsize_t cdims[2] = {1,1}; /* chunk dimensions */ int fillval = 0; @@ -2768,7 +2804,9 @@ check_dataset_extend_tags(void) hid_t fid = -1; /* File Identifier */ hid_t did = -1; /* Dataset Identifier */ hid_t sid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ hid_t dcpl = -1; /* dataset creation pl */ hsize_t cdims[2] = {1,1}; /* chunk dimensions */ int fillval = 0; @@ -2899,7 +2937,9 @@ check_object_info_tags(void) /* Variable Declarations */ hid_t fid = -1; /* File Identifier */ hid_t gid = -1; /* Group Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file output */ +#endif /* NDEBUG */ /* end debugging functions */ haddr_t root_tag = HADDR_UNDEF; haddr_t g_tag; H5O_info_t oinfo; /* Object info struct */ @@ -3002,7 +3042,9 @@ check_object_copy_tags(void) /* Variable Declarations */ hid_t fid = -1; /* File Identifier */ hid_t gid = -1; /* Group Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file output */ +#endif /* NDEBUG */ /* end debugging functions */ haddr_t root_tag = HADDR_UNDEF; haddr_t g_tag; haddr_t copy_tag; @@ -3117,7 +3159,9 @@ check_link_removal_tags(hid_t fcpl, int type) hid_t did = -1; /* Dataset Identifier */ hid_t sid = -1; /* Dataspace Identifier */ hid_t gid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ hid_t dcpl = -1; /* dataset creation pl */ hsize_t cdims[2] = {1,1}; /* chunk dimensions */ int fillval = 0; @@ -3270,7 +3314,9 @@ check_link_getname_tags(void) hid_t did = -1; /* Dataset Identifier */ hid_t sid = -1; /* Dataspace Identifier */ hid_t gid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ hid_t dcpl = -1; /* dataset creation pl */ hsize_t cdims[2] = {1,1}; /* chunk dimensions */ int fillval = 0; @@ -3413,7 +3459,9 @@ check_external_link_creation_tags(void) hid_t fid = -1; /* File Identifier */ hid_t fid2 = -1; /* File Identifier */ hid_t gid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ haddr_t root_tag = 0; /* Testing Macro */ @@ -3513,7 +3561,9 @@ check_external_link_open_tags(void) hid_t fid2 = -1; /* File Identifier */ hid_t gid = -1; /* Dataspace Identifier */ hid_t xid = -1; /* Dataspace Identifier */ +#ifndef NDEBUG int verbose = FALSE; /* verbose file outout */ +#endif /* NDEBUG */ /* end debugging functions */ haddr_t root_tag = 0; haddr_t root2_tag = 0; diff --git a/test/cmpd_dset.c b/test/cmpd_dset.c index ff3767c..c8ef1e4 100644 --- a/test/cmpd_dset.c +++ b/test/cmpd_dset.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Friday, January 23, 1998 */ diff --git a/test/cross_read.c b/test/cross_read.c index c16ddbc..dabd3ab 100644 --- a/test/cross_read.c +++ b/test/cross_read.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Raymond Lu <slu@ncsa.uiuc.edu> + * Programmer: Raymond Lu * Thursday, March 23, 2006 * * Purpose: Check if floating-point data created on big-endian and diff --git a/test/dangle.c b/test/dangle.c index 9f30f10..8300792 100644 --- a/test/dangle.c +++ b/test/dangle.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Programmer: Quincey Koziol * Tuesday, May 13, 2003 * * Purpose: Test dangling IDs diff --git a/test/del_many_dense_attrs.c b/test/del_many_dense_attrs.c index 4c1efae..6f48901 100644 --- a/test/del_many_dense_attrs.c +++ b/test/del_many_dense_attrs.c @@ -62,17 +62,17 @@ static void catch_signal(int H5_ATTR_UNUSED signo) int main(void) { - hid_t fid = -1; /* HDF5 File ID */ - hid_t gid = -1; /* Group ID */ - hid_t sid = -1; /* Dataspace ID */ - hid_t aid = -1; /* Attribute ID */ - hid_t tid = -1; /* Datatype ID */ - hid_t fapl = -1; /* File access property lists */ - hid_t gcpl = -1; /* Group creation property list */ - char aname[50]; /* Name of attribute */ - char *basename="attr"; /* Name prefix for attribute */ - char filename[100]; /* File name */ - int i; /* Local index variable */ + hid_t fid = -1; /* HDF5 File ID */ + hid_t gid = -1; /* Group ID */ + hid_t sid = -1; /* Dataspace ID */ + hid_t aid = -1; /* Attribute ID */ + hid_t tid = -1; /* Datatype ID */ + hid_t fapl = -1; /* File access property lists */ + hid_t gcpl = -1; /* Group creation property list */ + char aname[50]; /* Name of attribute */ + const char *basename="attr"; /* Name prefix for attribute */ + char filename[100]; /* File name */ + int i; /* Local index variable */ /* Testing setup */ h5_reset(); diff --git a/test/direct_chunk.c b/test/direct_chunk.c index 7b17043..2e6cc68 100644 --- a/test/direct_chunk.c +++ b/test/direct_chunk.c @@ -43,7 +43,7 @@ #define CHUNK_NX 4 #define CHUNK_NY 4 -#define DEFLATE_SIZE_ADJUST(s) (HDceil(((double)(s))*H5_DOUBLE(1.001))+H5_DOUBLE(12.0)) +#define DEFLATE_SIZE_ADJUST(s) (HDceil(((double)(s))*1.001)+12.0) /* Temporary filter IDs used for testing */ #define H5Z_FILTER_BOGUS1 305 @@ -661,20 +661,20 @@ filter_bogus1(unsigned int flags, size_t H5_ATTR_UNUSED cd_nelmts, size_t *buf_size, void **buf) { int *int_ptr=(int *)*buf; /* Pointer to the data values */ - ssize_t buf_left=(ssize_t)*buf_size; /* Amount of data buffer left to process */ + size_t buf_left=*buf_size; /* Amount of data buffer left to process */ if(flags & H5Z_FLAG_REVERSE) { /* read */ /* Substract the "add on" value to all the data values */ while(buf_left>0) { *int_ptr++ -= (int)ADD_ON; - buf_left -= (ssize_t)sizeof(int); + buf_left -= sizeof(int); } /* end while */ } /* end if */ else { /* write */ /* Add the "add on" value to all the data values */ while(buf_left>0) { *int_ptr++ += (int)ADD_ON; - buf_left -= (ssize_t)sizeof(int); + buf_left -= sizeof(int); } /* end while */ } /* end else */ @@ -698,20 +698,20 @@ filter_bogus2(unsigned int flags, size_t H5_ATTR_UNUSED cd_nelmts, size_t *buf_size, void **buf) { int *int_ptr=(int *)*buf; /* Pointer to the data values */ - ssize_t buf_left=(ssize_t)*buf_size; /* Amount of data buffer left to process */ + size_t buf_left=*buf_size; /* Amount of data buffer left to process */ if(flags & H5Z_FLAG_REVERSE) { /* read */ /* Substract the "add on" value to all the data values */ while(buf_left>0) { *int_ptr++ /= (int)FACTOR; - buf_left -= (ssize_t)sizeof(int); + buf_left -= sizeof(int); } /* end while */ } /* end if */ else { /* write */ /* Add the "add on" value to all the data values */ while(buf_left>0) { *int_ptr++ *= (int)FACTOR; - buf_left -= (ssize_t)sizeof(int); + buf_left -= sizeof(int); } /* end while */ } /* end else */ diff --git a/test/dsets.c b/test/dsets.c index f7e90a5..d72c65b 100644 --- a/test/dsets.c +++ b/test/dsets.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Tuesday, December 9, 1997 * * Purpose: Tests the dataset interface (H5D) @@ -274,13 +274,6 @@ const char *FILENAME[] = { #define STORAGE_SIZE_CHUNK_DIM1 5 #define STORAGE_SIZE_CHUNK_DIM2 5 -/* Parameters for testing version bounds */ -#define VDS_FNAME1 "virtual_file1" -#define VDS_FNAME2 "virtual_file2" -#define SRC_FNAME "source_file" -#define SRC_DSET "src_dset" -#define V_DSET "v_dset" - /* Shared global arrays */ #define DSET_DIM1 100 #define DSET_DIM2 200 @@ -3176,18 +3169,18 @@ test_nbit_double(hid_t file) */ double orig_data[2][5] = { { - H5_DOUBLE(1.6081706885101836e+60), - H5_DOUBLE(-255.32099170994480), - H5_DOUBLE(1.2677579992621376e-61), - H5_DOUBLE(64568.289448797700), - H5_DOUBLE(-1.0619721778839084e-75) + (double)1.6081706885101836e+60L, + -255.32099170994480f, + (double)1.2677579992621376e-61L, + 64568.289448797700f, + (double)-1.0619721778839084e-75L }, { - H5_DOUBLE(2.1499497833454840e+56), - H5_DOUBLE(6.6562295504670740e-3), - H5_DOUBLE(-1.5747263393432150), - H5_DOUBLE(1.0711093225222612), - H5_DOUBLE(-9.8971679387636870e-1) + (double)2.1499497833454840e+56L, + 6.6562295504670740e-3f, + -1.5747263393432150f, + 1.0711093225222612f, + -9.8971679387636870e-1f }}; double new_data[2][5]; size_t precision, offset; @@ -13232,6 +13225,11 @@ error: * *------------------------------------------------------------------------- */ +#define VDS_FNAME1 "virtual_file1" +#define VDS_FNAME2 "virtual_file2" +#define SRC_FNAME "source_file" +#define SRC_DSET "src_dset" +#define V_DSET "v_dset" static herr_t test_versionbounds(void) { diff --git a/test/dt_arith.c b/test/dt_arith.c index 7e1adf5..9b89225 100644 --- a/test/dt_arith.c +++ b/test/dt_arith.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Tuesday, December 9, 1997 * * Purpose: Tests the data type interface (H5T) @@ -770,7 +770,7 @@ static int test_particular_fp_integer(void) /* Print errors */ if(dst_c != SCHAR_MAX) { - double x; + double x = 0.0; signed char y; if(0 == fails_this_test++) @@ -814,7 +814,7 @@ static int test_particular_fp_integer(void) /* Print errors */ if(dst_i != fill_value) { - float x; + float x = 0.0; int y; if(0 == fails_this_test++) @@ -2723,16 +2723,16 @@ my_isnan(dtype_t type, void *val) char s[256]; if (FLT_FLOAT==type) { - float x; + float x = 0.0; HDmemcpy(&x, val, sizeof(float)); retval = (x!=x); } else if (FLT_DOUBLE==type) { - double x; + double x = 0.0; HDmemcpy(&x, val, sizeof(double)); retval = (x!=x); #if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE && H5_SIZEOF_LONG_DOUBLE!=0 } else if (FLT_LDOUBLE==type) { - long double x; + long double x = 0.0; HDmemcpy(&x, val, sizeof(long double)); retval = (x!=x); #endif @@ -2746,18 +2746,18 @@ my_isnan(dtype_t type, void *val) */ if (!retval) { if (FLT_FLOAT==type) { - float x; + float x = 0.0; HDmemcpy(&x, val, sizeof(float)); HDsnprintf(s, sizeof(s), "%g", (double)x); } else if (FLT_DOUBLE==type) { - double x; + double x = 0.0; HDmemcpy(&x, val, sizeof(double)); HDsnprintf(s, sizeof(s), "%g", x); #if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE && H5_SIZEOF_LONG_DOUBLE!=0 } else if (FLT_LDOUBLE==type) { - long double x; + long double x = 0.0; HDmemcpy(&x, val, sizeof(long double)); HDsnprintf(s, sizeof(s), "%Lg", x); @@ -3197,7 +3197,7 @@ test_conv_flt_1 (const char *name, int run_test, hid_t src, hid_t dst) int check_expo[2]; if (FLT_FLOAT==dst_type) { - float x; + float x = 0.0; HDmemcpy(&x, &buf[j*dst_size], sizeof(float)); if (underflow && HDfabsf(x) <= FLT_MIN && HDfabsf(hw_f) <= FLT_MIN) @@ -3208,7 +3208,7 @@ test_conv_flt_1 (const char *name, int run_test, hid_t src, hid_t dst) check_mant[0] = HDfrexpf(x, check_expo+0); check_mant[1] = HDfrexpf(hw_f, check_expo+1); } else if (FLT_DOUBLE==dst_type) { - double x; + double x = 0.0; HDmemcpy(&x, &buf[j*dst_size], sizeof(double)); if (underflow && HDfabs(x) <= DBL_MIN && HDfabs(hw_d) <= DBL_MIN) @@ -3220,7 +3220,7 @@ test_conv_flt_1 (const char *name, int run_test, hid_t src, hid_t dst) check_mant[1] = HDfrexp(hw_d, check_expo+1); #if H5_SIZEOF_LONG_DOUBLE !=0 && (H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE) } else { - long double x; + long double x = 0.0; HDmemcpy(&x, &buf[j*dst_size], sizeof(long double)); /* dst is largest float, no need to check underflow. */ check_mant[0] = (double)HDfrexpl(x, check_expo+0); @@ -3265,16 +3265,16 @@ test_conv_flt_1 (const char *name, int run_test, hid_t src, hid_t dst) HDprintf(" %02x", saved[j*src_size+ENDIAN(src_size,k,sendian)]); HDprintf("%*s", (int)(3*MAX(0, (ssize_t)dst_size-(ssize_t)src_size)), ""); if (FLT_FLOAT==src_type) { - float x; + float x = 0.0; HDmemcpy(&x, &saved[j*src_size], sizeof(float)); HDprintf(" %29.20e\n", (double)x); } else if (FLT_DOUBLE==src_type) { - double x; + double x = 0.0; HDmemcpy(&x, &saved[j*src_size], sizeof(double)); HDprintf(" %29.20e\n", x); #if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE } else { - long double x; + long double x = 0.0; HDmemcpy(&x, &saved[j*src_size], sizeof(long double)); HDfprintf(stdout," %29.20Le\n", x); #endif @@ -3285,16 +3285,16 @@ test_conv_flt_1 (const char *name, int run_test, hid_t src, hid_t dst) HDprintf(" %02x", buf[j*dst_size+ENDIAN(dst_size,k,dendian)]); HDprintf("%*s", (int)(3*MAX(0, (ssize_t)src_size-(ssize_t)dst_size)), ""); if (FLT_FLOAT==dst_type) { - float x; + float x = 0.0; HDmemcpy(&x, &buf[j*dst_size], sizeof(float)); HDprintf(" %29.20e\n", (double)x); } else if (FLT_DOUBLE==dst_type) { - double x; + double x = 0.0; HDmemcpy(&x, &buf[j*dst_size], sizeof(double)); HDprintf(" %29.20e\n", x); #if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE } else { - long double x; + long double x = 0.0; HDmemcpy(&x, &buf[j*dst_size], sizeof(long double)); HDfprintf(stdout," %29.20Le\n", x); #endif diff --git a/test/dtypes.c b/test/dtypes.c index c89688c..f0c4714 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Tuesday, December 9, 1997 * * Purpose: Tests the datatype interface (H5T) @@ -7642,19 +7642,19 @@ test_versionbounds(void) ret = H5Tenum_insert(enum_type, "RED", &enum_val); if (ret < 0) TEST_ERROR - enum_val++; + enum_val = E1_GREEN; ret = H5Tenum_insert(enum_type, "GREEN", &enum_val); if (ret < 0) TEST_ERROR - enum_val++; + enum_val = E1_BLUE; ret = H5Tenum_insert(enum_type, "BLUE", &enum_val); if (ret < 0) TEST_ERROR - enum_val++; + enum_val = E1_ORANGE; ret = H5Tenum_insert(enum_type, "ORANGE", &enum_val); if (ret < 0) TEST_ERROR - enum_val++; + enum_val = E1_YELLOW; ret = H5Tenum_insert(enum_type, "YELLOW", &enum_val); if (ret < 0) TEST_ERROR diff --git a/test/earray.c b/test/earray.c index aef7e58..d75e125 100644 --- a/test/earray.c +++ b/test/earray.c @@ -11,7 +11,7 @@ * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: Quincey Koziol <koziol@hdfgroup.org> +/* Programmer: Quincey Koziol * Tuesday, June 17, 2008 */ #include "h5test.h" diff --git a/test/enum.c b/test/enum.c index 109f7c3..1933ce1 100644 --- a/test/enum.c +++ b/test/enum.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Tuesday, December 22, 1998 */ #include "h5test.h" diff --git a/test/extend.c b/test/extend.c index 1e2b5b5..369ad32 100644 --- a/test/extend.c +++ b/test/extend.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Friday, January 30, 1998 * * Purpose: Tests extendible datasets. diff --git a/test/external.c b/test/external.c index d29fb6b..c98c228 100644 --- a/test/external.c +++ b/test/external.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Tuesday, March 3, 1998 * * Purpose: Tests datasets stored in external raw files. diff --git a/test/external_common.c b/test/external_common.c index cfd95a3..f0e7961 100644 --- a/test/external_common.c +++ b/test/external_common.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Raymond Lu <songyulu@hdfgroup.org> + * Programmer: Raymond Lu * April, 2019 * * Purpose: Private function for external.c and external_env.c diff --git a/test/external_common.h b/test/external_common.h index f02652b..3633ea3 100644 --- a/test/external_common.h +++ b/test/external_common.h @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Raymond Lu <songyulu@hdfgroup.org> + * Programmer: Raymond Lu * April, 2019 * * Purpose: Private function for external.c and external_env.c diff --git a/test/external_fname.h b/test/external_fname.h index c5111b6..f5aca6d 100644 --- a/test/external_fname.h +++ b/test/external_fname.h @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@lbl.gov> + * Programmer: Quincey Koziol * July, 2019 * * Purpose: Private declaration for external.c and external_env.c diff --git a/test/fheap.c b/test/fheap.c index 771081b..2e63149 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -11,7 +11,7 @@ * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> +/* Programmer: Quincey Koziol * Friday, February 24, 2006 */ #include "h5test.h" diff --git a/test/filter_fail.c b/test/filter_fail.c index e5187be..b3e5c8a 100644 --- a/test/filter_fail.c +++ b/test/filter_fail.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Raymond Lu <songyulu@hdfgroup.org> + * Programmer: Raymond Lu * 7 September 2010 * * Purpose: Make sure dataset, file, and library can close properly when a diff --git a/test/flush1.c b/test/flush1.c index 04f24f7..e01f4a5 100644 --- a/test/flush1.c +++ b/test/flush1.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Friday, October 23, 1998 * * Purpose: This is the first half of a two-part test that makes sure diff --git a/test/flush2.c b/test/flush2.c index 5fc716b..c3103d9 100644 --- a/test/flush2.c +++ b/test/flush2.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Friday, October 23, 1998 * * Purpose: This is the second half of a two-part test that makes sure diff --git a/test/gen_bad_compound.c b/test/gen_bad_compound.c index 292659c..bd857b4 100644 --- a/test/gen_bad_compound.c +++ b/test/gen_bad_compound.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@hdfgroup.org> + * Programmer: Quincey Koziol * April 14, 2011 * * Purpose: This program is run to generate an HDF5 data file with objects diff --git a/test/gen_bad_ohdr.c b/test/gen_bad_ohdr.c index 36ba64a..0f85cfe 100644 --- a/test/gen_bad_ohdr.c +++ b/test/gen_bad_ohdr.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@hdfgroup.org> + * Programmer: Quincey Koziol * Jan 5, 2008 * * Purpose: This program is run to generate an HDF5 data file with a diff --git a/test/gen_bogus.c b/test/gen_bogus.c index 1ab18a4..ab2620f 100644 --- a/test/gen_bogus.c +++ b/test/gen_bogus.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@hdfgroup.org> + * Programmer: Quincey Koziol * Apr 17, 2007 * * Purpose: This program is run to generate an HDF5 data file with several diff --git a/test/gen_cross.c b/test/gen_cross.c index 105895d..2c1ff4d 100644 --- a/test/gen_cross.c +++ b/test/gen_cross.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Raymond Lu <slu@ncsa.uiuc.edu> + * Programmer: Raymond Lu * Thursday, March 23, 2006 * * This program writes floating-point data to the HDF5 file. It generates diff --git a/test/gen_filters.c b/test/gen_filters.c index 9764830..ace86ba 100644 --- a/test/gen_filters.c +++ b/test/gen_filters.c @@ -38,7 +38,7 @@ static size_t filter_bogus(unsigned int flags, size_t cd_nelmts, * * Failure: -1 * - * Programmer: Pedro Vicente <pvn@ncsa.uiuc.edu> + * Programmer: Pedro Vicente * Thursday, March 25, 2004 * *------------------------------------------------------------------------- diff --git a/test/gen_mergemsg.c b/test/gen_mergemsg.c index f158d57..6633eb0 100644 --- a/test/gen_mergemsg.c +++ b/test/gen_mergemsg.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Programmer: Quincey Koziol * Friday, June 30, 2006 * * This program creates an object with fragmented object header messages diff --git a/test/gen_new_array.c b/test/gen_new_array.c index 27f162c..041b691 100644 --- a/test/gen_new_array.c +++ b/test/gen_new_array.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Programmer: Quincey Koziol * Thursday, November 09, 2000 * * Purpose: Create a two datasets, one with a compound datatypes with array diff --git a/test/gen_new_fill.c b/test/gen_new_fill.c index 5bdbf73..c012d8b 100644 --- a/test/gen_new_fill.c +++ b/test/gen_new_fill.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Raymond Lu <slu@ncsa.uiuc.edu> + * Programmer: Raymond Lu * Feb 27, 2002 * * Purpose: This program is run to generate a HDF5 data file with fill diff --git a/test/gen_new_group.c b/test/gen_new_group.c index 6924291..42a751f 100644 --- a/test/gen_new_group.c +++ b/test/gen_new_group.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Programmer: Quincey Koziol * Oct 24, 2005 * * Purpose: This program is run to generate an HDF5 data file with both diff --git a/test/gen_new_mtime.c b/test/gen_new_mtime.c index b44d567..90259c7 100644 --- a/test/gen_new_mtime.c +++ b/test/gen_new_mtime.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Programmer: Quincey Koziol * Friday, January 3, 2003 * * Purpose: Create a dataset, which should have the newer mtime information diff --git a/test/gen_new_super.c b/test/gen_new_super.c index d371f5f..36f2187 100644 --- a/test/gen_new_super.c +++ b/test/gen_new_super.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Programmer: Quincey Koziol * Tuesday, July 15, 2003 * * Purpose: Create a file which will have the newer superblock format. diff --git a/test/gen_old_array.c b/test/gen_old_array.c index 3fab657..402fd40 100644 --- a/test/gen_old_array.c +++ b/test/gen_old_array.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Programmer: Quincey Koziol * Thursday, November 09, 2000 * * Purpose: Create a two datasets with compound datatypes, one with no array diff --git a/test/gen_old_group.c b/test/gen_old_group.c index d109329..55dbde3 100644 --- a/test/gen_old_group.c +++ b/test/gen_old_group.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Programmer: Quincey Koziol * Oct 24, 2005 * * Purpose: This program is run to generate an HDF5 data file with an diff --git a/test/gen_old_layout.c b/test/gen_old_layout.c index 56c3e4e..0210786 100644 --- a/test/gen_old_layout.c +++ b/test/gen_old_layout.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Programmer: Quincey Koziol * Thursday, May 27, 2004 * * Purpose: Create two datasets (one for version 1 and one for version 2 of diff --git a/test/gen_old_mtime.c b/test/gen_old_mtime.c index cbe3bdc..e72c9b1 100644 --- a/test/gen_old_mtime.c +++ b/test/gen_old_mtime.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Programmer: Quincey Koziol * Friday, January 3, 2003 * * Purpose: Create a dataset, which should have the older mtime information diff --git a/test/gen_plist.c b/test/gen_plist.c index f82cc7b..e66b1d6 100644 --- a/test/gen_plist.c +++ b/test/gen_plist.c @@ -461,7 +461,7 @@ encode_plist(hid_t plist_id, int little_endian, int word_length, const char *fil herr_t ret = 0; void *temp_buf = NULL; size_t temp_size = 0; - ssize_t write_size; + ssize_t H5_ATTR_NDEBUG_UNUSED write_size; char filename[1024]; /* Generate filename */ diff --git a/test/gen_sizes_lheap.c b/test/gen_sizes_lheap.c index 81742df..0e62019 100644 --- a/test/gen_sizes_lheap.c +++ b/test/gen_sizes_lheap.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Neil Fortner <nfortne2@hdfgroup.org> + * Programmer: Neil Fortner * Thursday, July 15, 2010 * * Purpose: Creates a file with non-default sizes of lengths and addresses. diff --git a/test/gen_specmetaread.c b/test/gen_specmetaread.c index d06bd59..ca44f9a 100644 --- a/test/gen_specmetaread.c +++ b/test/gen_specmetaread.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@hdfgroup.org> + * Programmer: Quincey Koziol * Thursday, October 8, 2009 * * Purpose: Create a file with a dataset who's raw data immediately follows @@ -23,8 +23,8 @@ * the library on the trunk as of when this file is checked in. */ -#include "hdf5.h" -#include <assert.h> + +#include "h5test.h" #define FILENAME "specmetaread.h5" #define DIM 10 @@ -39,7 +39,7 @@ main(void) hsize_t dim[1] = {DIM}; unsigned data[DIM]; unsigned u; - herr_t ret; /* Generic return value */ + herr_t H5_ATTR_NDEBUG_UNUSED ret; /* Initialize the data */ for(u = 0; u < DIM; u++) diff --git a/test/gen_udlinks.c b/test/gen_udlinks.c index e48d0e8..456cb5c 100644 --- a/test/gen_udlinks.c +++ b/test/gen_udlinks.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: James Laird <jlaird@hdfgroup.org> + * Programmer: James Laird * Tuesday, June 6, 2006 * * This program creates HDF5 files with user-defined links. These files diff --git a/test/getname.c b/test/getname.c index 7933608..7233d17 100644 --- a/test/getname.c +++ b/test/getname.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Pedro Vicente <pvn@ncsa.uiuc.edu> + * Programmer: Pedro Vicente * April 12, 2002 * * Purpose: Tests the "ID to name" functionality diff --git a/test/gheap.c b/test/gheap.c index 32e2785..23fe0ba 100644 --- a/test/gheap.c +++ b/test/gheap.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Tuesday, March 31, 1998 * * Purpose: Tests the global heap. The global heap is the set of all diff --git a/test/h5test.c b/test/h5test.c index 2613ce1..4fa5102 100644 --- a/test/h5test.c +++ b/test/h5test.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Thursday, November 19, 1998 * * Purpose: Provides support functions for most of the hdf5 tests cases. @@ -1889,6 +1889,84 @@ h5_get_version_string(H5F_libver_t 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 + * + * Programmer: Binh-Minh Ribler + * October, 2018 + *------------------------------------------------------------------------- + */ +int +h5_compare_file_bytes(char *f1name, char *f2name) +{ + FILE *f1ptr = NULL; /* two file pointers */ + FILE *f2ptr = NULL; + off_t f1size = 0; /* size of the files */ + off_t f2size = 0; + char f1char = 0; /* one char from each file */ + char f2char = 0; + off_t ii = 0; + int ret_value = 0; /* for error handling */ + + /* Open files for reading */ + f1ptr = HDfopen(f1name, "rb"); + if (f1ptr == NULL) { + HDfprintf(stderr, "Unable to fopen() %s\n", f1name); + ret_value = -1; + goto done; + } + f2ptr = HDfopen(f2name, "rb"); + if (f2ptr == NULL) { + HDfprintf(stderr, "Unable to fopen() %s\n", f2name); + ret_value = -1; + goto done; + } + + /* Get the file sizes and verify that they equal */ + HDfseek(f1ptr , 0 , SEEK_END); + f1size = HDftell(f1ptr); + + HDfseek(f2ptr , 0 , SEEK_END); + f2size = HDftell(f2ptr); + + if (f1size != f2size) { + HDfprintf(stderr, "Files differ in size, %llu vs. %llu\n", f1size, f2size); + ret_value = -1; + goto done; + } + + /* Compare each byte and fail if a difference is found */ + HDrewind(f1ptr); + HDrewind(f2ptr); + for (ii = 0; ii < f1size; ii++) { + if(HDfread(&f1char, 1, 1, f1ptr) != 1) { + ret_value = -1; + goto done; + } + if(HDfread(&f2char, 1, 1, f2ptr) != 1) { + ret_value = -1; + goto done; + } + if (f1char != f2char) { + HDfprintf(stderr, "Mismatch @ 0x%llX: 0x%X != 0x%X\n", ii, f1char, f2char); + ret_value = -1; + goto done; + } + } + +done: + if (f1ptr) + HDfclose(f1ptr); + if (f2ptr) + HDfclose(f2ptr); + return ret_value; +} /* end h5_compare_file_bytes() */ + +/*------------------------------------------------------------------------- * Function: H5_get_srcdir_filename * * Purpose: Append the test file name to the srcdir path and return the whole string @@ -1941,3 +2019,131 @@ const char *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 + * + * Programmer: Jake Smith + * 24 June 2020 + * + *------------------------------------------------------------------------- + */ +int +h5_duplicate_file_by_bytes(const char *orig, const char *dest) +{ + FILE *orig_ptr = NULL; + FILE *dest_ptr = NULL; + hsize_t fsize = 0; + hsize_t read_size = 0; + hsize_t max_buf = 0; + void *dup_buf = NULL; + int ret_value = 0; + + max_buf = 4096 * sizeof(char); + + orig_ptr = HDfopen(orig, "rb"); + if (NULL == orig_ptr) { + ret_value = -1; + goto done; + } + + HDfseek(orig_ptr , 0 , SEEK_END); + fsize = (hsize_t)HDftell(orig_ptr); + HDrewind(orig_ptr); + + dest_ptr = HDfopen(dest, "wb"); + if (NULL == dest_ptr) { + ret_value = -1; + goto done; + } + + read_size = MIN(fsize, max_buf); + dup_buf = HDmalloc(read_size); + if (NULL == dup_buf) { + ret_value = -1; + goto done; + } + + while (read_size > 0) { + if (HDfread(dup_buf, read_size, 1, orig_ptr) != 1) { + ret_value = -1; + goto done; + } + HDfwrite(dup_buf, read_size, 1, dest_ptr); + fsize -= read_size; + read_size = MIN(fsize, max_buf); + } + +done: + if (orig_ptr != NULL) + HDfclose(orig_ptr); + if (dest_ptr != NULL) + HDfclose(dest_ptr); + if (dup_buf != NULL) + HDfree(dup_buf); + 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. + * + *------------------------------------------------------------------------- + */ +herr_t +h5_check_if_file_locking_enabled(hbool_t *is_enabled) +{ + const char *filename = "locking_test_file"; + int pmode = O_RDWR | O_CREAT | O_TRUNC; + int fd = -1; + + *is_enabled = TRUE; + + if((fd = HDopen(filename, pmode, H5_POSIX_CREATE_MODE_RW)) < 0) + goto error; + + /* Test HDflock() to see if it works */ + if(HDflock(fd, LOCK_EX | LOCK_NB) < 0) { + if(ENOSYS == errno) { + /* When errno is set to ENOSYS, the file system does not support + * locking, so ignore it. This is most frequently used on + * Lustre. If we also want to check for disabled NFS locks + * we'll need to check for ENOLCK, too. That isn't done by + * default here since that could also represent an actual + * error condition. + */ + errno = 0; + *is_enabled = FALSE; + } + else + goto error; + } + if(HDflock(fd, LOCK_UN) < 0) + goto error; + + if(HDclose(fd) < 0) + goto error; + if(HDremove(filename) < 0) + goto error; + + return SUCCEED; + +error: + *is_enabled = FALSE; + if (fd > -1) { + HDclose(fd); + HDremove(filename); + } + return FAIL; +} /* end h5_check_if_file_locking_enabled() */ + diff --git a/test/h5test.h b/test/h5test.h index 0d937e1..93cdf96 100644 --- a/test/h5test.h +++ b/test/h5test.h @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Friday, November 20, 1998 * * Purpose: Test support stuff. @@ -206,6 +206,9 @@ H5TEST_DLL int h5_make_local_copy(const char *origfilename, const char *local_co 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 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(hbool_t *are_enabled); /* Functions that will replace components of a FAPL */ H5TEST_DLL herr_t h5_get_vfd_fapl(hid_t fapl_id); diff --git a/test/hyperslab.c b/test/hyperslab.c index e702023..8168eed 100644 --- a/test/hyperslab.c +++ b/test/hyperslab.c @@ -11,7 +11,7 @@ * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: Robb Matzke <matzke@llnl.gov> +/* Programmer: Robb Matzke * Friday, October 10, 1997 * * Purpose: Hyperslab operations are rather complex, so this file diff --git a/test/istore.c b/test/istore.c index c8fe866..e80f260 100644 --- a/test/istore.c +++ b/test/istore.c @@ -11,7 +11,7 @@ * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: Robb Matzke <matzke@llnl.gov> +/* Programmer: Robb Matzke * Wednesday, October 15, 1997 * * Purpose: Tests various aspects of indexed raw data storage. diff --git a/test/lheap.c b/test/lheap.c index 4b40740..54c77a7 100644 --- a/test/lheap.c +++ b/test/lheap.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Tuesday, November 24, 1998 * * Purpose: Test local heaps used by symbol tables (groups). diff --git a/test/mirror_vfd.c b/test/mirror_vfd.c new file mode 100644 index 0000000..35c3f90 --- /dev/null +++ b/test/mirror_vfd.c @@ -0,0 +1,2763 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Purpose: Test the Mirror VFD functionality. + */ + +/* WARNING: The use of realpath() is probably system-dependent, as are + * other things here such as the socket calls. + * Notable to realpath() in particular is the use of "PATH_MAX", which + * apparently has some major potential issues if paths are abused. + * http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html + * so BE CAREFUL about the paths we throw around? + */ + +#include "h5test.h" +#include "cache_common.h" +#include "genall5.h" + +#ifdef H5_HAVE_MIRROR_VFD + +#include "H5FDmirror_priv.h" /* Private header for the mirror VFD */ + +/* For future consideration, IP address and port number might be + * environment variables? + */ +#define SERVER_IP_ADDRESS "127.0.0.1" + +/* Primary listening port on server. */ +#define SERVER_HANDSHAKE_PORT 3000 + +#define DATABUFFER_SIZE 128 +#define DSET_NAME_LEN 16 + +/* Parameters for the "large chunked dataset" writing */ +#define MAX_DSET_COUNT 255 +#define DSET_DIM 32 +#define CHUNK_DIM 8 + +#define CONCURRENT_COUNT 3 /* Number of files in concurrent test */ + +/* Macro: LOGPRINT() + * Prints logging and debugging messages to the output stream based + * on the level of verbosity. + * 0 : no logging + * 1 : errors only + * 2 : details + * 3 : all + */ +#define DEFAULT_VERBOSITY 1 +static unsigned int g_verbosity = DEFAULT_VERBOSITY; + +/* Macro for selective debug printing / logging */ +#define LOGPRINT(lvl, ...) \ +do { \ + if ((lvl) <= g_verbosity) { \ + fprintf(g_log_stream, __VA_ARGS__); \ + fflush(g_log_stream); \ + } \ +} while (0) + +#define MIRROR_RW_DIR "mirror_rw/" +#define MIRROR_WO_DIR "mirror_wo/" + +/* String buffer for error messages */ +#define MIRR_MESG_SIZE 128 +static char mesg[MIRR_MESG_SIZE + 1]; + +/* Convenience structure for passing file names via helper functions. + */ +struct mirrortest_filenames { + char rw[H5FD_SPLITTER_PATH_MAX+1]; + char wo[H5FD_SPLITTER_PATH_MAX+1]; + char log[H5FD_SPLITTER_PATH_MAX+1]; +}; + +static FILE *g_log_stream = NULL; /* initialized at runtime */ + +static herr_t _verify_datasets(unsigned min_dset, unsigned max_dset, + hid_t *filespace_id, hid_t *dataset_id, hid_t memspace_id); + +static herr_t _create_chunking_ids(hid_t file_id, unsigned min_dset, + unsigned max_dset, hsize_t *chunk_dims, hsize_t *dset_dims, + hid_t *dataspace_ids, hid_t *filespace_ids, hid_t *dataset_ids, + hid_t *memspace_id); + +static herr_t _close_chunking_ids(unsigned min_dset, unsigned max_dset, + hid_t *dataspace_ids, hid_t *filespace_ids, hid_t *dataset_ids, + hid_t *memspace_id); + +static herr_t _populate_filepath(const char *dirname, const char *_basename, + hid_t fapl_id, char *path_out, hbool_t h5suffix); + +static hid_t create_mirroring_split_fapl(const char *_basename, + struct mirrortest_filenames *names); + +static void mybzero(void *dest, size_t size); + + +/* ---------------------------------------------------------------------------- + * Function: mybzero + * + * Purpose: Have bzero simplicity and abstraction in (possible) absence of + * it being available. + * + * Programmer: Jacob Smith + * 2020-03-30 + * ---------------------------------------------------------------------------- + */ +static void +mybzero(void *dest, size_t size) +{ + size_t i = 0; + char *s = NULL; + HDassert(dest != NULL); + s = (char *)dest; + for (i = 0; i < size; i++) { + *(s+i) = 0; + } +} /* end mybzero() */ + + +/* ---------------------------------------------------------------------------- + * Function: _populate_filepath + * + * Purpose: Given a directory name and a base name, concatenate the two and + * run h5fixname() to get the "actual" path to the intented target. + * `h5suffix' should be FALSE to keep the base name unaltered; + * TRUE will append the '.h5' h5suffix to the basename... + * FALSE -> h5fixname_no_suffix(), TRUE -> h5fixname() + * <h5fixname_prefix> / <dirname> / <_basename> <h5prefix?> + * + * Programmer: Jacob Smith + * 2019-08-16 + * ---------------------------------------------------------------------------- + */ +static herr_t +_populate_filepath(const char *dirname, const char *_basename, hid_t fapl_id, + char *path_out, hbool_t h5suffix) +{ + char _path[H5FD_SPLITTER_PATH_MAX]; + + if ((_basename == NULL) || + (*_basename == 0) || + (dirname == NULL) || + (*dirname == 0) || + (path_out == NULL)) + { + TEST_ERROR; + } + + if (HDsnprintf(_path, H5FD_SPLITTER_PATH_MAX, "%s%s%s", dirname, + (dirname[strlen(dirname)] == '/') ? "" : "/", /* slash iff needed */ + _basename) + > H5FD_SPLITTER_PATH_MAX) + { + TEST_ERROR; + } + + if (h5suffix == TRUE) { + if (h5_fixname(_path, fapl_id, path_out, + H5FD_SPLITTER_PATH_MAX) + == NULL) + { + TEST_ERROR; + } + } + else { + if (h5_fixname_no_suffix(_path, fapl_id, path_out, + H5FD_SPLITTER_PATH_MAX) + == NULL) + { + TEST_ERROR; + } + } + + return SUCCEED; + +error: + return FAIL; +} /* end _populate_filepath() */ + + +/* --------------------------------------------------------------------------- + * Function: build_paths + * + * Purpose: Convenience function to create the three file paths used in + * most mirror tests. + * + * Return: SUCCEED/FAIL + * + * Programmer: Jacob Smith + * 2019-08-16 + * --------------------------------------------------------------------------- + */ +static herr_t +build_paths( + const char *_basename, + H5FD_splitter_vfd_config_t *splitter_config, + struct mirrortest_filenames *names) +{ + char baselogname[H5FD_SPLITTER_PATH_MAX]; + + if (_populate_filepath(MIRROR_RW_DIR, _basename, + splitter_config->rw_fapl_id, names->rw, TRUE) + == FAIL) + { + TEST_ERROR; + } + + if (_populate_filepath(MIRROR_WO_DIR, _basename, + splitter_config->wo_fapl_id, names->wo, TRUE) + == FAIL) + { + TEST_ERROR; + } + + if (_basename == NULL || *_basename == 0) + return FAIL; + if (HDsnprintf(baselogname, H5FD_SPLITTER_PATH_MAX, "%s_err.log", + _basename) + > H5FD_SPLITTER_PATH_MAX) + { + TEST_ERROR; + } + + if (_populate_filepath(MIRROR_WO_DIR, baselogname, + splitter_config->wo_fapl_id, names->log, FALSE) + == FAIL) + { + TEST_ERROR; + } + + return SUCCEED; + +error: + return FAIL; +} /* end build_paths() */ + + +/* --------------------------------------------------------------------------- + * Function: test_fapl_configuration + * + * Purpose: Test FAPL configuration and examination. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Jacob Smith + * 2019-03-12 + * --------------------------------------------------------------------------- + */ +static int +test_fapl_configuration(void) +{ + hid_t fapl_id; + H5FD_mirror_fapl_t mirror_conf = { + H5FD_MIRROR_FAPL_MAGIC, /* magic */ + H5FD_MIRROR_CURR_FAPL_T_VERSION, /* version */ + SERVER_HANDSHAKE_PORT, /* handhake_port */ + SERVER_IP_ADDRESS, /* remote_ip "IP address" */ + }; + H5FD_mirror_fapl_t fa_out = {0, 0, 0, ""}; + + TESTING("Mirror fapl configuration (set/get)"); + + fapl_id = H5Pcreate(H5P_FILE_ACCESS); + if (H5I_INVALID_HID == fapl_id) { + TEST_ERROR; + } + + if (H5Pset_fapl_mirror(fapl_id, &mirror_conf) == FAIL) { + TEST_ERROR; + } + + if (H5Pget_fapl_mirror(fapl_id, &fa_out) == FAIL) { + TEST_ERROR; + } + if (H5FD_MIRROR_FAPL_MAGIC != fa_out.magic) { + TEST_ERROR; + } + if (H5FD_MIRROR_CURR_FAPL_T_VERSION != fa_out.version) { + TEST_ERROR; + } + if (SERVER_HANDSHAKE_PORT != fa_out.handshake_port) { + TEST_ERROR; + } + if (HDstrncmp(SERVER_IP_ADDRESS, (const char *)fa_out.remote_ip, + H5FD_MIRROR_MAX_IP_LEN)) + { + TEST_ERROR; + } + + if (H5Pclose(fapl_id) == FAIL) { + TEST_ERROR; + } + + PASSED(); + return 0; + +error: + if (H5I_INVALID_HID != fapl_id) { + (void)H5Pclose(fapl_id); + } + return -1; +} /* end test_fapl_configuration() */ + + + +#define PRINT_BUFFER_DIFF(act, exp, len) do { \ + size_t _x = 0; \ + while ((act)[_x] == (exp)[_x]) { \ + _x++; \ + } \ + if (_x != (len)) { \ + size_t _y = 0; \ + HDprintf("First bytes differ at %zu\n", _x); \ + HDprintf("exp "); \ + for (_y = _x; _y < (len); _y++) { \ + HDprintf("%02X", (unsigned char)(exp)[_y]); \ + } \ + HDprintf("\nact "); \ + for (_y = _x; _y < (len); _y++) { \ + HDprintf("%02X", (unsigned char)(act)[_y]); \ + } \ + HDprintf("\n"); \ + } \ +} while (0); /* end PRINT_BUFFER_DIFF */ + + +/* --------------------------------------------------------------------------- + * Function: test_xmit_encode_decode + * + * Purpose: Test byte-encoding operations for network transport. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Jacob Smith + * 2020-02-02 + * --------------------------------------------------------------------------- + */ +static int +test_xmit_encode_decode(void) +{ + H5FD_mirror_xmit_t xmit_mock; /* re-used header in various xmit tests */ + + TESTING("Mirror encode/decode of xmit elements"); + + /* Set bogus values matching expected; encoding doesn't care + * Use sequential values to easily generate the expected buffer with a + * for loop. + */ + xmit_mock.magic = 0x00010203; + xmit_mock.version = 0x04; + xmit_mock.session_token = 0x05060708; + xmit_mock.xmit_count = 0x090A0B0C; + xmit_mock.op = 0x0D; + + /* Test uint8_t encode/decode + */ + do { + unsigned char buf[8]; + unsigned char expected[8]; + const uint8_t v = 200; + unsigned char out = 0; + + /* Start of buffer uint8_t + */ + mybzero(buf, 8); + mybzero(expected, 8); + expected[0] = 200; + out = 0; + if (H5FD__mirror_xmit_encode_uint8(buf, v) != 1) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 8); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint8(&out, buf) != 1) { + TEST_ERROR; + } + if (v != out) { + TEST_ERROR; + } + + /* Middle of buffer uint8_t + */ + mybzero(buf, 8); + mybzero(expected, 8); + expected[3] = v; + out = 0; + if (H5FD__mirror_xmit_encode_uint8((buf+3), v) != 1) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 8); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint8(&out, (buf+3)) != 1) { + TEST_ERROR; + } + if (v != out) { + TEST_ERROR; + } + + /* End of buffer uint8_t + */ + mybzero(buf, 8); + mybzero(expected, 8); + expected[7] = v; + out = 0; + if (H5FD__mirror_xmit_encode_uint8((buf+7), v) != 1) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 8); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint8(&out, (buf+7)) != 1) { + TEST_ERROR; + } + if (v != out) { + TEST_ERROR; + } + + } while (0); /* end uint8_t en/decode */ + + /* Test uint16_t encode/decode + */ + do { + unsigned char buf[8]; + unsigned char expected[8]; + const uint16_t v = 0x8F02; + uint16_t out = 0; + + /* Start of buffer uint16_t + */ + mybzero(buf, 8); + mybzero(expected, 8); + expected[0] = 0x8F; + expected[1] = 0x02; + out = 0; + if (H5FD__mirror_xmit_encode_uint16(buf, v) != 2) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 8); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint16(&out, buf) != 2) { + TEST_ERROR; + } + if (out != v) { + TEST_ERROR; + } + + /* Middle of buffer uint16_t + */ + mybzero(buf, 8); + mybzero(expected, 8); + expected[3] = 0x8F; + expected[4] = 0x02; + out = 0; + if (H5FD__mirror_xmit_encode_uint16((buf+3), v) != 2) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 8); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint16(&out, (buf+3)) != 2) { + TEST_ERROR; + } + if (out != v) { + TEST_ERROR; + } + /* slice */ + if (H5FD__mirror_xmit_decode_uint16(&out, (buf+4)) != 2) { + TEST_ERROR; + } + if (out != 0x0200) { + TEST_ERROR; + } + + /* End of buffer uint16_t + */ + mybzero(buf, 8); + mybzero(expected, 8); + expected[6] = 0x8F; + expected[7] = 0x02; + out = 0; + if (H5FD__mirror_xmit_encode_uint16((buf+6), v) != 2) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 8); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint16(&out, (buf+6)) != 2) { + TEST_ERROR; + } + if (out != v) { + TEST_ERROR; + } + + } while (0); /* end uint16_t en/decode */ + + /* Test uint32_t encode/decode + */ + do { + unsigned char buf[8]; + unsigned char expected[8]; + const uint32_t v = 0x8F020048; + uint32_t out = 0; + + /* Start of buffer uint32_t + */ + mybzero(buf, 8); + mybzero(expected, 8); + expected[0] = 0x8F; + expected[1] = 0x02; + expected[2] = 0x00; + expected[3] = 0x48; + out = 0; + if (H5FD__mirror_xmit_encode_uint32(buf, v) != 4) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 8); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint32(&out, buf) != 4) { + TEST_ERROR; + } + if (out != v) { + TEST_ERROR; + } + + /* Middle of buffer uint32_t + */ + mybzero(buf, 8); + mybzero(expected, 8); + expected[3] = 0x8F; + expected[4] = 0x02; + expected[5] = 0x00; + expected[6] = 0x48; + out = 0; + if (H5FD__mirror_xmit_encode_uint32((buf+3), v) != 4) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 8); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint32(&out, (buf+3)) != 4) { + TEST_ERROR; + } + if (out != v) { + TEST_ERROR; + } + /* slice */ + if (H5FD__mirror_xmit_decode_uint32(&out, (buf+4)) != 4) { + TEST_ERROR; + } + if (out != 0x02004800) { + TEST_ERROR; + } + + /* End of buffer uint32_t + */ + mybzero(buf, 8); + mybzero(expected, 8); + expected[4] = 0x8F; + expected[5] = 0x02; + expected[6] = 0x00; + expected[7] = 0x48; + out = 0; + if (H5FD__mirror_xmit_encode_uint32((buf+4), v) != 4) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 8); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint32(&out, (buf+4)) != 4) { + TEST_ERROR; + } + if (out != v) { + TEST_ERROR; + } + + } while (0); /* end uint32_t en/decode */ + + /* Test uint64_t encode/decode + */ + do { + unsigned char buf[16]; + unsigned char expected[16]; + const uint64_t v = 0x90DCBE17939CE4BB; + uint64_t out = 0; + + /* Start of buffer uint64_t + */ + mybzero(buf, 16); + mybzero(expected, 16); + expected[0] = 0x90; + expected[1] = 0xDC; + expected[2] = 0xBE; + expected[3] = 0x17; + expected[4] = 0x93; + expected[5] = 0x9C; + expected[6] = 0xE4; + expected[7] = 0xBB; + out = 0; + if (H5FD__mirror_xmit_encode_uint64(buf, v) != 8) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 16) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 16); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint64(&out, buf) != 8) { + TEST_ERROR; + } + if (out != v) { + TEST_ERROR; + } + + /* Middle of buffer uint64_t + */ + mybzero(buf, 16); + mybzero(expected, 16); + expected[3] = 0x90; + expected[4] = 0xDC; + expected[5] = 0xBE; + expected[6] = 0x17; + expected[7] = 0x93; + expected[8] = 0x9C; + expected[9] = 0xE4; + expected[10] = 0xBB; + out = 0; + if (H5FD__mirror_xmit_encode_uint64((buf+3), v) != 8) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 16) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 16); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint64(&out, (buf+3)) != 8) { + TEST_ERROR; + } + if (out != v) { + TEST_ERROR; + } + /* slice */ + if (H5FD__mirror_xmit_decode_uint64(&out, (buf+6)) != 8) { + TEST_ERROR; + } + if (out != 0x17939CE4BB000000) { + TEST_ERROR; + } + + /* End of buffer uint64_t + */ + mybzero(buf, 16); + mybzero(expected, 16); + expected[8] = 0x90; + expected[9] = 0xDC; + expected[10] = 0xBE; + expected[11] = 0x17; + expected[12] = 0x93; + expected[13] = 0x9C; + expected[14] = 0xE4; + expected[15] = 0xBB; + out = 0; + if (H5FD__mirror_xmit_encode_uint64((buf+8), v) != 8) { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, 16) != 0) { + PRINT_BUFFER_DIFF(buf, expected, 16); + TEST_ERROR; + } + if (H5FD__mirror_xmit_decode_uint64(&out, (buf+8)) != 8) { + TEST_ERROR; + } + if (out != v) { + TEST_ERROR; + } + + } while (0); /* end uint64_t en/decode */ + + /* Test xmit header structure encode/decode + * Write bogus but easily verifiable data to inside a buffer, and compare. + * Then decode the buffer and compare the structure contents. + * Then repeat from a different offset in the buffer and compare. + */ + do { + unsigned char buf[H5FD_MIRROR_XMIT_HEADER_SIZE+8]; + unsigned char expected[H5FD_MIRROR_XMIT_HEADER_SIZE+8]; + H5FD_mirror_xmit_t xmit_out; + size_t i = 0; + + /* sanity check */ + if (14 != H5FD_MIRROR_XMIT_HEADER_SIZE) { + FAIL_PUTS_ERROR("Header size definition does not match test\n"); + } + + /* Populate the expected buffer; expect end padding of 0xFF + */ + HDmemset(expected, 0xFF, H5FD_MIRROR_XMIT_HEADER_SIZE+8); + for (i=0; i < H5FD_MIRROR_XMIT_HEADER_SIZE; i++) { + expected[i+2] = (unsigned char)i; + } + + /* Encode, and compare buffer contents + * Initial buffer is filled with 0xFF to match expected padding + */ + HDmemset(buf, 0xFF, H5FD_MIRROR_XMIT_HEADER_SIZE+8); + if (H5FD_mirror_xmit_encode_header((buf+2), &xmit_mock) + != H5FD_MIRROR_XMIT_HEADER_SIZE) + { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, H5FD_MIRROR_XMIT_HEADER_SIZE+8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, H5FD_MIRROR_XMIT_HEADER_SIZE+8); + TEST_ERROR; + } + + /* Decode from buffer + */ + if (H5FD_mirror_xmit_decode_header(&xmit_out, (buf+2)) + != H5FD_MIRROR_XMIT_HEADER_SIZE) + { + TEST_ERROR; + } + if (xmit_out.magic != xmit_mock.magic) TEST_ERROR; + if (xmit_out.version != xmit_mock.version) TEST_ERROR; + if (xmit_out.session_token != xmit_mock.session_token) TEST_ERROR; + if (xmit_out.xmit_count != xmit_mock.xmit_count) TEST_ERROR; + if (xmit_out.op != xmit_mock.op) TEST_ERROR; + + /* Decode from different offset in buffer + * Observe changes when ingesting the padding + */ + if (H5FD_mirror_xmit_decode_header(&xmit_out, (buf)) + != H5FD_MIRROR_XMIT_HEADER_SIZE) + { + TEST_ERROR; + } + if (xmit_out.magic != 0xFFFF0001) TEST_ERROR; + if (xmit_out.version != 0x02) TEST_ERROR; + if (xmit_out.session_token != 0x03040506) TEST_ERROR; + if (xmit_out.xmit_count != 0x0708090A) TEST_ERROR; + if (xmit_out.op != 0x0B) TEST_ERROR; + + } while (0); /* end xmit header en/decode */ + + /* Test xmit set-eoa structure encode/decode + * Write bogus but easily verifiable data to inside a buffer, and compare. + * Then decode the buffer and compare the structure contents. + * Then repeat from a different offset in the buffer and compare. + */ + do { + unsigned char buf[H5FD_MIRROR_XMIT_EOA_SIZE+8]; + unsigned char expected[H5FD_MIRROR_XMIT_EOA_SIZE+8]; + H5FD_mirror_xmit_eoa_t xmit_in; + H5FD_mirror_xmit_eoa_t xmit_out; + size_t i = 0; + + /* sanity check */ + if ((14+9) != H5FD_MIRROR_XMIT_EOA_SIZE) { + FAIL_PUTS_ERROR("Header size definition does not match test\n"); + } + if (xmit_mock.op != 0x0D) { + FAIL_PUTS_ERROR("shared header structure is not in expected state"); + } + + /* Populate the expected buffer; expect end padding of 0xFF + */ + HDmemset(expected, 0xFF, H5FD_MIRROR_XMIT_EOA_SIZE+8); + for (i=0; i < H5FD_MIRROR_XMIT_EOA_SIZE; i++) { + expected[i+2] = (unsigned char)i; + } + + /* Set xmit_in + */ + xmit_in.pub = xmit_mock; /* shared/common */ + xmit_in.type = 0x0E; + xmit_in.eoa_addr = 0x0F10111213141516; + + /* Encode, and compare buffer contents + * Initial buffer is filled with 0xFF to match expected padding + */ + HDmemset(buf, 0xFF, H5FD_MIRROR_XMIT_EOA_SIZE+8); + if (H5FD_mirror_xmit_encode_set_eoa((buf+2), &xmit_in) + != H5FD_MIRROR_XMIT_EOA_SIZE) + { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, H5FD_MIRROR_XMIT_EOA_SIZE+8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, H5FD_MIRROR_XMIT_EOA_SIZE+8); + TEST_ERROR; + } + + /* Decode from buffer + */ + if (H5FD_mirror_xmit_decode_set_eoa(&xmit_out, (buf+2)) + != H5FD_MIRROR_XMIT_EOA_SIZE) + { + TEST_ERROR; + } + if (xmit_out.pub.magic != xmit_mock.magic) TEST_ERROR; + if (xmit_out.pub.version != xmit_mock.version) TEST_ERROR; + if (xmit_out.pub.session_token != xmit_mock.session_token) TEST_ERROR; + if (xmit_out.pub.xmit_count != xmit_mock.xmit_count) TEST_ERROR; + if (xmit_out.pub.op != xmit_mock.op) TEST_ERROR; + if (xmit_out.type != 0x0E) TEST_ERROR; + if (xmit_out.eoa_addr != 0x0F10111213141516) TEST_ERROR; + + /* Decode from different offset in buffer + * Observe changes when ingesting the padding + */ + if (H5FD_mirror_xmit_decode_set_eoa(&xmit_out, (buf)) + != H5FD_MIRROR_XMIT_EOA_SIZE) + { + TEST_ERROR; + } + if (xmit_out.pub.magic != 0xFFFF0001) TEST_ERROR; + if (xmit_out.pub.version != 0x02) TEST_ERROR; + if (xmit_out.pub.session_token != 0x03040506) TEST_ERROR; + if (xmit_out.pub.xmit_count != 0x0708090A) TEST_ERROR; + if (xmit_out.pub.op != 0x0B) TEST_ERROR; + if (xmit_out.type != 0x0C) TEST_ERROR; + if (xmit_out.eoa_addr != 0x0D0E0F1011121314) TEST_ERROR; + + } while (0); /* end xmit set-eoa en/decode */ + + /* Test xmit lock structure encode/decode + * Write bogus but easily verifiable data to inside a buffer, and compare. + * Then decode the buffer and compare the structure contents. + * Then repeat from a different offset in the buffer and compare. + */ + do { + unsigned char buf[H5FD_MIRROR_XMIT_LOCK_SIZE+8]; + unsigned char expected[H5FD_MIRROR_XMIT_LOCK_SIZE+8]; + H5FD_mirror_xmit_lock_t xmit_in; + H5FD_mirror_xmit_lock_t xmit_out; + size_t i = 0; + + /* sanity check */ + if ((14+8) != H5FD_MIRROR_XMIT_LOCK_SIZE) { + FAIL_PUTS_ERROR("Header size definition does not match test\n"); + } + if (xmit_mock.op != 0x0D) { + FAIL_PUTS_ERROR("shared header structure is not in expected state"); + } + + /* Populate the expected buffer; expect end padding of 0xFF + */ + HDmemset(expected, 0xFF, H5FD_MIRROR_XMIT_LOCK_SIZE+8); + for (i=0; i < H5FD_MIRROR_XMIT_LOCK_SIZE; i++) { + expected[i+2] = (unsigned char)i; + } + + /* Set xmit_in + */ + xmit_in.pub = xmit_mock; /* shared/common */ + xmit_in.rw = 0x0E0F101112131415; + + /* Encode, and compare buffer contents + * Initial buffer is filled with 0xFF to match expected padding + */ + HDmemset(buf, 0xFF, H5FD_MIRROR_XMIT_LOCK_SIZE+8); + if (H5FD_mirror_xmit_encode_lock((buf+2), &xmit_in) + != H5FD_MIRROR_XMIT_LOCK_SIZE) + { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, H5FD_MIRROR_XMIT_LOCK_SIZE+8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, H5FD_MIRROR_XMIT_LOCK_SIZE+8); + TEST_ERROR; + } + + /* Decode from buffer + */ + if (H5FD_mirror_xmit_decode_lock(&xmit_out, (buf+2)) + != H5FD_MIRROR_XMIT_LOCK_SIZE) + { + TEST_ERROR; + } + if (xmit_out.pub.magic != xmit_mock.magic) TEST_ERROR; + if (xmit_out.pub.version != xmit_mock.version) TEST_ERROR; + if (xmit_out.pub.session_token != xmit_mock.session_token) TEST_ERROR; + if (xmit_out.pub.xmit_count != xmit_mock.xmit_count) TEST_ERROR; + if (xmit_out.pub.op != xmit_mock.op) TEST_ERROR; + if (xmit_out.rw != 0x0E0F101112131415) TEST_ERROR; + + /* Decode from different offset in buffer + * Observe changes when ingesting the padding + */ + if (H5FD_mirror_xmit_decode_lock(&xmit_out, (buf)) + != H5FD_MIRROR_XMIT_LOCK_SIZE) + { + TEST_ERROR; + } + if (xmit_out.pub.magic != 0xFFFF0001) TEST_ERROR; + if (xmit_out.pub.version != 0x02) TEST_ERROR; + if (xmit_out.pub.session_token != 0x03040506) TEST_ERROR; + if (xmit_out.pub.xmit_count != 0x0708090A) TEST_ERROR; + if (xmit_out.pub.op != 0x0B) TEST_ERROR; + if (xmit_out.rw != 0x0C0D0E0F10111213) TEST_ERROR; + + } while (0); /* end xmit lock en/decode */ + + /* Test xmit open structure encode/decode + * Write bogus but easily verifiable data to inside a buffer, and compare. + * Then decode the buffer and compare the structure contents. + * Then repeat from a different offset in the buffer and compare. + * + * Verifies that the first zero character in the filepath will end the + * string, with all following bytes in the encoded buffer being zeroed. + */ + do { + unsigned char buf[H5FD_MIRROR_XMIT_OPEN_SIZE+8]; + unsigned char expected[H5FD_MIRROR_XMIT_OPEN_SIZE+8]; + H5FD_mirror_xmit_open_t xmit_in; + H5FD_mirror_xmit_open_t xmit_out; + size_t i = 0; + + /* sanity check */ + if ((14+20+4097) != H5FD_MIRROR_XMIT_OPEN_SIZE) { + FAIL_PUTS_ERROR("Header size definition does not match test\n"); + } + if (xmit_mock.op != 0x0D) { + FAIL_PUTS_ERROR("shared header structure is not in expected state"); + } + + /* Populate the expected buffer; expect end padding of 0xFF + */ + HDmemset(expected, 0xFF, H5FD_MIRROR_XMIT_OPEN_SIZE+8); + for (i=0; i < H5FD_MIRROR_XMIT_OPEN_SIZE; i++) { + /* 0x100 is "zero" in a byte, so encode will treat it as a NULL- + * terminator in the filepath string. Expect all zeroes following. + */ + expected[i+2] = (i > 0xFF) ? 0 : (unsigned char)i; + } + + /* Set xmit_in + */ + xmit_in.pub = xmit_mock; /* shared/common */ + xmit_in.flags = 0x0E0F1011; + xmit_in.maxaddr = 0x1213141516171819; + xmit_in.size_t_blob = 0x1A1B1C1D1E1F2021; + for (i=0x22; i < H5FD_MIRROR_XMIT_FILEPATH_MAX+0x22; i++) { + /* nonzero values repeat after 0x100, but will not be encoded */ + xmit_in.filename[i-0x22] = (char)(i % 0x100); + } + xmit_in.filename[H5FD_MIRROR_XMIT_FILEPATH_MAX-1] = 0; + + /* Encode, and compare buffer contents + * Initial buffer is filled with 0xFF to match expected padding + */ + HDmemset(buf, 0xFF, H5FD_MIRROR_XMIT_OPEN_SIZE+8); + if (H5FD_mirror_xmit_encode_open((buf+2), &xmit_in) + != H5FD_MIRROR_XMIT_OPEN_SIZE) + { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, H5FD_MIRROR_XMIT_OPEN_SIZE+8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, H5FD_MIRROR_XMIT_OPEN_SIZE+8); + TEST_ERROR; + } + + /* Decode from buffer + */ + if (H5FD_mirror_xmit_decode_open(&xmit_out, (buf+2)) + != H5FD_MIRROR_XMIT_OPEN_SIZE) + { + TEST_ERROR; + } + if (xmit_out.pub.magic != xmit_mock.magic) TEST_ERROR; + if (xmit_out.pub.version != xmit_mock.version) TEST_ERROR; + if (xmit_out.pub.session_token != xmit_mock.session_token) TEST_ERROR; + if (xmit_out.pub.xmit_count != xmit_mock.xmit_count) TEST_ERROR; + if (xmit_out.pub.op != xmit_mock.op) TEST_ERROR; + if (xmit_out.flags != xmit_in.flags) TEST_ERROR; + if (xmit_out.maxaddr != xmit_in.maxaddr) TEST_ERROR; + if (xmit_out.size_t_blob != xmit_in.size_t_blob) TEST_ERROR; + if (HDstrncmp(xmit_out.filename, xmit_in.filename, + H5FD_MIRROR_XMIT_FILEPATH_MAX) + != 0) + { + PRINT_BUFFER_DIFF(xmit_out.filename, xmit_in.filename, + H5FD_MIRROR_XMIT_FILEPATH_MAX); + TEST_ERROR; + } + + /* Decode from different offset in buffer + * Observe changes when ingesting the padding + */ + if (H5FD_mirror_xmit_decode_open(&xmit_out, (buf)) + != H5FD_MIRROR_XMIT_OPEN_SIZE) + { + TEST_ERROR; + } + if (xmit_out.pub.magic != 0xFFFF0001) TEST_ERROR; + if (xmit_out.pub.version != 0x02) TEST_ERROR; + if (xmit_out.pub.session_token != 0x03040506) TEST_ERROR; + if (xmit_out.pub.xmit_count != 0x0708090A) TEST_ERROR; + if (xmit_out.pub.op != 0x0B) TEST_ERROR; + if (xmit_out.flags != 0x0C0D0E0F) TEST_ERROR; + if (xmit_out.maxaddr != 0x1011121314151617) TEST_ERROR; + if (xmit_out.size_t_blob != 0x18191A1B1C1D1E1F) TEST_ERROR; + /* update expected "filepath" in structure */ + for (i=0x20; i < H5FD_MIRROR_XMIT_FILEPATH_MAX+0x20; i++) { + xmit_in.filename[i-0x20] = (i > 0xFF) ? 0 : (char)i; + } + if (HDstrncmp(xmit_out.filename, xmit_in.filename, + H5FD_MIRROR_XMIT_FILEPATH_MAX) + != 0) + { + PRINT_BUFFER_DIFF(xmit_out.filename, xmit_in.filename, + H5FD_MIRROR_XMIT_FILEPATH_MAX); + TEST_ERROR; + } + + } while (0); /* end xmit open en/decode */ + + /* Test xmit reply structure encode/decode + * Write bogus but easily verifiable data to inside a buffer, and compare. + * Then decode the buffer and compare the structure contents. + * Then repeat from a different offset in the buffer and compare. + * + * Verifies that the first zero character in the filepath will end the + * string, with all following bytes in the encoded buffer being zeroed. + */ + do { + unsigned char buf[H5FD_MIRROR_XMIT_REPLY_SIZE+8]; + unsigned char expected[H5FD_MIRROR_XMIT_REPLY_SIZE+8]; + H5FD_mirror_xmit_reply_t xmit_in; + H5FD_mirror_xmit_reply_t xmit_out; + size_t i = 0; + + /* sanity check */ + if ((14+4+256) != H5FD_MIRROR_XMIT_REPLY_SIZE) { + FAIL_PUTS_ERROR("Header size definition does not match test\n"); + } + if (xmit_mock.op != 0x0D) { + FAIL_PUTS_ERROR("shared header structure is not in expected state"); + } + + /* Populate the expected buffer; expect end padding of 0xFF + */ + HDmemset(expected, 0xFF, H5FD_MIRROR_XMIT_REPLY_SIZE+8); + for (i=0; i < H5FD_MIRROR_XMIT_REPLY_SIZE; i++) { + /* 0x100 is "zero" in a byte, so encode will treat it as a NULL- + * terminator in the filepath string. Expect all zeroes following. + */ + expected[i+2] = (i > 0xFF) ? 0 : (unsigned char)i; + } + + /* Set xmit_in + */ + xmit_in.pub = xmit_mock; /* shared/common */ + xmit_in.status = 0x0E0F1011; + for (i=0x12; i < H5FD_MIRROR_STATUS_MESSAGE_MAX+0x12; i++) { + /* nonzero values repeat after 0x100, but will not be encoded */ + xmit_in.message[i-0x12] = (char)(i % 0x100); + } + xmit_in.message[H5FD_MIRROR_STATUS_MESSAGE_MAX-1] = 0; + + /* Encode, and compare buffer contents + * Initial buffer is filled with 0xFF to match expected padding + */ + HDmemset(buf, 0xFF, H5FD_MIRROR_XMIT_REPLY_SIZE+8); + if (H5FD_mirror_xmit_encode_reply((buf+2), &xmit_in) + != H5FD_MIRROR_XMIT_REPLY_SIZE) + { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, H5FD_MIRROR_XMIT_REPLY_SIZE+8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, H5FD_MIRROR_XMIT_REPLY_SIZE+8); + TEST_ERROR; + } + + /* Decode from buffer + */ + if (H5FD_mirror_xmit_decode_reply(&xmit_out, (buf+2)) + != H5FD_MIRROR_XMIT_REPLY_SIZE) + { + TEST_ERROR; + } + if (xmit_out.pub.magic != xmit_mock.magic) TEST_ERROR; + if (xmit_out.pub.version != xmit_mock.version) TEST_ERROR; + if (xmit_out.pub.session_token != xmit_mock.session_token) TEST_ERROR; + if (xmit_out.pub.xmit_count != xmit_mock.xmit_count) TEST_ERROR; + if (xmit_out.pub.op != xmit_mock.op) TEST_ERROR; + if (xmit_out.status != xmit_in.status) TEST_ERROR; + if (HDstrncmp(xmit_out.message, xmit_in.message, + H5FD_MIRROR_STATUS_MESSAGE_MAX) + != 0) + { + PRINT_BUFFER_DIFF(xmit_out.message, xmit_in.message, + H5FD_MIRROR_STATUS_MESSAGE_MAX); + TEST_ERROR; + } + + /* Decode from different offset in buffer + * Observe changes when ingesting the padding + */ + if (H5FD_mirror_xmit_decode_reply(&xmit_out, (buf)) + != H5FD_MIRROR_XMIT_REPLY_SIZE) + { + TEST_ERROR; + } + if (xmit_out.pub.magic != 0xFFFF0001) TEST_ERROR; + if (xmit_out.pub.version != 0x02) TEST_ERROR; + if (xmit_out.pub.session_token != 0x03040506) TEST_ERROR; + if (xmit_out.pub.xmit_count != 0x0708090A) TEST_ERROR; + if (xmit_out.pub.op != 0x0B) TEST_ERROR; + if (xmit_out.status != 0x0C0D0E0F) TEST_ERROR; + /* update expected "message" in structure */ + for (i=0x10; i < H5FD_MIRROR_STATUS_MESSAGE_MAX+0x10; i++) { + xmit_in.message[i-0x10] = (i > 0xFF) ? 0 : (char)i; + } + if (HDstrncmp(xmit_out.message, xmit_in.message, + H5FD_MIRROR_STATUS_MESSAGE_MAX) + != 0) + { + PRINT_BUFFER_DIFF(xmit_out.message, xmit_in.message, + H5FD_MIRROR_STATUS_MESSAGE_MAX); + TEST_ERROR; + } + + } while (0); /* end xmit reply en/decode */ + + /* Test xmit write structure encode/decode + * Write bogus but easily verifiable data to inside a buffer, and compare. + * Then decode the buffer and compare the structure contents. + * Then repeat from a different offset in the buffer and compare. + */ + do { + unsigned char buf[H5FD_MIRROR_XMIT_WRITE_SIZE+8]; + unsigned char expected[H5FD_MIRROR_XMIT_WRITE_SIZE+8]; + H5FD_mirror_xmit_write_t xmit_in; + H5FD_mirror_xmit_write_t xmit_out; + size_t i = 0; + + /* sanity check */ + if ((14+17) != H5FD_MIRROR_XMIT_WRITE_SIZE) { + FAIL_PUTS_ERROR("Header size definition does not match test\n"); + } + if (xmit_mock.op != 0x0D) { + FAIL_PUTS_ERROR("shared header structure is not in expected state"); + } + + /* Populate the expected buffer; expect end padding of 0xFF + */ + HDmemset(expected, 0xFF, H5FD_MIRROR_XMIT_WRITE_SIZE+8); + for (i=0; i < H5FD_MIRROR_XMIT_WRITE_SIZE; i++) { + expected[i+2] = (unsigned char)i; + } + + /* Set xmit_in + */ + xmit_in.pub = xmit_mock; /* shared/common */ + xmit_in.type = 0x0E; + xmit_in.offset = 0x0F10111213141516; + xmit_in.size = 0x1718191A1B1C1D1E; + + /* Encode, and compare buffer contents + * Initial buffer is filled with 0xFF to match expected padding + */ + HDmemset(buf, 0xFF, H5FD_MIRROR_XMIT_WRITE_SIZE+8); + if (H5FD_mirror_xmit_encode_write((buf+2), &xmit_in) + != H5FD_MIRROR_XMIT_WRITE_SIZE) + { + TEST_ERROR; + } + if (HDmemcmp(buf, expected, H5FD_MIRROR_XMIT_WRITE_SIZE+8) != 0) { + PRINT_BUFFER_DIFF(buf, expected, H5FD_MIRROR_XMIT_WRITE_SIZE+8); + TEST_ERROR; + } + + /* Decode from buffer + */ + if (H5FD_mirror_xmit_decode_write(&xmit_out, (buf+2)) + != H5FD_MIRROR_XMIT_WRITE_SIZE) + { + TEST_ERROR; + } + if (xmit_out.pub.magic != xmit_mock.magic) TEST_ERROR; + if (xmit_out.pub.version != xmit_mock.version) TEST_ERROR; + if (xmit_out.pub.session_token != xmit_mock.session_token) TEST_ERROR; + if (xmit_out.pub.xmit_count != xmit_mock.xmit_count) TEST_ERROR; + if (xmit_out.pub.op != xmit_mock.op) TEST_ERROR; + if (xmit_out.type != 0x0E) TEST_ERROR; + if (xmit_out.offset != 0x0F10111213141516) TEST_ERROR; + if (xmit_out.size != 0x1718191A1B1C1D1E) TEST_ERROR; + + /* Decode from different offset in buffer + * Observe changes when ingesting the padding + */ + if (H5FD_mirror_xmit_decode_write(&xmit_out, (buf)) + != H5FD_MIRROR_XMIT_WRITE_SIZE) + { + TEST_ERROR; + } + if (xmit_out.pub.magic != 0xFFFF0001) TEST_ERROR; + if (xmit_out.pub.version != 0x02) TEST_ERROR; + if (xmit_out.pub.session_token != 0x03040506) TEST_ERROR; + if (xmit_out.pub.xmit_count != 0x0708090A) TEST_ERROR; + if (xmit_out.pub.op != 0x0B) TEST_ERROR; + if (xmit_out.type != 0x0C) TEST_ERROR; + if (xmit_out.offset != 0x0D0E0F1011121314) TEST_ERROR; + if (xmit_out.size != 0x15161718191A1B1C) TEST_ERROR; + + } while (0); /* end xmit write en/decode */ + + PASSED(); + return 0; + +error: + return -1; +} /* end test_xmit_encode_decode */ + + +/* --------------------------------------------------------------------------- + * Function: create_mirroring_split_fapl + * + * Purpose: Create and populate a mirroring FAPL ID. + * Creates target files with the given base name -- ideally the + * test name -- and creates mirroring/split FAPL set to use the + * global mirroring info and a sec2 R/W channel driver. + * + * TODO: receive target IP from caller? + * + * Return: Success: HID of the top-level (splitter) FAPL, a non-negative + * value. + * Failure: H5I_INVALID_HID, a negative value. + * + * Programmer: Jacob Smith + * 2019 + * --------------------------------------------------------------------------- + */ +static hid_t +create_mirroring_split_fapl(const char *_basename, + struct mirrortest_filenames *names) +{ + H5FD_splitter_vfd_config_t splitter_config; + H5FD_mirror_fapl_t mirror_conf; + hid_t ret_value = H5I_INVALID_HID; + + if (_basename == NULL || *_basename == '\0') { + TEST_ERROR; + } + + splitter_config.magic = H5FD_SPLITTER_MAGIC; + splitter_config.version = H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION; + splitter_config.ignore_wo_errs = FALSE; + + /* Create Splitter R/W channel driver (sec2) + */ + splitter_config.rw_fapl_id = H5Pcreate(H5P_FILE_ACCESS); + if (H5I_INVALID_HID == splitter_config.rw_fapl_id) { + TEST_ERROR; + } + if (H5Pset_fapl_sec2(splitter_config.rw_fapl_id) == FAIL) { + TEST_ERROR; + } + + /* Create Splitter W/O channel driver (mirror) + */ + mirror_conf.magic = H5FD_MIRROR_FAPL_MAGIC; + mirror_conf.version = H5FD_MIRROR_CURR_FAPL_T_VERSION; + mirror_conf.handshake_port = SERVER_HANDSHAKE_PORT; + if (HDstrncpy(mirror_conf.remote_ip, SERVER_IP_ADDRESS, + H5FD_MIRROR_MAX_IP_LEN) + == NULL) + { + TEST_ERROR; + } + splitter_config.wo_fapl_id = H5Pcreate(H5P_FILE_ACCESS); + if (H5I_INVALID_HID == splitter_config.wo_fapl_id) { + TEST_ERROR; + } + if (H5Pset_fapl_mirror(splitter_config.wo_fapl_id, &mirror_conf) == FAIL) { + TEST_ERROR; + } + + /* Build r/w, w/o, and log file paths + */ + if (build_paths(_basename, &splitter_config, names) < 0) { + TEST_ERROR; + } + + /* Set file paths for w/o and logfile + */ + if (HDstrncpy(splitter_config.wo_path, (const char *)names->wo, + H5FD_SPLITTER_PATH_MAX) + == NULL) + { + TEST_ERROR; + } + if (HDstrncpy(splitter_config.log_file_path, (const char *)names->log, + H5FD_SPLITTER_PATH_MAX) + == NULL) + { + TEST_ERROR; + } + + /* Create Splitter FAPL + */ + ret_value = H5Pcreate(H5P_FILE_ACCESS); + if (H5I_INVALID_HID == ret_value) { + TEST_ERROR; + } + if (H5Pset_fapl_splitter(ret_value, &splitter_config) == FAIL) { + TEST_ERROR; + } + + /* Close FAPLs created for child channels + */ + if (H5Pclose(splitter_config.rw_fapl_id) < 0) { + TEST_ERROR; + } + splitter_config.rw_fapl_id = H5I_INVALID_HID; + if (H5Pclose(splitter_config.wo_fapl_id) < 0) { + TEST_ERROR; + } + splitter_config.wo_fapl_id = H5I_INVALID_HID; + + return ret_value; + +error: + if (splitter_config.wo_fapl_id >= 0) { + (void)H5Pclose(splitter_config.wo_fapl_id); + } + if (splitter_config.rw_fapl_id >= 0) { + (void)H5Pclose(splitter_config.rw_fapl_id); + } + if (ret_value >= 0) { + (void)H5Pclose(ret_value); + } + return H5I_INVALID_HID; +} /* end create_mirroring_split_fapl() */ + + +/* --------------------------------------------------------------------------- + * Function: test_create_and_close + * + * Purpose: Test/demonstrate a do-nothing file open and close. + * + * Verifying file existence and contents is part of other tests. + * + * TODO: receive target IP from caller? + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Jacob Smith + * 2019-12-17 + * --------------------------------------------------------------------------- + */ +static int +test_create_and_close(void) +{ + struct mirrortest_filenames names; + hid_t file_id = H5I_INVALID_HID; + hid_t fapl_id = H5P_DEFAULT; + + TESTING("File creation and immediate close"); + + /* Create FAPL for Splitter[sec2|mirror] + */ + fapl_id = create_mirroring_split_fapl("basic_create", &names); + if (H5I_INVALID_HID == fapl_id) { + TEST_ERROR; + } + + /* -------------------- */ + /* TEST: Create and Close */ + + file_id = H5Fcreate(names.rw, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + if (H5I_INVALID_HID == file_id) { + TEST_ERROR; + } + + /* -------------------- */ + /* Standard cleanup */ + + if (H5Fclose(file_id) == FAIL) { + TEST_ERROR; + } + if (fapl_id != H5P_DEFAULT && fapl_id >= 0) { + if (H5Pclose(fapl_id) == FAIL) { + TEST_ERROR; + } + } + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY{ + (void)H5Fclose(file_id); + (void)H5Pclose(fapl_id); + } H5E_END_TRY; + return -1; +} /* end test_create_and_close() */ + + +/* ---------------------------------------------------------------------------- + * Function: create_datasets + * + * Purpose: Given a file ID and least and greateset dataset indices, create + * populated chunked datasets in the target file from min_dset to + * (and including) max_dset. + * Uses #defined constants to determine chunk and dataset sizes + * and values. + * + * Return: SUCCEED/FAIL + * + * Programmer: Jacob Smith + * 2019-08-14 + * ---------------------------------------------------------------------------- + */ +static herr_t +create_datasets(hid_t file_id, + unsigned min_dset, + unsigned max_dset) +{ + hid_t dataspace_ids[MAX_DSET_COUNT + 1]; + hid_t dataset_ids[MAX_DSET_COUNT + 1]; + hid_t filespace_ids[MAX_DSET_COUNT + 1]; + int data_chunk[CHUNK_DIM][CHUNK_DIM]; + unsigned int i, j, k, l, m; + hsize_t offset[2]; + hid_t memspace_id = H5I_INVALID_HID; + hsize_t a_size[2] = {CHUNK_DIM, CHUNK_DIM}; + hsize_t chunk_dims[2] = {CHUNK_DIM, CHUNK_DIM}; + hsize_t dset_dims[2] = {DSET_DIM, DSET_DIM}; + + HDassert(file_id >= 0); + HDassert(min_dset <= max_dset); + HDassert(max_dset <= MAX_DSET_COUNT); + + LOGPRINT(2, "create_dataset()\n"); + + /* --------------------------------- + * "Clear" ID arrays + */ + + for (i = 0; i < MAX_DSET_COUNT; i++) { + LOGPRINT(3, "clearing IDs [%d]\n", i); + dataspace_ids[i] = H5I_INVALID_HID; + dataset_ids[i] = H5I_INVALID_HID; + filespace_ids[i] = H5I_INVALID_HID; + } + + /* --------------------------------- + * Generate dataspace, dataset, and 'filespace' IDs + */ + + if (_create_chunking_ids(file_id, min_dset, max_dset, chunk_dims, + dset_dims, dataspace_ids, filespace_ids, dataset_ids, &memspace_id) + == FAIL) + { + TEST_ERROR; + } + + /* --------------------------------- + * Initialize (write) all datasets in a "round robin"... + * for a given chunk 'location', write chunk data to each dataset. + */ + + for (i = 0; i < DSET_DIM; i += CHUNK_DIM) + { + LOGPRINT(3, "i: %d\n", i); + for (j = 0; j < DSET_DIM; j += CHUNK_DIM) + { + LOGPRINT(3, " j: %d\n", j); + for (m = min_dset; m <= max_dset; m++) + { + LOGPRINT(3, " m: %d\n", m); + for (k = 0; k < CHUNK_DIM; k++) + { + for (l = 0; l < CHUNK_DIM; l++) + { + data_chunk[k][l] = (int)((DSET_DIM * DSET_DIM * m) + + (DSET_DIM * (i + k)) + j + l); + LOGPRINT(3, " data_chunk[%d][%d]: %d\n", + k, l, data_chunk[k][l]); + } + } + + /* select on disk hyperslab */ + offset[0] = (hsize_t)i; + offset[1] = (hsize_t)j; + LOGPRINT(3, " H5Sselect_hyperslab()\n"); + if (H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET, + offset, NULL, a_size, NULL) + < 0) + { + TEST_ERROR; + } + + LOGPRINT(3, " H5Dwrite()\n"); + if (H5Dwrite(dataset_ids[m], H5T_NATIVE_INT, memspace_id, + filespace_ids[m], H5P_DEFAULT, data_chunk) + < 0) + { + TEST_ERROR; + } + + } + } + } + + /* --------------------------------- + * Read and verify data from datasets + */ + + if (_verify_datasets(min_dset, max_dset, filespace_ids, dataset_ids, + memspace_id) + == FAIL) + { + TEST_ERROR; + } + + /* --------------------------------- + * Cleanup + */ + + if (_close_chunking_ids(min_dset, max_dset, dataspace_ids, filespace_ids, + dataset_ids, &memspace_id) + == FAIL) + { + TEST_ERROR; + } + + return SUCCEED; + +error: + (void)_close_chunking_ids(min_dset, max_dset, dataspace_ids, + filespace_ids, dataset_ids, &memspace_id); + LOGPRINT(1, "create_datasets() FAILED\n"); + return FAIL; +} /* end create_datasets() */ + + +/* ---------------------------------------------------------------------------- + * Function: _create_chunking_ids + * + * Purpose: Create new IDs to be used with the associated file. + * + * Return: SUCCEED/FAIL + * + * Programer: Jacob Smith + * 2019 + * ---------------------------------------------------------------------------- + */ +static herr_t +_create_chunking_ids(hid_t file_id, + unsigned min_dset, + unsigned max_dset, + hsize_t *chunk_dims, + hsize_t *dset_dims, + hid_t *dataspace_ids, + hid_t *filespace_ids, + hid_t *dataset_ids, + hid_t *memspace_id) +{ + char dset_name[DSET_NAME_LEN + 1]; + unsigned m = 0; + hid_t dcpl_id = H5I_INVALID_HID; + + LOGPRINT(2, "_create_chunking_ids()\n"); + + /* -------------------- + * Create chunking DCPL + */ + + dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + if (dcpl_id < 0) { + TEST_ERROR; + } + if (H5Pset_chunk(dcpl_id, 2, chunk_dims) == FAIL) { + TEST_ERROR; + } + + /* -------------------- + * Create dataspace IDs + */ + + for (m = min_dset; m <= max_dset; m++) { + dataspace_ids[m] = H5Screate_simple(2, dset_dims, NULL); + if (dataspace_ids[m] < 0) { + HDsnprintf(mesg, MIRR_MESG_SIZE, + "unable to create dataspace ID %d\n", m); + FAIL_PUTS_ERROR(mesg); + } + } + + /* -------------------- + * Create dataset IDs + */ + + for (m = min_dset; m <= max_dset; m++) { + if (HDsnprintf(dset_name, DSET_NAME_LEN, "/dset%03d", m) + > DSET_NAME_LEN) + { + HDsnprintf(mesg, MIRR_MESG_SIZE, + "unable to compose dset name %d\n", m); + FAIL_PUTS_ERROR(mesg); + } + + dataset_ids[m] = H5Dcreate(file_id, dset_name, H5T_STD_I32BE, + dataspace_ids[m], H5P_DEFAULT, dcpl_id, H5P_DEFAULT); + if (dataset_ids[m] < 0) { + HDsnprintf(mesg, MIRR_MESG_SIZE, + "unable to create dset ID %d\n", m); + FAIL_PUTS_ERROR(mesg); + } + } + + /* -------------------- + * Get file space IDs + */ + + for (m = min_dset; m <= max_dset; m++) { + filespace_ids[m] = H5Dget_space(dataset_ids[m]); + if (filespace_ids[m] < 0) { + HDsnprintf(mesg, MIRR_MESG_SIZE, + "unable to create filespace ID %d\n", m); + FAIL_PUTS_ERROR(mesg); + } + } + + /* -------------------- + * Create mem space to be used to read and write chunks + */ + + *memspace_id = H5Screate_simple(2, chunk_dims, NULL); + if (*memspace_id < 0) { + TEST_ERROR; + } + + /* -------------------- + * Clean up the DCPL, even if there were errors before + */ + + if (dcpl_id != H5P_DEFAULT && dcpl_id != H5I_INVALID_HID) { + if (H5Pclose(dcpl_id) == FAIL) { + TEST_ERROR; + } + } + + return SUCCEED; + +error: + if (dcpl_id != H5P_DEFAULT && dcpl_id != H5I_INVALID_HID) { + (void)H5Pclose(dcpl_id); + } + LOGPRINT(1, "_create_chunking_ids() FAILED\n"); + return FAIL; +} /* end _create_chunking_ids() */ + + +/* ---------------------------------------------------------------------------- + * Function: _open_chunking_ids + * + * Purpose: Open/access IDs from the given file. + * + * Return: SUCCEED/FAIL + * + * Programmer: Jacob Smith + * 2019 + * ---------------------------------------------------------------------------- + */ +static herr_t +_open_chunking_ids( + hid_t file_id, + unsigned min_dset, + unsigned max_dset, + hsize_t *chunk_dims, + hid_t *filespace_ids, + hid_t *dataset_ids, + hid_t *memspace_id) +{ + char dset_name[DSET_NAME_LEN+1]; + unsigned m = 0; + + LOGPRINT(2, "_open_chunking_ids()\n"); + + /* -------------------- + * Open dataset IDs + */ + + for (m = min_dset; m <= max_dset; m++) { + if (HDsnprintf(dset_name, DSET_NAME_LEN, "/dset%03d", m) + > DSET_NAME_LEN) + { + HDsnprintf(mesg, MIRR_MESG_SIZE, + "unable to compose dset name %d\n", m); + FAIL_PUTS_ERROR(mesg); + } + + dataset_ids[m] = H5Dopen2(file_id, dset_name, H5P_DEFAULT); + if (dataset_ids[m] < 0) { + HDsnprintf(mesg, MIRR_MESG_SIZE, "unable to open dset ID %d\n", m); + FAIL_PUTS_ERROR(mesg); + } + } + + /* -------------------- + * Open filespace IDs + */ + + for (m = min_dset; m <= max_dset; m++) { + filespace_ids[m] = H5Dget_space(dataset_ids[m]); + if (filespace_ids[m] < 0) { + HDsnprintf(mesg, MIRR_MESG_SIZE, + "unable to get filespace ID %d\n", m); + FAIL_PUTS_ERROR(mesg); + } + } + + /* -------------------- + * Create mem space to be used to read and write chunks + */ + + *memspace_id = H5Screate_simple(2, chunk_dims, NULL); + if (*memspace_id < 0) { + TEST_ERROR; + } + + return SUCCEED; + +error: + LOGPRINT(1, "_open_chunking_ids() FAILED\n"); + return FAIL; +} /* end _open_chunking_ids() */ + + +/* --------------------------------------------------------------------------- + * Function: _close_chunking_ids + * + * Purpose: Close IDs that were created or opened. + * Pass NULL into `dataspace_ids` when closing items opened with + * _open_chunking_ids(). (as opposed to created IDs) + * + * Return: SUCCEED/FAIL + * + * Programmer: Jacob Smith + * 2019 + * --------------------------------------------------------------------------- + */ +static herr_t +_close_chunking_ids(unsigned min_dset, + unsigned max_dset, + hid_t *dataspace_ids, + hid_t *filespace_ids, + hid_t *dataset_ids, + hid_t *memspace_id) +{ + unsigned m; + + LOGPRINT(2, "_close_chunking_ids()\n"); + + for (m = min_dset; m <= max_dset; m++) { + LOGPRINT(3, "closing ids[%d]\n", m); + if (dataspace_ids) { + if (H5Sclose(dataspace_ids[m]) < 0) { + HDsnprintf(mesg, MIRR_MESG_SIZE, + "unable to close dataspace_id[%d]\n", m); + FAIL_PUTS_ERROR(mesg); + } + } + if (H5Dclose(dataset_ids[m]) < 0) { + HDsnprintf(mesg, MIRR_MESG_SIZE, + "unable to close dataset_id[%d]\n", m); + FAIL_PUTS_ERROR(mesg); + } + if (H5Sclose(filespace_ids[m]) < 0) { + HDsnprintf(mesg, MIRR_MESG_SIZE, + "unable to close filespace_id[%d]\n", m); + FAIL_PUTS_ERROR(mesg); + } + } + + if ( (*memspace_id != H5I_INVALID_HID) && + (H5Sclose(*memspace_id) < 0) ) + { + TEST_ERROR; + } + + return SUCCEED; + +error: + LOGPRINT(1, "_close_chunking_ids() FAILED\n"); + return FAIL; +} /* end _close_chunking_ids() */ + + +/* --------------------------------------------------------------------------- + * Function: _verify_datasets + * + * Purpose: Check that each chunk's contents are as expected, as pertaining + * to create_datasets(). + * + * Return: SUCCEED/FAIL + * + * Programmer: Jacob Smith + * 2019 + * --------------------------------------------------------------------------- + */ +static herr_t +_verify_datasets(unsigned min_dset, + unsigned max_dset, + hid_t *filespace_ids, + hid_t *dataset_ids, + hid_t memspace_id) +{ + unsigned i, j, k, l, m; + int data_chunk[CHUNK_DIM][CHUNK_DIM]; + hsize_t offset[2]; + hsize_t a_size[2] = {CHUNK_DIM, CHUNK_DIM}; + + LOGPRINT(2, "_verify_datasets()\n"); + + for (i = 0; i < DSET_DIM; i += CHUNK_DIM) + { + LOGPRINT(3, "i: %d\n", i); + for (j = 0; j < DSET_DIM; j += CHUNK_DIM) + { + LOGPRINT(3, " j: %d\n", j); + for (m = min_dset; m <= max_dset; m++) + { + LOGPRINT(3, " m: %d\n", m); + + /* select on disk hyperslab */ + offset[0] = (hsize_t)i; + offset[1] = (hsize_t)j; + if (H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET, + offset, NULL, a_size, NULL) + < 0) + { + TEST_ERROR; + } + + if (H5Dread(dataset_ids[m], H5T_NATIVE_INT, memspace_id, + filespace_ids[m], H5P_DEFAULT, data_chunk) + < 0) + { + HDsnprintf(mesg, MIRR_MESG_SIZE, + " H5Dread() [%d][%d][%d]\n", + i, j, m); + FAIL_PUTS_ERROR(mesg); + } + + for (k = 0; k < CHUNK_DIM; k++) { + for (l = 0; l < CHUNK_DIM; l++) { + if ((unsigned)data_chunk[k][l] + != + ((DSET_DIM * DSET_DIM * m) + + (DSET_DIM * (i + k)) + j + l)) + { + HDsnprintf(mesg, MIRR_MESG_SIZE, + " MISMATCH [%d][%d][%d][%d][%d]\n", + i, j, m, k, l); + FAIL_PUTS_ERROR(mesg); + } + } + } + + } + } + } + + return SUCCEED; + +error: + LOGPRINT(1, "_verify_datasets() FAILED\n"); + return FAIL; +} /* end _verify_datasets() */ + + +/* --------------------------------------------------------------------------- + * Function: verify_datasets + * + * Purpose: Inspect the datasets in the file created by create_datasets(). + * Wrapper for _verify_datasets() -- this function sets up and + * tears down accessor information. + * + * Return: SUCCEED/FAIL + * + * Programmer: Jacob Smith + * 2019 + * --------------------------------------------------------------------------- + */ +static herr_t +verify_datasets(hid_t file_id, + unsigned min_dset, + unsigned max_dset) +{ + hid_t dataset_ids[MAX_DSET_COUNT + 1]; + hid_t filespace_ids[MAX_DSET_COUNT + 1]; + unsigned i; + hid_t memspace_id = H5I_INVALID_HID; + hsize_t chunk_dims[2] = {CHUNK_DIM, CHUNK_DIM}; + + HDassert(file_id >= 0); + HDassert(min_dset <= max_dset); + HDassert(max_dset <= MAX_DSET_COUNT); + + LOGPRINT(2, "verify_datasets()\n"); + + /* --------------------------------- + * "Clear" ID arrays + */ + + for (i = 0; i < MAX_DSET_COUNT; i++) { + LOGPRINT(3, "clearing IDs [%d]\n", i); + dataset_ids[i] = H5I_INVALID_HID; + filespace_ids[i] = H5I_INVALID_HID; + } + + /* --------------------------------- + * Generate dataspace, dataset, and 'filespace' IDs + */ + + if (_open_chunking_ids(file_id, min_dset, max_dset, chunk_dims, + filespace_ids, dataset_ids, &memspace_id) + == FAIL) + { + TEST_ERROR; + } + + /* --------------------------------- + * Read and verify data from datasets + */ + + if (_verify_datasets(min_dset, max_dset, filespace_ids, dataset_ids, + memspace_id) + == FAIL) + { + TEST_ERROR; + } + + /* --------------------------------- + * Cleanup + */ + + if (_close_chunking_ids(min_dset, max_dset, NULL, filespace_ids, + dataset_ids, &memspace_id) + == FAIL) + { + TEST_ERROR; + } + + return SUCCEED; + +error: + LOGPRINT(1, "verify_datasets() FAILED\n"); + (void)_close_chunking_ids(min_dset, max_dset, NULL, filespace_ids, + dataset_ids, &memspace_id); + return FAIL; + +} /* end verify_datasets() */ + + +/* --------------------------------------------------------------------------- + * Function: test_basic_dataset_write + * + * Purpose: Create and close files; repoen files and write a dataset, + * close; compare files. + * + * TODO: receive target IP from caller? + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Jacob Smith + * 2019 + * --------------------------------------------------------------------------- + */ +static int +test_basic_dataset_write(void) +{ + struct mirrortest_filenames names; + hid_t file_id = H5I_INVALID_HID; + hid_t fapl_id = H5P_DEFAULT; + hid_t dset_id = H5I_INVALID_HID; + hid_t dspace_id = H5I_INVALID_HID; + hid_t dtype_id = H5T_NATIVE_INT; + hsize_t dims[2] = { DATABUFFER_SIZE, DATABUFFER_SIZE }; + int *buf = NULL; + int i = 0; + int j = 0; + + TESTING("Mirror open and dataset writing"); + + /* Create FAPL for Splitter[sec2|mirror] + */ + fapl_id = create_mirroring_split_fapl("basic_write", &names); + if (H5I_INVALID_HID == fapl_id) { + TEST_ERROR; + } + + /* Prepare data to be written + */ + buf = (int *)HDmalloc(DATABUFFER_SIZE * DATABUFFER_SIZE * sizeof(int)); + if (NULL == buf) { + TEST_ERROR; + } + for (i = 0; i < DATABUFFER_SIZE; i++) { + for (j = 0; j < DATABUFFER_SIZE; j++) { + int k = i * DATABUFFER_SIZE + j; + buf[k] = k; + } + } + + /* -------------------- */ + /* TEST: Create and Close */ + + file_id = H5Fcreate(names.rw, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + if (H5I_INVALID_HID == file_id) { + TEST_ERROR; + } + if (H5Fclose(file_id) == FAIL) { + TEST_ERROR; + } + file_id = H5I_INVALID_HID; + + + /* -------------------- */ + /* TEST: Repoen and Write */ + + file_id = H5Fopen(names.rw, H5F_ACC_RDWR, fapl_id); + if (H5I_INVALID_HID == file_id) { + TEST_ERROR; + } + + dspace_id = H5Screate_simple(2, dims, NULL); + if (H5I_INVALID_HID == dspace_id) { + TEST_ERROR; + } + dset_id = H5Dcreate2(file_id, "dataset", dtype_id, dspace_id, H5P_DEFAULT, + H5P_DEFAULT, H5P_DEFAULT); + if (H5I_INVALID_HID == dset_id) { + TEST_ERROR; + } + + if (H5Dwrite(dset_id, dtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) + == FAIL) + { + TEST_ERROR; + } + + /* -------------------- */ + /* Standard cleanup */ + + HDfree(buf); + buf = NULL; + if (H5Dclose(dset_id) == FAIL) { + TEST_ERROR; + } + if (H5Sclose(dspace_id) == FAIL) { + TEST_ERROR; + } + if (H5Fclose(file_id) == FAIL) { + TEST_ERROR; + } + if (fapl_id != H5P_DEFAULT && fapl_id > 0) { + if (H5Pclose(fapl_id) == FAIL) { + TEST_ERROR; + } + } + + /* -------------------- */ + /* TEST: Verify that the R/W and W/O files are identical */ + + if (h5_compare_file_bytes(names.rw, names.wo) < 0) { + TEST_ERROR; + } + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY{ + (void)H5Fclose(file_id); + if (buf) { + HDfree(buf); + } + (void)H5Dclose(dset_id); + (void)H5Sclose(dspace_id); + if (fapl_id != H5P_DEFAULT && fapl_id > 0) { + (void)H5Pclose(fapl_id); + } + } H5E_END_TRY; + return -1; +} /* end test_basic_dataset_write() */ + + +/* --------------------------------------------------------------------------- + * Function: test_chunked_dataset_write + * + * Purpose: Create and close files; repoen files and write a dataset, + * close; compare files. + * + * TODO: receive target IP from caller? + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Jacob Smith + * 2019 + * --------------------------------------------------------------------------- + */ +static int +test_chunked_dataset_write(void) +{ + struct mirrortest_filenames names; + hid_t file_id = H5I_INVALID_HID; + hid_t fapl_id = H5P_DEFAULT; + + TESTING("Mirror open and dataset writing (chunked)"); + + /* Create FAPL for Splitter[sec2|mirror] + */ + fapl_id = create_mirroring_split_fapl("chunked_write", &names); + if (H5I_INVALID_HID == fapl_id) { + TEST_ERROR; + } + + /* -------------------- */ + /* TEST: Create and Close */ + + file_id = H5Fcreate(names.rw, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + if (H5I_INVALID_HID == file_id) { + TEST_ERROR; + } + if (H5Fclose(file_id) == FAIL) { + TEST_ERROR; + } + file_id = H5I_INVALID_HID; + + /* -------------------- */ + /* TEST: Reopen and Write */ + + file_id = H5Fopen(names.rw, H5F_ACC_RDWR, fapl_id); + if (H5I_INVALID_HID == file_id) { + TEST_ERROR; + } + + /* Write datasets to file + */ + if (create_datasets(file_id, 0, MAX_DSET_COUNT) == FAIL) { + TEST_ERROR; + } + + /* Close to 'flush to disk', and reopen file + */ + if (H5Fclose(file_id) == FAIL) { + TEST_ERROR; + } + file_id = H5I_INVALID_HID; + + /* Reopen file + */ + file_id = H5Fopen(names.rw, H5F_ACC_RDWR, fapl_id); + if (H5I_INVALID_HID == file_id) { + TEST_ERROR; + } + + /* Verify written data integrity + */ + if (verify_datasets(file_id, 0, MAX_DSET_COUNT) == FAIL) { + TEST_ERROR; + } + + /* -------------------- */ + /* Standard cleanup */ + + if (H5Fclose(file_id) == FAIL) { + TEST_ERROR; + } + file_id = H5I_INVALID_HID; + if (fapl_id != H5P_DEFAULT && fapl_id > 0) { + if (H5Pclose(fapl_id) == FAIL) { + TEST_ERROR; + } + fapl_id = H5I_INVALID_HID; + } + + /* -------------------- */ + /* TEST: Verify that the R/W and W/O files are identical */ + + if (h5_compare_file_bytes(names.rw, names.wo) < 0) { + TEST_ERROR; + } + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + (void)H5Fclose(file_id); + if (fapl_id != H5P_DEFAULT && fapl_id > 0) { + (void)H5Pclose(fapl_id); + } + } H5E_END_TRY; + return -1; +} /* end test_chunked_dataset_write() */ + + +/* --------------------------------------------------------------------------- + * Function: test_on_disk_zoo + * + * Purpose: Verify that the mirror can handle the passing of all the + * various on-disk data structures over the wire, as implemented + * in genall5.c:create_zoo(). + * + * TODO: receive target IP from caller? + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Jacob Smith + * 2019 + * --------------------------------------------------------------------------- + */ +static int +test_on_disk_zoo(void) +{ + const char grp_name[] = "/only"; + struct mirrortest_filenames names; + hid_t file_id = H5I_INVALID_HID; + hid_t grp_id = H5I_INVALID_HID; + hid_t fapl_id = H5P_DEFAULT; + + TESTING("'Zoo' of on-disk structures"); + + /* Create FAPL for Splitter[sec2|mirror] + */ + fapl_id = create_mirroring_split_fapl("zoo", &names); + if (H5I_INVALID_HID == fapl_id) { + TEST_ERROR; + } + + /* -------------------- */ + /* TEST: Create file */ + file_id = H5Fcreate(names.rw, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + if (H5I_INVALID_HID == file_id) { + TEST_ERROR; + } + + grp_id = H5Gcreate2(file_id, grp_name, H5P_DEFAULT, H5P_DEFAULT, + H5P_DEFAULT); + if (grp_id == H5I_INVALID_HID) { + TEST_ERROR; + } + + /* Create datasets in file, close (flush) and reopen, validate. + * Use of ( pass ) a conceit required for using create_ and validate_zoo() + * from cache_common and/or genall5. + */ + + if ( pass ) { + create_zoo(file_id, grp_name, 0); + } + if ( pass ) { + if (H5Fclose(file_id) == FAIL) { + TEST_ERROR; + } + file_id = H5Fopen(names.rw, H5F_ACC_RDWR, fapl_id); + if (H5I_INVALID_HID == file_id) { + TEST_ERROR; + } + } + if ( pass ) { + validate_zoo(file_id, grp_name, 0); /* sanity-check */ + } + if ( !pass ) { + HDprintf(failure_mssg); + TEST_ERROR; + } + + /* -------------------- */ + /* Standard cleanup */ + + if (fapl_id != H5P_DEFAULT && fapl_id >= 0) { + if (H5Pclose(fapl_id) == FAIL) { + TEST_ERROR; + } + } + if (H5Gclose(grp_id) == FAIL) { + TEST_ERROR; + } + if (H5Fclose(file_id) == FAIL) { + TEST_ERROR; + } + + /* -------------------- */ + /* TEST: Verify that the R/W and W/O files are identical */ + + if (h5_compare_file_bytes(names.rw, names.wo) < 0) { + TEST_ERROR; + } + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + (void)H5Fclose(file_id); + (void)H5Gclose(grp_id); + if (fapl_id != H5P_DEFAULT && fapl_id > 0) { + (void)H5Pclose(fapl_id); + } + } H5E_END_TRY; + return -1; +} /* end test_on_disk_zoo() */ + + +/* --------------------------------------------------------------------------- + * Function: test_vanishing_datasets + * + * Purpose: Verify behavior when writing to a file where data is deleted. + * + * Each dataset is populated with the value of its suffix + * (dset5 is all fives). + * + * Opens 0..15 create one new dataset each, '/dset[i]'. + * Opens 3..18 delete '/dset[1-3]' + * + * Should end with no data in file. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Jacob Smith + * 2019 + * --------------------------------------------------------------------------- + */ +static int +test_vanishing_datasets(void) +{ + struct mirrortest_filenames names; + hid_t file_id = H5I_INVALID_HID; + hid_t fapl_id = H5I_INVALID_HID; + hid_t dset_id = H5I_INVALID_HID; + hid_t dspace_id = H5I_INVALID_HID; + hid_t mirror_fapl_id = H5I_INVALID_HID; + hsize_t dims[2] = {DATABUFFER_SIZE, DATABUFFER_SIZE}; + uint32_t buf[DATABUFFER_SIZE][DATABUFFER_SIZE]; /* consider malloc? */ + H5G_info_t group_info; + unsigned int i, j, k; + const unsigned int max_loops = 20; + const unsigned int max_at_one_time = 3; + + TESTING("Vanishing Datasets"); + + /* -------------------- */ + /* Set up recurrent data (FAPL, dataspace) */ + + /* Create FAPL for Splitter[sec2|mirror] + */ + fapl_id = create_mirroring_split_fapl("vanishing", &names); + if (H5I_INVALID_HID == fapl_id) { + TEST_ERROR; + } + + dspace_id = H5Screate_simple(2, dims, NULL); + if (dspace_id < 0) { + TEST_ERROR; + } + + /* create file */ + file_id = H5Fcreate(names.rw, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + if (H5I_INVALID_HID == file_id) { + TEST_ERROR; + } + + for (i=0; i < max_loops; i++) { + char namebuf[DSET_NAME_LEN + 1]; + + /* deleting datasets */ + if (i >= max_at_one_time) { + if (HDsnprintf(namebuf, DSET_NAME_LEN, "/dset%02d", + (i - max_at_one_time) ) + > DSET_NAME_LEN) + { + TEST_ERROR; + } + if (H5Ldelete(file_id, namebuf, H5P_DEFAULT) < 0) { + TEST_ERROR; + } + } /* end if deleting a dataset */ + + /* writing datasets */ + if (i < (max_loops - max_at_one_time)) { + if (HDsnprintf(namebuf, DSET_NAME_LEN, "/dset%02d", i) + > DSET_NAME_LEN) + { + TEST_ERROR; + } + dset_id = H5Dcreate2(file_id, namebuf, H5T_STD_U32LE, dspace_id, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (H5I_INVALID_HID == dset_id) { + TEST_ERROR; + } + + for (j=0; j < DATABUFFER_SIZE; j++) { + for (k=0; k < DATABUFFER_SIZE; k++) { + buf[j][k] = (uint32_t)i; + } + } + + if (H5Dwrite(dset_id, H5T_STD_U32LE, H5S_ALL, H5S_ALL, H5P_DEFAULT, + buf) + < 0) + { + TEST_ERROR; + } + + if (H5Dclose(dset_id) < 0) { + TEST_ERROR; + } + dset_id = H5I_INVALID_HID; + } /* end if writing a dataset */ + + } /* end for dataset create-destroy cycles */ + + if (H5Fclose(file_id) < 0) { + TEST_ERROR; + } + file_id = H5I_INVALID_HID; + + /* verify there are no datasets in file */ + file_id = H5Fopen(names.rw, H5F_ACC_RDONLY, H5P_DEFAULT); + if (file_id < 0) { + TEST_ERROR; + } + if (H5Gget_info(file_id, &group_info) < 0) { + TEST_ERROR; + } + if (group_info.nlinks > 0) { + HDfprintf(stderr, "links in rw file: %d\n", group_info.nlinks); + HDfflush(stderr); + TEST_ERROR; + } + if (H5Fclose(file_id) < 0) { + TEST_ERROR; + } + file_id = H5Fopen(names.wo, H5F_ACC_RDONLY, H5P_DEFAULT); + if (file_id < 0) { + TEST_ERROR; + } + if (H5Gget_info(file_id, &group_info) < 0) { + TEST_ERROR; + } + if (group_info.nlinks > 0) { + HDfprintf(stderr, "links in wo file: %d\n", group_info.nlinks); + HDfflush(stderr); + TEST_ERROR; + } + if (H5Fclose(file_id) < 0) { + TEST_ERROR; + } + file_id = H5I_INVALID_HID; + + if (h5_compare_file_bytes(names.rw, names.wo) < 0) + TEST_ERROR; + + /* -------------------- */ + /* Teardown */ + + if (H5Sclose(dspace_id) < 0) { + TEST_ERROR; + } + if (H5Pclose(fapl_id) < 0) { + TEST_ERROR; + } + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + if (mirror_fapl_id != H5I_INVALID_HID) { + H5Pclose(mirror_fapl_id); + } + if (fapl_id != H5I_INVALID_HID) { + H5Pclose(fapl_id); + } + if (file_id != H5I_INVALID_HID) { + H5Fclose(file_id); + } + if (dset_id != H5I_INVALID_HID) { + H5Dclose(dset_id); + } + if (dspace_id != H5I_INVALID_HID) { + H5Sclose(dspace_id); + } + } H5E_END_TRY; + return -1; +} /* test_vanishing_datasets() */ + + +/* --------------------------------------------------------------------------- + * Function: test_concurrent_access + * + * Purpose: Verify that more than one file may be opened at a time. + * + * TODO: receive target IP from caller? + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Jacob Smith + * 2020-03-09 + * --------------------------------------------------------------------------- + */ +static int +test_concurrent_access(void) +{ + struct file_bundle { + struct mirrortest_filenames names; + hid_t dset_id; + hid_t fapl_id; + hid_t file_id; + } bundle[CONCURRENT_COUNT]; + hid_t dspace_id = H5I_INVALID_HID; + hid_t dtype_id = H5T_NATIVE_INT; + hsize_t dims[2] = { DATABUFFER_SIZE, DATABUFFER_SIZE }; + int *buf = NULL; + int i = 0; + int j = 0; + + TESTING("Concurrent opened mirrored files"); + + /* blank bundle */ + for (i = 0; i < CONCURRENT_COUNT; i++) { + bundle[i].dset_id = H5I_INVALID_HID; + bundle[i].fapl_id = H5I_INVALID_HID; + bundle[i].file_id = H5I_INVALID_HID; + *bundle[i].names.rw = '\0'; + *bundle[i].names.wo = '\0'; + *bundle[i].names.log = '\0'; + } + + /* Create FAPL for Splitter[sec2|mirror] + */ + for (i = 0; i < CONCURRENT_COUNT; i++) { + char _name[16] = ""; + hid_t _fapl_id = H5I_INVALID_HID; + HDsnprintf(_name, 15, "concurrent%d", i); + _fapl_id = create_mirroring_split_fapl(_name, &bundle[i].names); + if (H5I_INVALID_HID == _fapl_id) { + TEST_ERROR; + } + bundle[i].fapl_id = _fapl_id; + } + + /* Prepare data to be written + */ + buf = (int *)HDmalloc(DATABUFFER_SIZE * DATABUFFER_SIZE * sizeof(int)); + if (NULL == buf) { + TEST_ERROR; + } + for (i = 0; i < DATABUFFER_SIZE; i++) { + for (j = 0; j < DATABUFFER_SIZE; j++) { + int k = i * DATABUFFER_SIZE + j; + buf[k] = k; + } + } + + /* Prepare generic dataspace + */ + dspace_id = H5Screate_simple(2, dims, NULL); + if (H5I_INVALID_HID == dspace_id) { + TEST_ERROR; + } + + /* -------------------- */ + /* TEST: Create file and open elements */ + + for (i = 0; i < CONCURRENT_COUNT; i++) { + hid_t _file_id = H5I_INVALID_HID; + hid_t _dset_id = H5I_INVALID_HID; + + _file_id = H5Fcreate(bundle[i].names.rw, H5F_ACC_TRUNC, H5P_DEFAULT, + bundle[i].fapl_id); + if (H5I_INVALID_HID == _file_id) { + TEST_ERROR; + } + + bundle[i].file_id = _file_id; + + _dset_id = H5Dcreate2(_file_id, "dataset", dtype_id, dspace_id, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (H5I_INVALID_HID == _dset_id) { + TEST_ERROR; + } + bundle[i].dset_id = _dset_id; + } + + /* -------------------- */ + /* TEST: Write to files */ + + for (i = 0; i < CONCURRENT_COUNT; i++) { + if (H5Dwrite(bundle[i].dset_id, dtype_id, H5S_ALL, H5S_ALL, + H5P_DEFAULT, buf) + == FAIL) + { + TEST_ERROR; + } + } + + /* -------------------- */ + /* TEST: Close elements */ + + for (i = 0; i < CONCURRENT_COUNT; i++) { + if (H5Dclose(bundle[i].dset_id) == FAIL) { + TEST_ERROR; + } + if (H5Fclose(bundle[i].file_id) == FAIL) { + TEST_ERROR; + } + if (H5Pclose(bundle[i].fapl_id) == FAIL) { + TEST_ERROR; + } + } + + /* -------------------- */ + /* Standard cleanup */ + + HDfree(buf); + buf = NULL; + if (H5Sclose(dspace_id) == FAIL) { + TEST_ERROR; + } + + /* -------------------- */ + /* TEST: Verify that the R/W and W/O files are identical */ + + for (i = 0; i < CONCURRENT_COUNT; i++) { + if (h5_compare_file_bytes(bundle[i].names.rw, bundle[i].names.wo) < 0) { + TEST_ERROR; + } + } + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY{ + if (buf) { + HDfree(buf); + } + (void)H5Sclose(dspace_id); + for (i = 0; i < CONCURRENT_COUNT; i++) { + (void)H5Dclose(bundle[i].dset_id); + (void)H5Fclose(bundle[i].file_id); + (void)H5Pclose(bundle[i].fapl_id); + } + } H5E_END_TRY; + return -1; +} /* end test_concurrent_access() */ + + +/* --------------------------------------------------------------------------- + * Function: main + * + * Purpose: Run tests. + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: Jacob Smith + * 2019 + * --------------------------------------------------------------------------- + */ +int +main(void) +{ + int nerrors = 0; + + h5_reset(); + + g_log_stream = stdout; /* default debug/logging output stream */ + + HDprintf("Testing Mirror VFD functionality.\n"); + + /* -------------------- */ + /* SETUP */ + + /* Create directories for test-generated .h5 files + */ + if (nerrors == 0) { + if ((HDmkdir(MIRROR_RW_DIR, (mode_t)0755) < 0) && (errno != EEXIST)) { + nerrors++; + } + } + if (nerrors == 0) { + if ((HDmkdir(MIRROR_WO_DIR, (mode_t)0755) < 0) && (errno != EEXIST)) { + nerrors++; + } + } + + /* -------------------- */ + /* TESTS */ + /* Tests return negative values; `-=' increments nerrors count */ + + if (nerrors == 0) { + nerrors -= test_fapl_configuration(); + nerrors -= test_xmit_encode_decode(); + nerrors -= test_create_and_close(); + nerrors -= test_basic_dataset_write(); + nerrors -= test_chunked_dataset_write(); + nerrors -= test_on_disk_zoo(); + nerrors -= test_vanishing_datasets(); + nerrors -= test_concurrent_access(); + } + + if (nerrors) { + HDprintf("***** %d Mirror VFD TEST%s FAILED! *****\n", + nerrors, nerrors > 1 ? "S" : ""); + return EXIT_FAILURE; + } + + HDprintf("All Mirror Virtual File Driver tests passed.\n"); + return EXIT_SUCCESS; +} /* end main() */ + +#else /* H5_HAVE_MIRROR_VFD */ + +int +main(void) +{ + h5_reset(); + HDprintf("Testing Mirror VFD functionality.\n"); + HDprintf("SKIPPED - Mirror VFD not built.\n"); + return EXIT_SUCCESS; +} + +#endif /* H5_HAVE_MIRROR_VFD */ + + diff --git a/test/mount.c b/test/mount.c index 181b8cb..2af1483 100644 --- a/test/mount.c +++ b/test/mount.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Wednesday, October 7, 1998 * * Purpose: Tests file mounting. diff --git a/test/mtime.c b/test/mtime.c index 06f576b..04e302e 100644 --- a/test/mtime.c +++ b/test/mtime.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Thursday, July 30, 1998 * * Purpose: Determines if the modification time message is working diff --git a/test/ntypes.c b/test/ntypes.c index d3d10eb..f1260ad 100644 --- a/test/ntypes.c +++ b/test/ntypes.c @@ -2675,7 +2675,7 @@ error: * Return: Success: 0 * Failure: -1 * - * Programmer: pvn@ncsa.uiuc.edu + * Programmer: Pedro Vicente * September 3, 2004 * * Modifications: diff --git a/test/ohdr.c b/test/ohdr.c index 8deec10..36a7742 100644 --- a/test/ohdr.c +++ b/test/ohdr.c @@ -11,7 +11,7 @@ * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: Robb Matzke <matzke@llnl.gov> +/* Programmer: Robb Matzke * Tuesday, November 24, 1998 */ #include "h5test.h" diff --git a/test/pool.c b/test/pool.c index 1851d6e..59f9201 100644 --- a/test/pool.c +++ b/test/pool.c @@ -11,7 +11,7 @@ * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> +/* Programmer: Quincey Koziol * Tuesday, May 3, 2005 */ #include "h5test.h" @@ -636,10 +636,10 @@ test_allocate_random(void) /* Initialize random number seed */ curr_time = HDtime(NULL); -#ifdef QAK +#if 0 curr_time=1115412944; HDfprintf(stderr,"curr_time=%lu\n",(unsigned long)curr_time); -#endif /* QAK */ +#endif HDsrandom((unsigned)curr_time); /* Create a memory pool */ diff --git a/test/space_overflow.c b/test/space_overflow.c index 15be9ba..82ddb3b 100644 --- a/test/space_overflow.c +++ b/test/space_overflow.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Monday, October 26, 1998 * * Purpose: Create a dataset with a simple data space that has the diff --git a/test/stab.c b/test/stab.c index 9afe28e..c3f8dbf 100644 --- a/test/stab.c +++ b/test/stab.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Tuesday, November 24, 1998 */ @@ -171,7 +171,7 @@ test_misc(hid_t fcpl, hid_t fapl, hbool_t new_format) * * Failure: number of errors * - * Programmer: Robb Matzke <matzke@llnl.gov> 2002-03-28 + * Programmer: Robb Matzke 2002-03-28 * * Modifications: *------------------------------------------------------------------------- diff --git a/test/swmr.c b/test/swmr.c index 700a68c..dde6eac 100644 --- a/test/swmr.c +++ b/test/swmr.c @@ -90,7 +90,7 @@ static int test_file_lock_concur(hid_t fapl); static int test_file_lock_swmr_concur(hid_t fapl); /* Test file lock environment variable */ -static int test_file_lock_env_var(hid_t fapl); +static int test_file_locking(hid_t in_fapl, hbool_t turn_locking_on, hbool_t env_var_override); /* Tests for SWMR VFD flag */ static int test_swmr_vfd_flag(void); @@ -4255,8 +4255,11 @@ test_file_lock_same(hid_t in_fapl) /* Output message about test being performed */ TESTING("File open with different combinations of flags--single process access"); + /* Set locking in the fapl */ if((fapl = H5Pcopy(in_fapl)) < 0) FAIL_STACK_ERROR + if(H5Pset_file_locking(fapl, TRUE, TRUE) < 0) + FAIL_STACK_ERROR /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[1], fapl, filename, sizeof(filename)); @@ -4415,9 +4418,11 @@ test_file_lock_swmr_same(hid_t in_fapl) /* Output message about test being performed */ TESTING("File open with different combinations of flags + SWMR flags--single process access"); - /* Get a copy of the parameter in_fapl */ + /* Set locking in the fapl */ if((fapl = H5Pcopy(in_fapl)) < 0) FAIL_STACK_ERROR + if(H5Pset_file_locking(fapl, TRUE, TRUE) < 0) + FAIL_STACK_ERROR /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[1], fapl, filename, sizeof(filename)); @@ -4725,8 +4730,11 @@ test_file_lock_concur(hid_t in_fapl) /* Output message about test being performed */ TESTING("File open with different combinations of flags--concurrent access"); + /* Set locking in the fapl */ if((fapl = H5Pcopy(in_fapl)) < 0) FAIL_STACK_ERROR + if(H5Pset_file_locking(fapl, TRUE, TRUE) < 0) + FAIL_STACK_ERROR /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[1], fapl, filename, sizeof(filename)); @@ -5101,8 +5109,11 @@ test_file_lock_swmr_concur(hid_t in_fapl) /* Output message about test being performed */ TESTING("File open with different combintations of flags + SWMR flags--concurrent access"); + /* Set locking in the fapl */ if((fapl = H5Pcopy(in_fapl)) < 0) FAIL_STACK_ERROR + if(H5Pset_file_locking(fapl, TRUE, TRUE) < 0) + FAIL_STACK_ERROR /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[2], fapl, filename, sizeof(filename)); @@ -5133,7 +5144,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) @@ -5154,7 +5165,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(child_fid == FAIL) HDexit(EXIT_SUCCESS); - /* Close the pipe */ + /* Close the pipe */ if(HDclose(out_pdf[0]) < 0) HDexit(EXIT_FAILURE); @@ -5204,13 +5215,13 @@ test_file_lock_swmr_concur(hid_t in_fapl) /* Fork child process */ if((childpid = HDfork()) < 0) - FAIL_STACK_ERROR + FAIL_STACK_ERROR if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; - /* Close unused write end for out_pdf */ + /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) HDexit(EXIT_FAILURE); @@ -5229,7 +5240,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(child_fid == FAIL) HDexit(EXIT_SUCCESS); - /* Close the pipe */ + /* Close the pipe */ if(HDclose(out_pdf[0]) < 0) HDexit(EXIT_FAILURE); @@ -5242,7 +5253,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) /* Open the test file */ if((fid = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) - FAIL_STACK_ERROR + FAIL_STACK_ERROR /* Notify child process */ notify = 1; @@ -5255,7 +5266,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) /* Wait for child process to complete */ if(HDwaitpid(childpid, &child_status, child_wait_option) < 0) - FAIL_STACK_ERROR + FAIL_STACK_ERROR /* Check if child terminated normally */ if(WIFEXITED(child_status)) { @@ -5283,7 +5294,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) @@ -5304,7 +5315,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(child_fid == FAIL) HDexit(EXIT_SUCCESS); - /* Close the pipe */ + /* Close the pipe */ if(HDclose(out_pdf[0]) < 0) HDexit(EXIT_FAILURE); @@ -5353,11 +5364,11 @@ test_file_lock_swmr_concur(hid_t in_fapl) /* Fork child process */ if((childpid = HDfork()) < 0) - FAIL_STACK_ERROR + FAIL_STACK_ERROR if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) @@ -5378,7 +5389,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(child_fid == FAIL) HDexit(EXIT_SUCCESS); - /* Close the pipe */ + /* Close the pipe */ if(HDclose(out_pdf[0]) < 0) HDexit(EXIT_FAILURE); @@ -5391,7 +5402,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) /* Open the test file */ if((fid = H5Fopen(filename, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl)) < 0) - FAIL_STACK_ERROR + FAIL_STACK_ERROR /* Notify child process */ notify = 1; @@ -5404,7 +5415,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) /* Wait for child process to complete */ if(HDwaitpid(childpid, &child_status, child_wait_option) < 0) - FAIL_STACK_ERROR + FAIL_STACK_ERROR /* Check if child terminated normally */ if(WIFEXITED(child_status)) { @@ -5427,11 +5438,11 @@ test_file_lock_swmr_concur(hid_t in_fapl) /* Fork child process */ if((childpid = HDfork()) < 0) - FAIL_STACK_ERROR + FAIL_STACK_ERROR if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) @@ -5455,7 +5466,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) HDexit(EXIT_SUCCESS); } - /* Close the pipe */ + /* Close the pipe */ if(HDclose(out_pdf[0]) < 0) HDexit(EXIT_FAILURE); @@ -5468,7 +5479,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) /* Open the test file */ if((fid = H5Fopen(filename, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl)) < 0) - FAIL_STACK_ERROR + FAIL_STACK_ERROR /* Notify child process */ notify = 1; @@ -5481,7 +5492,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) /* Wait for child process to complete */ if(HDwaitpid(childpid, &child_status, child_wait_option) < 0) - FAIL_STACK_ERROR + FAIL_STACK_ERROR /* Check if child terminated normally */ if(WIFEXITED(child_status)) { @@ -5508,7 +5519,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) @@ -5529,7 +5540,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(child_fid == FAIL) HDexit(EXIT_SUCCESS); - /* Close the pipe */ + /* Close the pipe */ if(HDclose(out_pdf[0]) < 0) HDexit(EXIT_FAILURE); @@ -5583,7 +5594,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) @@ -5597,14 +5608,14 @@ test_file_lock_swmr_concur(hid_t in_fapl) /* Open the test file */ H5E_BEGIN_TRY { - child_fid = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT); + child_fid = H5Fopen(filename, H5F_ACC_RDWR, fapl); } H5E_END_TRY; /* Should fail */ if(child_fid == FAIL) HDexit(EXIT_SUCCESS); - /* Close the pipe */ + /* Close the pipe */ if(HDclose(out_pdf[0]) < 0) HDexit(EXIT_FAILURE); @@ -5658,7 +5669,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) @@ -5733,7 +5744,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) @@ -5811,7 +5822,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) @@ -5834,7 +5845,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) HDexit(EXIT_SUCCESS); } - /* Close the pipe */ + /* Close the pipe */ if(HDclose(out_pdf[0]) < 0) HDexit(EXIT_FAILURE); @@ -5888,7 +5899,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) @@ -5909,7 +5920,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(child_fid == FAIL) HDexit(EXIT_SUCCESS); - /* Close the pipe */ + /* Close the pipe */ if(HDclose(out_pdf[0]) < 0) HDexit(EXIT_FAILURE); @@ -5921,7 +5932,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) FAIL_STACK_ERROR /* Open the test file */ - if((fid = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + if((fid = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) FAIL_STACK_ERROR /* Notify child process */ @@ -5963,7 +5974,7 @@ test_file_lock_swmr_concur(hid_t in_fapl) if(childpid == 0) { /* Child process */ hid_t child_fid; /* File ID */ - int child_notify = 0; + int child_notify = 0; /* Close unused write end for out_pdf */ if(HDclose(out_pdf[1]) < 0) @@ -6058,7 +6069,7 @@ error: ** *****************************************************************/ static int -test_file_lock_env_var(hid_t in_fapl) +test_file_locking(hid_t in_fapl, hbool_t turn_locking_on, hbool_t env_var_override) { #if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID)) SKIPPED(); @@ -6073,18 +6084,40 @@ test_file_lock_env_var(hid_t in_fapl) int child_wait_option=0; /* Options passed to waitpid */ int out_pdf[2]; int notify = 0; + int exit_status = 0; + herr_t ret; + + if (turn_locking_on && env_var_override) + TESTING("File locking: ON w/ env var override") + else if (turn_locking_on && !env_var_override) + TESTING("File locking: ON") + else if (!turn_locking_on && env_var_override) + TESTING("File locking: OFF w/ env var override") + else + TESTING("File locking: OFF") - - TESTING("File locking environment variable"); - - - /* Set the environment variable */ - if(HDsetenv("HDF5_USE_FILE_LOCKING", "FALSE", TRUE) < 0) + /* Copy the incoming fapl */ + if((fapl = H5Pcopy(in_fapl)) < 0) TEST_ERROR - if((fapl = H5Pcopy(in_fapl)) < 0) + /* Set locking in the fapl */ + if(H5Pset_file_locking(fapl, turn_locking_on ? TRUE : FALSE, TRUE) < 0) TEST_ERROR + /* If requested, set the environment variable */ + if (env_var_override) { + if(HDsetenv("HDF5_USE_FILE_LOCKING", turn_locking_on ? "FALSE" : "TRUE", TRUE) < 0) + TEST_ERROR + if(H5F__reparse_file_lock_variable_test() < 0) + TEST_ERROR + } + else { + if(HDsetenv("HDF5_USE_FILE_LOCKING", "", TRUE) < 0) + TEST_ERROR + if(H5F__reparse_file_lock_variable_test() < 0) + TEST_ERROR + } + /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[1], fapl, filename, sizeof(filename)); @@ -6096,10 +6129,8 @@ test_file_lock_env_var(hid_t in_fapl) if(H5Fclose(fid) < 0) TEST_ERROR - /* Open a file for read-only and then read-write. This would - * normally fail due to the file locking scheme but should - * pass when the environment variable is set to disable file - * locking. + /* Open a file for read-only and then read-write. This will fail + * when the locking scheme is turned on. */ /* Create 1 pipe */ @@ -6114,7 +6145,7 @@ test_file_lock_env_var(hid_t in_fapl) /* Child process */ - hid_t child_fid; /* File ID */ + hid_t child_fid = H5I_INVALID_HID; /* File ID */ int child_notify = 0; /* Close unused write end for out_pdf */ @@ -6125,18 +6156,23 @@ test_file_lock_env_var(hid_t in_fapl) while(child_notify != 1) { if(HDread(out_pdf[0], &child_notify, sizeof(int)) < 0) HDexit(EXIT_FAILURE); - } /* end while */ + } - /* Open the test file */ - if((child_fid = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) - TEST_ERROR + /* Open and close the test file */ + H5E_BEGIN_TRY { + child_fid = H5Fopen(filename, H5F_ACC_RDWR, fapl); + ret = H5Fclose(child_fid); + } H5E_END_TRY; /* Close the pipe */ if(HDclose(out_pdf[0]) < 0) HDexit(EXIT_FAILURE); - HDexit(EXIT_SUCCESS); - } /* end if */ + if(H5I_INVALID_HID == child_fid || FAIL == ret) + HDexit(EXIT_FAILURE); + else + HDexit(EXIT_SUCCESS); + } /* end child process work */ /* close unused read end for out_pdf */ if(HDclose(out_pdf[0]) < 0) @@ -6159,15 +6195,28 @@ test_file_lock_env_var(hid_t in_fapl) if(HDwaitpid(childpid, &child_status, child_wait_option) < 0) TEST_ERROR - /* Check if child terminated normally */ - if(WIFEXITED(child_status)) { - /* Check exit status of the child */ - if(WEXITSTATUS(child_status) != 0) - TEST_ERROR - } /* end if */ + /* Check exit status of the child */ + if(WIFEXITED(child_status)) + exit_status = WEXITSTATUS(child_status); else TEST_ERROR + /* The child process should have passed or failed as follows: + * + * locks on: FAIL + * locks off: PASS + * locks on, env var override: PASS + * locks off, env var override: FAIL + */ + if(turn_locking_on && !env_var_override && (0 == exit_status)) + TEST_ERROR + else if(!turn_locking_on && !env_var_override && (0 != exit_status)) + TEST_ERROR + else if(turn_locking_on && env_var_override && (0 != exit_status)) + TEST_ERROR + else if(!turn_locking_on && env_var_override && (0 == exit_status)) + TEST_ERROR + /* Close the file */ if(H5Fclose(fid) < 0) TEST_ERROR @@ -6191,7 +6240,7 @@ error: #endif /* !(defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID)) */ -} /* end test_file_lock_env_var() */ +} /* end test_file_locking() */ static int @@ -7018,7 +7067,7 @@ error: H5Fclose(fid3); } H5E_END_TRY; - return -1; + return 1; } /* test_multiple_same() */ @@ -7035,6 +7084,7 @@ main(void) char *driver = NULL; /* VFD string (from env variable) */ char *lock_env_var = NULL; /* file locking env var pointer */ hbool_t use_file_locking; /* read from env var */ + hbool_t file_locking_enabled = FALSE; /* Checks if the file system supports locks */ /* Skip this test if SWMR I/O is not supported for the VFD specified * by the environment variable. @@ -7055,6 +7105,13 @@ main(void) else use_file_locking = TRUE; + /* Check if file locking is enabled on this file system */ + if(use_file_locking) + if(h5_check_if_file_locking_enabled(&file_locking_enabled) < 0) { + HDprintf("Error when determining if file locks are enabled\n"); + return EXIT_FAILURE; + } + /* Set up */ h5_reset(); @@ -7096,7 +7153,7 @@ main(void) nerrors += test_append_flush_dataset_fixed(fapl); nerrors += test_append_flush_dataset_multiple(fapl); - if(use_file_locking) { + if(use_file_locking && file_locking_enabled) { /* * Tests for: * file open flags--single process access @@ -7126,7 +7183,12 @@ main(void) /* This test changes the HDF5_USE_FILE_LOCKING environment variable * so it should be run last. */ - nerrors += test_file_lock_env_var(fapl); + if (use_file_locking && file_locking_enabled) { + nerrors += test_file_locking(fapl, TRUE, TRUE); + nerrors += test_file_locking(fapl, TRUE, FALSE); + nerrors += test_file_locking(fapl, FALSE, TRUE); + nerrors += test_file_locking(fapl, FALSE, FALSE); + } if(nerrors) goto error; diff --git a/test/swmr_addrem_writer.c b/test/swmr_addrem_writer.c index 71e4929..7ad74ed 100644 --- a/test/swmr_addrem_writer.c +++ b/test/swmr_addrem_writer.c @@ -88,26 +88,6 @@ open_skeleton(const char *filename, unsigned verbose) if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) return -1; -#ifdef QAK - /* Increase the initial size of the metadata cache */ - { - H5AC_cache_config_t mdc_config; - - mdc_config.version = H5AC__CURR_CACHE_CONFIG_VERSION; - H5Pget_mdc_config(fapl, &mdc_config); - HDfprintf(stderr, "mdc_config.initial_size = %lu\n", (unsigned long)mdc_config.initial_size); - HDfprintf(stderr, "mdc_config.epoch_length = %lu\n", (unsigned long)mdc_config.epoch_length); - mdc_config.set_initial_size = 1; - mdc_config.initial_size = 16 * 1024 * 1024; - /* mdc_config.epoch_length = 5000; */ - H5Pset_mdc_config(fapl, &mdc_config); - } -#endif /* QAK */ - -#ifdef QAK - H5Pset_fapl_log(fapl, "append.log", H5FD_LOG_ALL, (size_t)(512 * 1024 * 1024)); -#endif /* QAK */ - /* Open the file */ if((fid = H5Fopen(filename, H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE, fapl)) < 0) return -1; diff --git a/test/swmr_generator.c b/test/swmr_generator.c index f6a4fe2..7fb08df 100644 --- a/test/swmr_generator.c +++ b/test/swmr_generator.c @@ -121,38 +121,10 @@ gen_skeleton(const char *filename, hbool_t verbose, hbool_t swmr_write, if(!HDstrcmp(index_type, "b2")) max_dims[0] = H5S_UNLIMITED; -#ifdef QAK - /* Increase the initial size of the metadata cache */ - { - H5AC_cache_config_t mdc_config; - - mdc_config.version = H5AC__CURR_CACHE_CONFIG_VERSION; - H5Pget_mdc_config(fapl, &mdc_config); - HDfprintf(stderr, "mdc_config.initial_size = %lu\n", (unsigned long)mdc_config.initial_size); - HDfprintf(stderr, "mdc_config.epoch_length = %lu\n", (unsigned long)mdc_config.epoch_length); - mdc_config.set_initial_size = 1; - mdc_config.initial_size = 16 * 1024 * 1024; - /* mdc_config.epoch_length = 5000; */ - H5Pset_mdc_config(fapl, &mdc_config); - } -#endif /* QAK */ - -#ifdef QAK - H5Pset_small_data_block_size(fapl, (hsize_t)(50 * CHUNK_SIZE * DTYPE_SIZE)); -#endif /* QAK */ - -#ifdef QAK - H5Pset_fapl_log(fapl, "append.log", H5FD_LOG_ALL, (size_t)(512 * 1024 * 1024)); -#endif /* QAK */ - /* Create file creation property list */ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) return -1; -#ifdef QAK - H5Pset_link_phase_change(fcpl, 0, 0); -#endif /* QAK */ - /* Emit informational message */ if(verbose) HDfprintf(stderr, "Creating file\n"); diff --git a/test/swmr_remove_writer.c b/test/swmr_remove_writer.c index 2bebab9..504ea8a 100644 --- a/test/swmr_remove_writer.c +++ b/test/swmr_remove_writer.c @@ -90,26 +90,6 @@ open_skeleton(const char *filename, unsigned verbose, unsigned old) return -1; } -#ifdef QAK -/* Increase the initial size of the metadata cache */ - { - H5AC_cache_config_t mdc_config; - - mdc_config.version = H5AC__CURR_CACHE_CONFIG_VERSION; - H5Pget_mdc_config(fapl, &mdc_config); - HDfprintf(stderr, "mdc_config.initial_size = %lu\n", (unsigned long)mdc_config.initial_size); - HDfprintf(stderr, "mdc_config.epoch_length = %lu\n", (unsigned long)mdc_config.epoch_length); - mdc_config.set_initial_size = 1; - mdc_config.initial_size = 16 * 1024 * 1024; - /* mdc_config.epoch_length = 5000; */ - H5Pset_mdc_config(fapl, &mdc_config); - } -#endif /* QAK */ - -#ifdef QAK - H5Pset_fapl_log(fapl, "append.log", H5FD_LOG_ALL, (size_t)(512 * 1024 * 1024)); -#endif /* QAK */ - /* Open the file */ if((fid = H5Fopen(filename, H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE, fapl)) < 0) return -1; diff --git a/test/swmr_sparse_writer.c b/test/swmr_sparse_writer.c index 5173c71..1892fe2 100644 --- a/test/swmr_sparse_writer.c +++ b/test/swmr_sparse_writer.c @@ -87,26 +87,6 @@ open_skeleton(const char *filename, unsigned verbose) if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) return -1; -#ifdef QAK - /* Increase the initial size of the metadata cache */ - { - H5AC_cache_config_t mdc_config; - - mdc_config.version = H5AC__CURR_CACHE_CONFIG_VERSION; - H5Pget_mdc_config(fapl, &mdc_config); - HDfprintf(stderr, "mdc_config.initial_size = %lu\n", (unsigned long)mdc_config.initial_size); - HDfprintf(stderr,"mdc_config.epoch_length = %lu\n", (unsigned long)mdc_config.epoch_length); - mdc_config.set_initial_size = 1; - mdc_config.initial_size = 16 * 1024 * 1024; - /* mdc_config.epoch_length = 5000; */ - H5Pset_mdc_config(fapl, &mdc_config); - } -#endif /* QAK */ - -#ifdef QAK - H5Pset_fapl_log(fapl, "append.log", H5FD_LOG_ALL, (size_t)(512 * 1024 * 1024)); -#endif /* QAK */ - /* Open the file */ if((fid = H5Fopen(filename, H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE, fapl)) < 0) return -1; diff --git a/test/swmr_start_write.c b/test/swmr_start_write.c index fc7e7a5..0527229 100644 --- a/test/swmr_start_write.c +++ b/test/swmr_start_write.c @@ -85,16 +85,6 @@ create_file(const char *filename, hbool_t verbose, FILE *verbose_file, if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) return -1; -#ifdef QAK - if(verbose) { - char verbose_name[1024]; - - HDsnprintf(verbose_name, sizeof(verbose_name), "swmr_start_write.log.%u", random_seed); - - H5Pset_fapl_log(fapl, verbose_name, H5FD_LOG_ALL, (size_t)(512 * 1024 * 1024)); - } /* end if */ -#endif /* QAK */ - /* Create file creation property list */ if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) return -1; diff --git a/test/swmr_writer.c b/test/swmr_writer.c index d4387aa..656a5b2 100644 --- a/test/swmr_writer.c +++ b/test/swmr_writer.c @@ -90,22 +90,6 @@ open_skeleton(const char *filename, hbool_t verbose, FILE *verbose_file, return -1; } -#ifdef QAK - /* Increase the initial size of the metadata cache */ - { - H5AC_cache_config_t mdc_config; - - mdc_config.version = H5AC__CURR_CACHE_CONFIG_VERSION; - H5Pget_mdc_config(fapl, &mdc_config); - HDfprintf(stderr, "mdc_config.initial_size = %lu\n", (unsigned long)mdc_config.initial_size); - HDfprintf(stderr, "mdc_config.epoch_length = %lu\n", (unsigned long)mdc_config.epoch_length); - mdc_config.set_initial_size = 1; - mdc_config.initial_size = 16 * 1024 * 1024; - /* mdc_config.epoch_length = 5000; */ - H5Pset_mdc_config(fapl, &mdc_config); - } -#endif /* QAK */ - if(use_log_vfd) { char verbose_name[1024]; diff --git a/test/tattr.c b/test/tattr.c index b11fd0d..2a5e613 100644 --- a/test/tattr.c +++ b/test/tattr.c @@ -531,7 +531,7 @@ test_attr_flush(hid_t fapl) ret=H5Aread(att, H5T_NATIVE_DOUBLE, &rdata); CHECK(ret, FAIL, "H5Awrite"); - if(!H5_DBL_ABS_EQUAL(rdata, H5_DOUBLE(0.0))) + if(!H5_DBL_ABS_EQUAL(rdata, (double)0.0f)) TestErrPrintf("attribute value wrong: rdata=%f, should be %f\n",rdata,(double)0.0F); ret=H5Fflush(fil, H5F_SCOPE_GLOBAL); @@ -540,7 +540,7 @@ test_attr_flush(hid_t fapl) ret=H5Aread(att, H5T_NATIVE_DOUBLE, &rdata); CHECK(ret, FAIL, "H5Awrite"); - if(!H5_DBL_ABS_EQUAL(rdata, H5_DOUBLE(0.0))) + if(!H5_DBL_ABS_EQUAL(rdata, (double)0.0f)) TestErrPrintf("attribute value wrong: rdata=%f, should be %f\n",rdata,(double)0.0F); ret=H5Awrite(att, H5T_NATIVE_DOUBLE, &wdata); @@ -6560,13 +6560,6 @@ attr_iterate2_cb(hid_t loc_id, const char *attr_name, const H5A_info_t *info, char attrname[NAME_BUF_SIZE]; /* Object name */ H5A_info_t my_info; /* Local attribute info */ -#ifdef QAK -HDfprintf(stderr, "attr_name = '%s'\n", attr_name); -if(info) - HDfprintf(stderr, "info->corder = %u\n", (unsigned)info->corder); -HDfprintf(stderr, "op_data->curr = %Hd\n", op_data->curr); -#endif /* QAK */ - /* Increment # of times the callback was called */ op_data->ncalled++; diff --git a/test/tchecksum.c b/test/tchecksum.c index 6e509fb..82dc135 100644 --- a/test/tchecksum.c +++ b/test/tchecksum.c @@ -15,7 +15,7 @@ * * Created: tchecksum.c * Aug 21 2006 - * Quincey Koziol <koziol@hdfgroup.org> + * Quincey Koziol * * Purpose: Test internal checksum routine(s) * diff --git a/test/test_mirror.sh.in b/test/test_mirror.sh.in new file mode 100644 index 0000000..9635c38 --- /dev/null +++ b/test/test_mirror.sh.in @@ -0,0 +1,100 @@ +#! /bin/bash +# +# 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. +# +# Tests for the Mirror VFD feature. +# +# Created: +# Jacob Smith, 2019-12-30 + +############################################################################### +## test parameters +############################################################################### + +nerrors=0 + +SERVER_VERBOSITY="--verbosity=1" +SERVER_PORT="--port=3000" + + +############################################################################### +## Main +############################################################################### + +## TODO: arguments for main port, port range, verbosity? +# Parse options (none accepted at this time) +while [ $# -gt 0 ]; do + case "$1" in + *) # unknown option + echo "$0: Unknown option ($1)" + exit 1 + ;; + esac +done + + + +RUN_DIR=mirror_vfd_test +MIRROR_UTILS=../utils/mirror_vfd # TODO: presupposes from test/ + +mkdir $RUN_DIR + +# Copy program files into dedicated test directory +for FILE in $MIRROR_UTILS/mirror_* ; do + case "$FILE" in + *.o) continue ;; # Don't copy .o files + esac + cp $FILE $RUN_DIR +done +cp mirror_vfd $RUN_DIR + +# With the --disable-shared option, program files are built in their main +# directories; otherwise they are built in dir/.libs with a corresponding +# wrapper script. Copy these libs builds if appropriate. +if [ -f $MIRROR_UTILS/.libs/mirror_server ] ; then + RUN_LIBS=$RUN_DIR/.libs + mkdir $RUN_LIBS + for FILE in $MIRROR_UTILS/.libs/mirror_* ; do + case "$FILE" in + *.o) continue ;; # Don't copy .o files + esac + cp $FILE $RUN_LIBS + done + cp .libs/mirror_vfd $RUN_LIBS +fi + +cd $RUN_DIR + +echo "Launching Mirror Server" +SERVER_ARGS="$SERVER_PORT $SERVER_VERBOSITY" +./mirror_server $SERVER_ARGS & + +./mirror_vfd +nerrors=$? + +echo "Stopping Mirror Server" +./mirror_server_stop $SERVER_PORT + +############################################################################### +## Report and exit +############################################################################### +cd .. +if test $nerrors -eq 0 ; then + echo "Mirror VFD tests passed." + if test -z "$HDF5_NOCLEANUP" ; then + rm -rf $RUN_DIR + fi + exit 0 +else + echo "Mirror VFD tests FAILED." + exit 1 +fi + diff --git a/test/testframe.c b/test/testframe.c index 3c2a335..cfb62ec 100644 --- a/test/testframe.c +++ b/test/testframe.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Programmer: Quincey Koziol * Tuesday, January 6, 2004 * * Purpose: Provides support functions for the testing framework. diff --git a/test/timer.c b/test/timer.c new file mode 100644 index 0000000..1014e75 --- /dev/null +++ b/test/timer.c @@ -0,0 +1,414 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Dana Robinson + * May, 2011 + * + * Purpose: Tests the operation of the platform-independent timers. + */ + +#include "h5test.h" + + + + +/*------------------------------------------------------------------------- + * Function: test_time_formatting + * + * Purpose: Tests time string creation. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Dana Robinson + * May 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +test_time_formatting(void) +{ + char *s = NULL; + + TESTING("Time string formats"); + + /* < 0, N/A */ + s = H5_timer_get_time_string(-1.0F); + if(NULL == s || HDstrcmp(s, "N/A") != 0) + TEST_ERROR; + HDfree(s); + + /* 0 0 */ + s = H5_timer_get_time_string(0.0F); + if(NULL == s || HDstrcmp(s, "0.0 s") != 0) + TEST_ERROR; + HDfree(s); + + /* < 1 us nanoseconds */ + s = H5_timer_get_time_string(123.0E-9F); + if(NULL == s || HDstrcmp(s, "123 ns") != 0) + TEST_ERROR; + HDfree(s); + + /* < 1 ms microseconds */ + s = H5_timer_get_time_string(23.456E-6F); + if(NULL == s || HDstrcmp(s, "23.5 us") != 0) + TEST_ERROR; + HDfree(s); + + /* < 1 s milliseconds */ + s = H5_timer_get_time_string(4.56789E-3F); + if(NULL == s || HDstrcmp(s, "4.6 ms") != 0) + TEST_ERROR; + HDfree(s); + + /* < 1 min seconds */ + s = H5_timer_get_time_string(3.14F); + if(NULL == s || HDstrcmp(s, "3.14 s") != 0) + TEST_ERROR; + HDfree(s); + + /* < 1 hr mins, secs */ + s = H5_timer_get_time_string(2521.0F); + if(NULL == s || HDstrcmp(s, "42 m 1 s") != 0) + TEST_ERROR; + HDfree(s); + + /* < 1 d hrs, mins, secs */ + s = H5_timer_get_time_string(9756.0F); + if(NULL == s || HDstrcmp(s, "2 h 42 m 36 s") != 0) + TEST_ERROR; + HDfree(s); + + /* > 1 d days, hrs, mins, secs */ + s = H5_timer_get_time_string(280802.0F); + if(NULL == s || HDstrcmp(s, "3 d 6 h 0 m 2 s") != 0) + TEST_ERROR; + HDfree(s); + + PASSED(); + return 0; + +error: + if(s) + HDfree(s); + return -1; + +} + + +/*------------------------------------------------------------------------- + * Function: test_timer_system_user + * + * Purpose: Tests the ability to get system and user times from the + * timers. + * Some platforms may require special code to get system and + * user times. If we do not support that particular platform + * dependent functionality, this test is skipped. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Dana Robinson + * May 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +test_timer_system_user(void) +{ + int i; + char *buf = NULL; + H5_timer_t timer; + H5_timevals_t times; + herr_t err; + + TESTING("system/user times"); + + err = H5_timer_init(&timer); + if(err < 0) + TEST_ERROR; + + err = H5_timer_start(&timer); + if(err < 0) + TEST_ERROR; + + /* The system and user times may not be present on some systems. They + * will be -1.0 if they are not. + */ + if(timer.initial.system < (double)0.0f || timer.initial.user < (double)0.0f) { + SKIPPED(); + printf("NOTE: No suitable way to get system/user times on this platform.\n"); + return 0; + } + + /* Do some fake work */ + for(i=0; i < 1024; i++) { + buf = (char *)HDmalloc(1024 * (size_t)i); + HDfree(buf); + } + + err = H5_timer_stop(&timer); + if(err < 0) + TEST_ERROR; + + err = H5_timer_get_times(timer, ×); + if(err < 0) + TEST_ERROR; + + /* System and user times should be non-negative. */ + if(times.system < (double)0.0f || times.user < (double)0.0f) + TEST_ERROR; + + PASSED(); + return 0; + +error: + return -1; +} + + +/*------------------------------------------------------------------------- + * Function: test_timer_elapsed + * + * Purpose: Tests the ability to get elapsed times from the timers. + * We should always be able to get an elapsed time, + * regardless of the time libraries or platform. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Dana Robinson + * May 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +test_timer_elapsed(void) +{ + int i; + char *buf = NULL; + H5_timer_t timer; + H5_timevals_t times; + herr_t err; + + TESTING("elapsed times"); + + err = H5_timer_init(&timer); + if(err < 0) + TEST_ERROR; + + err = H5_timer_start(&timer); + if(err < 0) + TEST_ERROR; + + /* Do some fake work */ + for(i=0; i < 1024; i++) { + buf = (char *)HDmalloc(1024 * (size_t)i); + HDfree(buf); + } + + err = H5_timer_stop(&timer); + if(err < 0) + TEST_ERROR; + + err = H5_timer_get_times(timer, ×); + if(err < 0) + TEST_ERROR; + + /* Elapsed time should be non-negative. */ + if(times.elapsed < (double)0.0f) + TEST_ERROR; + + PASSED(); + return 0; + +error: + return -1; +} + + + +static herr_t +test_timer_functionality(void) +{ + int i; + char *buf = NULL; + H5_timer_t timer; + + H5_timevals_t times; + double prev_etime; + double prev_total_etime; + + herr_t err; + + TESTING("timer functionality"); + + /***************** + * CHECK STARTUP * + *****************/ + + /* Timer should be running after start */ + err = H5_timer_init(&timer); + if(err < 0 || timer.is_running) + TEST_ERROR; + + /* Times should be initialized to zero */ + err = H5_timer_get_times(timer, ×); + if(err < 0 || !H5_DBL_ABS_EQUAL(times.elapsed, (double)0.0f)) + TEST_ERROR; + + err = H5_timer_get_total_times(timer, ×); + if(err < 0 || !H5_DBL_ABS_EQUAL(times.elapsed, (double)0.0f)) + TEST_ERROR; + + + /******************** + * CHECK START/STOP * + ********************/ + + /* Running state should change after start */ + err = H5_timer_start(&timer); + if(err < 0 || !timer.is_running) + TEST_ERROR; + + /* Do some fake work */ + for(i=0; i < 1024; i++) { + buf = (char *)HDmalloc(1024 * (size_t)i); + HDfree(buf); + } + + /* Running state should change after stop */ + err = H5_timer_stop(&timer); + if(err < 0 || timer.is_running) + TEST_ERROR; + + /* Times should be positive and non-negative */ + err = H5_timer_get_times(timer, ×); + if(err < 0 || times.elapsed < (double)0.0f) + TEST_ERROR; + + err = H5_timer_get_total_times(timer, ×); + if(err < 0 || times.elapsed < (double)0.0f) + TEST_ERROR; + + + /********************** + * CHECK INTERRUPTING * + **********************/ + + /* Timer should change stat and refresh to 0s */ + err = H5_timer_init(&timer); + if(err < 0 || timer.is_running) + TEST_ERROR; + + err = H5_timer_get_times(timer, ×); + if(err < 0 || !H5_DBL_ABS_EQUAL(times.elapsed, (double)0.0f)) + TEST_ERROR; + + err = H5_timer_get_total_times(timer, ×); + if(err < 0 || !H5_DBL_ABS_EQUAL(times.elapsed, (double)0.0f)) + TEST_ERROR; + + /* Timer state should flip */ + err = H5_timer_start(&timer); + if(err < 0 || !timer.is_running) + TEST_ERROR; + + /* Do some fake work */ + for(i=0; i < 1024; i++) { + buf = (char *)HDmalloc(1024 * (size_t)i); + HDfree(buf); + } + + /* Times should be non-negative */ + err = H5_timer_get_times(timer, ×); + if(err < 0 || times.elapsed < (double)0.0f) + TEST_ERROR; + prev_etime = times.elapsed; + + err = H5_timer_get_total_times(timer, ×); + if(err < 0 || times.elapsed < (double)0.0f) + TEST_ERROR; + prev_total_etime = times.elapsed; + + /* Do some fake work */ + for(i=0; i < 1024; i++) { + buf = (char *)HDmalloc(1024 * (size_t)i); + HDfree(buf); + } + + /* State should flip on stop */ + err = H5_timer_stop(&timer); + if(err < 0 || timer.is_running) + TEST_ERROR; + + /* Times should be >= than the cached intermediate times */ + err = H5_timer_get_times(timer, ×); + if(err < 0 || times.elapsed < prev_etime) + TEST_ERROR; + + err = H5_timer_get_total_times(timer, ×); + if(err < 0 || times.elapsed < prev_total_etime) + TEST_ERROR; + + + PASSED(); + return 0; + +error: + return -1; +} + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: Tests the basic functionality of the platform-independent + * timers + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: Dana Robinson + * May, 2011 + * + *------------------------------------------------------------------------- + */ +int +main(void) +{ + int nerrors = 0; + + h5_reset(); + + printf("Testing platform-independent timer functionality.\n"); + + nerrors += test_time_formatting() < 0 ? 1 : 0; + nerrors += test_timer_system_user() < 0 ? 1 : 0; + nerrors += test_timer_elapsed() < 0 ? 1 : 0; + nerrors += test_timer_functionality() < 0 ? 1 : 0; + + if(nerrors) { + printf("***** %d platform-independent timer TEST%s FAILED! *****\n", + nerrors, nerrors > 1 ? "S" : ""); + return 1; + } else { + printf("All platform-independent timer tests passed.\n"); + return 0; + } +} + diff --git a/test/unlink.c b/test/unlink.c index 89c59c3..c599b49 100644 --- a/test/unlink.c +++ b/test/unlink.c @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Robb Matzke <matzke@llnl.gov> + * Programmer: Robb Matzke * Friday, September 25, 1998 * * Purpose: Test unlinking operations. diff --git a/test/use_append_chunk_mirror.c b/test/use_append_chunk_mirror.c new file mode 100644 index 0000000..6ee01c0 --- /dev/null +++ b/test/use_append_chunk_mirror.c @@ -0,0 +1,403 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* HACKED VERSION + * Demonstrate SWMR with a mirrored file. + * + * Must be built with SERVER_IP as the IP address of the target system + * with a running mirror server, and SERVER_PORT as the primary server port. + * + * In addition to the local file, 'shinano.h5' will be created on the remote + * system, mirroring the local file. The file location will be local to + * Server's/Writer's invocation directory. + * + * Template for demonstration purposes: + * + * # Launch mirror server on remote machine (in foreground to easily stop) + * REMOTE(1)$ ./mirror_server /path/to/mirror_worker + * + * # Launch chunk writer with plenty of chunks. + * LOCAL(1)$ ./use_append_chunk_mirror -l w -n 10000 + * + * # Wait one second for files to be created. + * + * # Launch chunk readers on both files. + * LOCAL(2)$ ./use_append_chunk_mirror -l r -n 10000 + * REMOTE(2)$ ./use_append_chunk_mirror -l r -n 10000 -f shinano.h5 + * + * # Hard-stop the server. + * REMOTE(1)$ ^C + * # alt, softer shutdown using echo and nc + * echo "SHUTDOWN" | nc localhost 3000 + */ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Use Case 1.7 Appending a single chunk + * Description: + * Appending a single chunk of raw data to a dataset along an unlimited + * dimension within a pre-created file and reading the new data back. + * Goal: + * Read data appended by the Writer to a pre-existing dataset in a + * file. The dataset has one or more unlimited dimensions. The data is + * appended by a hyperslab that is contained in one chunk (for example, + * appending 2-dim planes along the slowest changing dimension in the + * 3-dim dataset). + * Level: + * User Level + * Guarantees: + * o Readers will see the modified dimension sizes after the Writer + * finishes HDF5 metadata updates and issues H5Fflush or H5Oflush calls. + * o Readers will see newly appended data after the Writer finishes + * the flush operation. + * + * Preconditions: + * o Readers are not allowed to modify the file. + * o All datasets that are modified by the Writer exist when the Writer + * opens the file. + * o All datasets that are modified by the Writer exist when a Reader + * opens the file. + * o Data is written by a hyperslab contained in one chunk. + * + * Main Success Scenario: + * 1. An application creates a file with required objects (groups, + * datasets, and attributes). + * 2. The Writer application opens the file and datasets in the file + * and starts adding data along the unlimited dimension using a hyperslab + * selection that corresponds to an HDF5 chunk. + * 3. A Reader opens the file and a dataset in a file, and queries + * the sizes of the dataset; if the extent of the dataset has changed, + * reads the appended data back. + * + * Discussion points: + * 1. Since the new data is written to the file, and metadata update + * operation of adding pointer to the newly written chunk is atomic and + * happens after the chunk is on the disk, only two things may happen + * to the Reader: + * o The Reader will not see new data. + * o The Reader will see all new data written by Writer. + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Created: Jacob Smith, 2019 */ + +#include "use.h" + +/* This test uses many POSIX things that are not available on + * Windows. We're using a check for fork(2) here as a proxy for + * all POSIX/Unix/Linux things until this test can be made + * more platform-independent. + */ +#ifdef H5_HAVE_FORK + +#ifdef H5_HAVE_MIRROR_VFD + +#define THIS_PROGNAME "use_append_chunk_mirror" + +#define CONNECT_WITH_JELLY 0 + +#if CONNECT_WITH_JELLY +#define SERVER_IP "10.10.10.248" /* hard-coded IP address */ +#else +#define SERVER_IP "127.0.0.1" /* localhost */ +#endif /* CONNECT_WITH_JELLY */ +#define SERVER_PORT 3000 /* hard-coded port number */ +#define MIRROR_FILE_NAME "shinano.h5" /* hard-coded duplicate/mirror filename */ + +static options_t UC_opts; /* Use Case Options */ + +/* Setup parameters for the use case. + * Return: 0 succeed; -1 fail. + */ +int +setup_parameters(int argc, char * const argv[], options_t * opts) +{ + /* use case defaults */ + HDmemset(opts, 0, sizeof(options_t)); + opts->chunksize = Chunksize_DFT; + opts->use_swmr = TRUE; + opts->iterations = 1; + opts->chunkplanes = 1; + opts->progname = THIS_PROGNAME; + + if (parse_option(argc, argv, opts) < 0) + return(-1); + + opts->chunkdims[0] = opts->chunkplanes; + opts->chunkdims[1] = opts->chunkdims[2] = opts->chunksize; + + opts->dims[0] = 0; + opts->max_dims[0] = H5S_UNLIMITED; + opts->dims[1] = opts->dims[2] = opts->max_dims[1] = opts->max_dims[2] = opts->chunksize; + + if (opts->nplanes == 0) + opts->nplanes = (hsize_t)opts->chunksize; + + show_parameters(opts); + return(0); +} /* setup_parameters() */ + + +/* Overall Algorithm: + * Parse options from user; + * Generate/pre-created test files needed and close it; + * fork: child process becomes the reader process; + * while parent process continues as the writer process; + * both run till ending conditions are met. + */ +int +main(int argc, char *argv[]) +{ + pid_t childpid=0; + pid_t mypid, tmppid; + int child_status; + int child_wait_option=0; + int ret_value = 0; + int child_ret_value; + hbool_t send_wait = FALSE; + hid_t fid = -1; /* File ID */ + H5FD_mirror_fapl_t mirr_fa; + H5FD_splitter_vfd_config_t split_fa; + hid_t mirr_fapl_id = H5I_INVALID_HID; + + if (setup_parameters(argc, argv, &UC_opts) < 0) { + Hgoto_error(1); + } + + mirr_fa.magic = H5FD_MIRROR_FAPL_MAGIC; + mirr_fa.version = H5FD_MIRROR_CURR_FAPL_T_VERSION; + mirr_fa.handshake_port = SERVER_PORT; + HDstrncpy(mirr_fa.remote_ip, SERVER_IP, H5FD_MIRROR_MAX_IP_LEN); + + + split_fa.wo_fapl_id = H5I_INVALID_HID; + split_fa.rw_fapl_id = H5I_INVALID_HID; + split_fa.magic = H5FD_SPLITTER_MAGIC; + split_fa.version = H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION; + split_fa.log_file_path[0] = '\0'; /* none */ + split_fa.ignore_wo_errs = FALSE; + HDstrncpy(split_fa.wo_path, MIRROR_FILE_NAME, H5FD_SPLITTER_PATH_MAX); + + /* Determine the need to send/wait message file*/ + if (UC_opts.launch == UC_READWRITE) { + HDunlink(WRITER_MESSAGE); + send_wait = TRUE; + } + + /* ==============================================================*/ + /* UC_READWRITE: create datafile, launch both reader and writer. */ + /* UC_WRITER: create datafile, skip reader, launch writer. */ + /* UC_READER: skip create, launch reader, exit. */ + /* ==============================================================*/ + /* =========== */ + /* Create file */ + /* =========== */ + if (UC_opts.launch != UC_READER) { + HDprintf("Creating skeleton data file for test...\n"); + + /* Prepare mirror child driver */ + mirr_fapl_id = H5Pcreate(H5P_FILE_ACCESS); + if (mirr_fapl_id == H5I_INVALID_HID) { + HDfprintf(stderr, "can't create creation mirror FAPL\n"); + Hgoto_error(1); + } + if (H5Pset_fapl_mirror(mirr_fapl_id, &mirr_fa) < 0) { + HDfprintf(stderr, "can't set creation mirror FAPL\n"); + H5Eprint2(H5E_DEFAULT, stdout); + Hgoto_error(1); + } + + /* Prepare parent "splitter" driver in UC_opts */ + split_fa.wo_fapl_id = mirr_fapl_id; + split_fa.rw_fapl_id = H5P_DEFAULT; + UC_opts.fapl_id = H5Pcreate(H5P_FILE_ACCESS); + if (UC_opts.fapl_id == H5I_INVALID_HID) { + HDfprintf(stderr, "can't create creation FAPL\n"); + Hgoto_error(1); + } + if (H5Pset_fapl_splitter(UC_opts.fapl_id, &split_fa) < 0) { + HDfprintf(stderr, "can't set creation FAPL\n"); + H5Eprint2(H5E_DEFAULT, stdout); + Hgoto_error(1); + } + + if (H5Pset_libver_bounds(UC_opts.fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) { + HDfprintf(stderr, "can't set creation FAPL libver bounds\n"); + Hgoto_error(1); + } + + /* Create file */ + if (create_uc_file(&UC_opts) < 0) { + HDfprintf(stderr, "***encounter error\n"); + Hgoto_error(1); + } else { + HDprintf("File created.\n"); + } + + /* Close FAPLs to prevent issues with forking later */ + if (H5Pclose(UC_opts.fapl_id) < 0) { + HDfprintf(stderr, "can't close creation FAPL\n"); + Hgoto_error(1); + } + UC_opts.fapl_id = H5I_INVALID_HID; + if (H5Pclose(mirr_fapl_id) < 0) { + HDfprintf(stderr, "can't close creation mirror FAPL\n"); + Hgoto_error(1); + } + mirr_fapl_id = H5I_INVALID_HID; + } + + /* ============ */ + /* Fork process */ + /* ============ */ + if (UC_opts.launch == UC_READWRITE) { + if ((childpid = HDfork()) < 0) { + HDperror("fork"); + Hgoto_error(1); + } + } + mypid = HDgetpid(); + + /* ============= */ + /* launch reader */ + /* ============= */ + if (UC_opts.launch != UC_WRITER) { + /* child process -- launch the reader */ + /* reader only opens the one file -- separate reader needed for mirrored file 'shinano.h5' */ + if (0 == childpid) { + HDprintf("%d: launch reader process\n", mypid); + + UC_opts.fapl_id = H5P_DEFAULT; + if (read_uc_file(send_wait, &UC_opts) < 0) { + HDfprintf(stderr, "read_uc_file encountered error (%d)\n", mypid); + HDexit(1); + } + + HDexit(0); + } + } + + /* ============= */ + /* launch writer */ + /* ============= */ + /* this process continues to launch the writer */ + HDprintf("%d: continue as the writer process\n", mypid); + + /* Prepare mirror child driver */ + mirr_fapl_id = H5Pcreate(H5P_FILE_ACCESS); + if (mirr_fapl_id == H5I_INVALID_HID) { + HDfprintf(stderr, "can't create creation mirror FAPL\n"); + Hgoto_error(1); + } + if (H5Pset_fapl_mirror(mirr_fapl_id, &mirr_fa) < 0) { + HDfprintf(stderr, "can't set creation mirror FAPL\n"); + H5Eprint2(H5E_DEFAULT, stdout); + Hgoto_error(1); + } + + /* Prepare parent "splitter" driver in UC_opts */ + split_fa.wo_fapl_id = mirr_fapl_id; + split_fa.rw_fapl_id = H5P_DEFAULT; + UC_opts.fapl_id = H5Pcreate(H5P_FILE_ACCESS); + if (UC_opts.fapl_id == H5I_INVALID_HID) { + HDfprintf(stderr, "can't create creation FAPL\n"); + Hgoto_error(1); + } + if (H5Pset_fapl_splitter(UC_opts.fapl_id, &split_fa) < 0) { + HDfprintf(stderr, "can't set creation FAPL\n"); + H5Eprint2(H5E_DEFAULT, stdout); + Hgoto_error(1); + } + + if (UC_opts.use_swmr) { + if (H5Pset_libver_bounds(UC_opts.fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) { + HDfprintf(stderr, "can't set write FAPL libver bounds\n"); + Hgoto_error(1); + } + } + + if ((fid = H5Fopen(UC_opts.filename, H5F_ACC_RDWR | (UC_opts.use_swmr ? H5F_ACC_SWMR_WRITE : 0), UC_opts.fapl_id)) < 0) { + HDfprintf(stderr, "H5Fopen failed\n"); + Hgoto_error(1); + } + + if (write_uc_file(send_wait, fid, &UC_opts) < 0) { + HDfprintf(stderr, "write_uc_file encountered error\n"); + Hgoto_error(1); + } + + if (H5Fclose(fid) < 0) { + HDfprintf(stderr, "Failed to close write\n"); + Hgoto_error(1); + } + + if (H5Pclose(UC_opts.fapl_id) < 0) { + HDfprintf(stderr, "can't close write FAPL\n"); + Hgoto_error(1); + } + + if (H5Pclose(mirr_fapl_id) < 0) { + HDfprintf(stderr, "can't close write mirror FAPL\n"); + Hgoto_error(1); + } + + /* ================================================ */ + /* If readwrite, collect exit code of child process */ + /* ================================================ */ + if (UC_opts.launch == UC_READWRITE) { + if ((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0) { + HDperror("waitpid"); + Hgoto_error(1); + } + + if (WIFEXITED(child_status)) { + if ((child_ret_value = WEXITSTATUS(child_status)) != 0) { + HDprintf("%d: child process exited with non-zero code (%d)\n", + mypid, child_ret_value); + Hgoto_error(2); + } + } else { + HDprintf("%d: child process terminated abnormally\n", mypid); + Hgoto_error(2); + } + } + +done: + if (ret_value != 0) { + HDprintf("Error(s) encountered\n"); + } else { + HDprintf("All passed\n"); + } + + return(ret_value); +} + +#else /* H5_HAVE_MIRROR_VFD */ + +int +main(void) +{ + HDfprintf(stderr, "Mirror VFD is not built. Skipping.\n"); + return EXIT_SUCCESS; +} /* end main() */ + +#endif /* H5_HAVE_MIRROR_VFD */ + +#else /* H5_HAVE_FORK */ + +int +main(void) +{ + HDfprintf(stderr, "Non-POSIX platform. Skipping.\n"); + return EXIT_SUCCESS; +} /* end main() */ + +#endif /* H5_HAVE_FORK */ + @@ -11,7 +11,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Neil Fortner <nfortne2@hdfgroup.org> + * Programmer: Neil Fortner * Monday, February 16, 2015 * * Purpose: Tests datasets with virtual layout. diff --git a/test/vds_env.c b/test/vds_env.c index 3d5b5dd..0d0891f 100644 --- a/test/vds_env.c +++ b/test/vds_env.c @@ -11,7 +11,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Neil Fortner <nfortne2@hdfgroup.org> + * Programmer: Neil Fortner * Monday, February 16, 2015 * * Purpose: Tests datasets with virtual layout. @@ -12,7 +12,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Programmer: Raymond Lu<slu@ncsa.uiuc.edu> + * Programmer: Raymond Lu * Tuesday, Sept 24, 2002 * * Purpose: Tests the basic features of Virtual File Drivers @@ -25,6 +25,7 @@ #define FAMILY_SIZE (1*KB) #define FAMILY_SIZE2 (5*KB) #define MULTI_SIZE 128 +#define SPLITTER_SIZE 8 /* dimensions of a dataset */ #define CORE_INCREMENT (4*KB) #define CORE_PAGE_SIZE (1024*KB) @@ -59,6 +60,9 @@ const char *FILENAME[] = { "windows_file", /*8*/ "new_multi_file_v16",/*9*/ "ro_s3_file", /*10*/ + "splitter_rw_file", /*11*/ + "splitter_wo_file", /*12*/ + "splitter.log", /*13*/ NULL }; @@ -66,7 +70,46 @@ const char *FILENAME[] = { #define COMPAT_BASENAME "family_v16_" #define MULTI_COMPAT_BASENAME "multi_file_v16" +#define SPLITTER_DATASET_NAME "dataset" + +/* Macro: HEXPRINT() + * Helper macro to pretty-print hexadecimal output of a buffer of known size. + * Each line has the address of the first printed byte, and four columns of + * four-byte data. + */ +static int __k; +#define HEXPRINT(size, buf) \ +for (__k = 0; __k < (size); __k++) { \ + if (__k % 16 == 0) { \ + HDprintf("\n%04x", __k); \ + } \ + HDprintf((__k%4 == 0) ? " %02X" : " %02X", (unsigned char)(buf)[__k]); \ +} /* end #define HEXPRINT() */ + +/* Helper structure to pass around dataset information. + */ +struct splitter_dataset_def { + void *buf; /* contents of dataset */ + const char *dset_name; /* dataset name, always added to root group */ + hid_t mem_type_id; /* datatype */ + const hsize_t *dims; /* dimensions */ + int n_dims; /* rank */ +}; + +static int splitter_prepare_file_paths(H5FD_splitter_vfd_config_t *vfd_config, + char *filename_rw_out); +static int splitter_create_single_file_at(const char *filename, hid_t fapl_id, + const struct splitter_dataset_def *data); +static int splitter_compare_expected_data(hid_t file_id, + const struct splitter_dataset_def *data); +static int run_splitter_test(const struct splitter_dataset_def *data, + hbool_t ignore_wo_errors, hbool_t provide_logfile_path, + hid_t sub_fapl_ids[2]); +static int splitter_RO_test(const struct splitter_dataset_def *data, + hid_t child_fapl_id); +static int splitter_tentative_open_test(hid_t child_fapl_id); +static int file_exists(const char *filename, hid_t fapl_id); /*------------------------------------------------------------------------- * Function: test_sec2 @@ -1148,6 +1191,123 @@ H5_GCC_DIAG_ON(format-nonliteral) /*------------------------------------------------------------------------- + * Function: test_family_member_fapl + * + * Purpose: Actually use the member fapl input to the member vfd. + * + * Return: SUCCEED/FAIL + * + * Programmer: Jacob Smith + * 21 May 2019 + * + *------------------------------------------------------------------------- + */ +static herr_t +test_family_member_fapl(void) +{ + hid_t file = H5I_INVALID_HID; + hid_t fapl_id = H5I_INVALID_HID; + hid_t memb_fapl_id = H5I_INVALID_HID; + hid_t space = H5I_INVALID_HID; + hid_t dset = H5I_INVALID_HID; + char filename[1024]; + char dname[] = "dataset"; + unsigned i = 0; + unsigned j = 0; + int **buf = NULL; + int *buf_data = NULL; + hsize_t dims[2] = {FAMILY_NUMBER, FAMILY_SIZE}; + + TESTING("Family member FAPL"); + + /* Set up data array */ + if(NULL == (buf_data = (int *)HDcalloc(FAMILY_NUMBER * FAMILY_SIZE, sizeof(int)))) + TEST_ERROR; + if(NULL == (buf = (int **)HDcalloc(FAMILY_NUMBER, sizeof(buf_data)))) + TEST_ERROR; + for (i = 0; i < FAMILY_NUMBER; i++) + buf[i] = buf_data + (i * FAMILY_SIZE); + + if((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) == H5I_INVALID_HID) + TEST_ERROR; + + if((memb_fapl_id = H5Pcreate(H5P_FILE_ACCESS)) == H5I_INVALID_HID) + TEST_ERROR; + + if (H5Pset_fapl_sec2(memb_fapl_id) == FAIL) + TEST_ERROR; + if (H5Pset_fapl_family(fapl_id, (hsize_t)FAMILY_SIZE, memb_fapl_id) == FAIL) + TEST_ERROR; + + h5_fixname(FILENAME[2], fapl_id, filename, sizeof(filename)); + + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) == H5I_INVALID_HID) + TEST_ERROR; + + if((space = H5Screate_simple(2, dims, NULL)) == H5I_INVALID_HID) + TEST_ERROR; + + /* Create and write to dataset, then close file. + */ + if((dset = H5Dcreate2(file, dname, H5T_NATIVE_INT, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) == H5I_INVALID_HID) + TEST_ERROR; + + for (i = 0; i < FAMILY_NUMBER; i++) { + for (j = 0; j < FAMILY_SIZE; j++) { + buf[i][j] = (int)((i * 10000) + j); + } + } + + if (H5Dwrite(dset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf_data) == FAIL) + TEST_ERROR; + + if (H5Dclose(dset) == FAIL) + TEST_ERROR; + if (H5Sclose(space) == FAIL) + TEST_ERROR; + if (H5Fclose(file) == FAIL) + TEST_ERROR; + + /* "Close" member FAPL at top level and re-open file. + * Should succeed, with library managing reference count properly + */ + if (H5Pclose(memb_fapl_id) == FAIL) + TEST_ERROR; + + if ((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_id)) == H5I_INVALID_HID) + TEST_ERROR; + + if (H5Fclose(file) == FAIL) + TEST_ERROR; + + h5_delete_test_file(FILENAME[2], fapl_id); + + if (H5Pclose(fapl_id) == FAIL) + TEST_ERROR; + + HDfree(buf); + HDfree(buf_data); + + PASSED(); + return SUCCEED; + +error: + H5E_BEGIN_TRY { + H5Sclose(space); + H5Dclose(dset); + H5Pclose(memb_fapl_id); + H5Pclose(fapl_id); + H5Fclose(file); + } H5E_END_TRY; + + HDfree(buf); + HDfree(buf_data); + + return FAIL; +} /* end test_family_member_fapl() */ + + +/*------------------------------------------------------------------------- * Function: test_multi_opens * * Purpose: Private function for test_multi() to tests wrong ways of @@ -2062,6 +2222,1104 @@ error: #endif /* H5_HAVE_ROS3_VFD */ } /* end test_ros3() */ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Macro: SPLITTER_TEST_FAULT() + * + * utility macro, helps create stack-like backtrace on error. + * requires defined in the calling function: + * * variable `int ret_value` (return -1 on error)` + * * label `done` for exit on fault + * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + */ +#define SPLITTER_TEST_FAULT(mesg) { \ + H5_FAILED(); \ + AT(); \ + HDfprintf(stderr, mesg); \ + H5Eprint2(H5E_DEFAULT, stderr); \ + fflush(stderr); \ + ret_value = -1; \ + goto done; \ +} + + +/*------------------------------------------------------------------------- + * Function: compare_splitter_config_info + * + * Purpose: Helper function to compare configuration info found in a + * FAPL against a canonical structure. + * + * Return: Success: 0, if config info in FAPL matches info structure. + * Failure: -1, if difference detected. + * + *------------------------------------------------------------------------- + */ +static int +compare_splitter_config_info(hid_t fapl_id, H5FD_splitter_vfd_config_t *info) +{ + int ret_value = 0; + H5FD_splitter_vfd_config_t *fetched_info = NULL; + + if (NULL == (fetched_info = HDcalloc(1, sizeof(H5FD_splitter_vfd_config_t)))) + SPLITTER_TEST_FAULT("memory allocation for fetched_info struct failed"); + + fetched_info->magic = H5FD_SPLITTER_MAGIC; + fetched_info->version = H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION; + fetched_info->rw_fapl_id = H5I_INVALID_HID; + fetched_info->wo_fapl_id = H5I_INVALID_HID; + + if (H5Pget_fapl_splitter(fapl_id, fetched_info) < 0) { + SPLITTER_TEST_FAULT("can't get splitter info"); + } + if (info->rw_fapl_id == H5P_DEFAULT) { + if (H5Pget_driver(fetched_info->rw_fapl_id) != H5Pget_driver(H5P_FILE_ACCESS_DEFAULT)) { + SPLITTER_TEST_FAULT("Read-Write driver mismatch (default)\n"); + } + } + else { + if (H5Pget_driver(fetched_info->rw_fapl_id) != H5Pget_driver(info->rw_fapl_id)) { + SPLITTER_TEST_FAULT("Read-Write driver mismatch\n"); + } + } + if (info->wo_fapl_id == H5P_DEFAULT) { + if (H5Pget_driver(fetched_info->wo_fapl_id) != H5Pget_driver(H5P_FILE_ACCESS_DEFAULT)) { + SPLITTER_TEST_FAULT("Write-Only driver mismatch (default)\n"); + } + } + else { + if (H5Pget_driver(fetched_info->wo_fapl_id) != H5Pget_driver(info->wo_fapl_id)) { + SPLITTER_TEST_FAULT("Write-Only driver mismatch\n"); + } + } + if ( (HDstrlen(info->wo_path) != HDstrlen(fetched_info->wo_path)) || + HDstrncmp(info->wo_path, fetched_info->wo_path, H5FD_SPLITTER_PATH_MAX)) + { + HDfprintf(stderr, "MISMATCH: '%s' :: '%s'\n", info->wo_path, fetched_info->wo_path); + HEXPRINT(H5FD_SPLITTER_PATH_MAX, info->wo_path); + HEXPRINT(H5FD_SPLITTER_PATH_MAX, fetched_info->wo_path); + SPLITTER_TEST_FAULT("Write-Only file path mismatch\n"); + } + +done: + HDfree(fetched_info); + + return ret_value; +} /* end compare_splitter_config_info() */ + + +/*------------------------------------------------------------------------- + * Function: run_splitter_test + * + * Purpose: Auxiliary function for test_splitter(). + * + * Return: Success: 0 + * Failure: -1 + * + * Description: + * Perform basic open-write-close with the Splitter VFD. + * Prior to operations, removes files from a previous run, + * if they exist. + * After writing, compares read-write and write-only files. + * Includes FAPL sanity testing. + * + *------------------------------------------------------------------------- + */ +static int +run_splitter_test(const struct splitter_dataset_def *data, + hbool_t ignore_wo_errors, + hbool_t provide_logfile_path, + hid_t sub_fapl_ids[2]) +{ + hid_t file_id = H5I_INVALID_HID; + hid_t fapl_id = H5I_INVALID_HID; + hid_t dset_id = H5I_INVALID_HID; + hid_t space_id = H5I_INVALID_HID; + hid_t fapl_id_out = H5I_INVALID_HID; + hid_t fapl_id_cpy = H5I_INVALID_HID; + H5FD_splitter_vfd_config_t *vfd_config = NULL; + char *filename_rw = NULL; + FILE *logfile = NULL; + int ret_value = 0; + + if (NULL == (vfd_config = HDcalloc(1, sizeof(H5FD_splitter_vfd_config_t)))) + SPLITTER_TEST_FAULT("memory allocation for vfd_config struct failed"); + if (NULL == (filename_rw = HDcalloc(H5FD_SPLITTER_PATH_MAX + 1, sizeof(char)))) + SPLITTER_TEST_FAULT("memory allocation for filename_rw string failed"); + + vfd_config->magic = H5FD_SPLITTER_MAGIC; + vfd_config->version = H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION; + vfd_config->ignore_wo_errs = ignore_wo_errors; + vfd_config->rw_fapl_id = sub_fapl_ids[0]; + vfd_config->wo_fapl_id = sub_fapl_ids[1]; + + if (splitter_prepare_file_paths(vfd_config, filename_rw) < 0) { + SPLITTER_TEST_FAULT("can't prepare file paths\n"); + } + + if (provide_logfile_path == FALSE) { + vfd_config->log_file_path[0] = '\0'; /* reset as empty string */ + } + + /* Create a new fapl to use the SPLITTER file driver */ + if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) == H5I_INVALID_HID) { + SPLITTER_TEST_FAULT("can't create FAPL ID\n"); + } + if (H5Pset_fapl_splitter(fapl_id, vfd_config) < 0) { + SPLITTER_TEST_FAULT("can't set splitter FAPL\n"); + } + if (H5Pget_driver(fapl_id) != H5FD_SPLITTER) { + SPLITTER_TEST_FAULT("set FAPL not SPLITTER\n"); + } + + if (compare_splitter_config_info(fapl_id, vfd_config) < 0) { + SPLITTER_TEST_FAULT("information mismatch\n"); + } + + /* + * Copy property list, light compare, and close the copy. + * Helps test driver-implemented FAPL-copying and library ID management. + */ + + fapl_id_cpy = H5Pcopy(fapl_id); + if (H5I_INVALID_HID == fapl_id_cpy) { + SPLITTER_TEST_FAULT("can't copy FAPL\n"); + } + if (compare_splitter_config_info(fapl_id_cpy, vfd_config) < 0) { + SPLITTER_TEST_FAULT("information mismatch\n"); + } + if (H5Pclose(fapl_id_cpy) < 0) { + SPLITTER_TEST_FAULT("can't close fapl copy\n"); + } + + /* + * Proceed with test. Create file. + */ + file_id = H5Fcreate(filename_rw, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + if (file_id < 0) { + SPLITTER_TEST_FAULT("can't create file\n"); + } + + /* + * Check driver from file + */ + + fapl_id_out = H5Fget_access_plist(file_id); + if (H5I_INVALID_HID == fapl_id_out) { + SPLITTER_TEST_FAULT("can't get file's FAPL\n"); + + } + if (H5Pget_driver(fapl_id_out) != H5FD_SPLITTER) { + SPLITTER_TEST_FAULT("wrong file FAPL driver\n"); + } + if (compare_splitter_config_info(fapl_id_out, vfd_config) < 0) { + SPLITTER_TEST_FAULT("information mismatch\n"); + } + if (H5Pclose(fapl_id_out) < 0) { + SPLITTER_TEST_FAULT("can't close file's FAPL\n"); + } + + /* + * Create and write the dataset + */ + + space_id = H5Screate_simple(data->n_dims, data->dims, NULL); + if (space_id < 0) { + SPLITTER_TEST_FAULT("can't create dataspace\n"); + } + dset_id = H5Dcreate2(file_id, data->dset_name, data->mem_type_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (dset_id < 0) { + SPLITTER_TEST_FAULT("can't create dataset\n"); + } + if (H5Dwrite(dset_id, data->mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, data->buf) < 0) { + SPLITTER_TEST_FAULT("can't write data to dataset\n"); + } + + /* Close everything */ + if (H5Dclose(dset_id) < 0) { + SPLITTER_TEST_FAULT("can't close dset\n"); + } + if (H5Sclose(space_id) < 0) { + SPLITTER_TEST_FAULT("can't close space\n"); + } + if (H5Pclose(fapl_id) < 0) { + SPLITTER_TEST_FAULT("can't close fapl\n"); + } + if (H5Fclose(file_id) < 0) { + SPLITTER_TEST_FAULT("can't close file\n"); + } + + /* Verify that the R/W and W/O files are identical */ + if (h5_compare_file_bytes(filename_rw, vfd_config->wo_path) < 0) { + SPLITTER_TEST_FAULT("files are not byte-for-byte equivalent\n"); + } + + /* Verify existence of logfile if appropriate */ + logfile = fopen(vfd_config->log_file_path, "r"); + if ( (TRUE == provide_logfile_path && NULL == logfile) || + (FALSE == provide_logfile_path && NULL != logfile) ) + { + SPLITTER_TEST_FAULT("no logfile when one was expected\n"); + } + +done: + if (ret_value < 0) { + H5E_BEGIN_TRY { + H5Dclose(dset_id); + H5Sclose(space_id); + H5Pclose(fapl_id_out); + H5Pclose(fapl_id_cpy); + H5Pclose(fapl_id); + H5Fclose(file_id); + } H5E_END_TRY; + } + + if (logfile != NULL) + fclose(logfile); + + HDfree(vfd_config); + HDfree(filename_rw); + + return ret_value; +} /* end run_splitter_test() */ + + +/*------------------------------------------------------------------------- + * Function: driver_is_splitter_compatible + * + * Purpose: Determine whether the driver set in the FAPL ID is compatible + * with the Splitter VFD -- specificially, Write-Only channel. + * + * Return: Success: 0 + * Failure: -1 + * + * Description: Attempts to put the given FAPL ID as the W/O channel. + * Uses driver's own mechanisms to generate error, and catches + * error. + * + *------------------------------------------------------------------------- + */ +static int +driver_is_splitter_compatible(hid_t fapl_id) +{ + H5FD_splitter_vfd_config_t *vfd_config = NULL; + hid_t split_fapl_id = H5I_INVALID_HID; + herr_t ret = SUCCEED; + int ret_value = 0; + + if (NULL == (vfd_config = HDcalloc(1, sizeof(H5FD_splitter_vfd_config_t)))) { + FAIL_PUTS_ERROR("memory allocation for vfd_config struct failed"); + } + + if(H5I_INVALID_HID == (split_fapl_id = H5Pcreate(H5P_FILE_ACCESS))) { + FAIL_PUTS_ERROR("Can't create contained FAPL"); + } + vfd_config->magic = H5FD_SPLITTER_MAGIC; + vfd_config->version = H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION; + vfd_config->ignore_wo_errs = FALSE; + vfd_config->rw_fapl_id = H5P_DEFAULT; + vfd_config->wo_fapl_id = fapl_id; + HDstrncpy(vfd_config->wo_path, "nonesuch", H5FD_SPLITTER_PATH_MAX); + vfd_config->log_file_path[0] = '\0'; + + H5E_BEGIN_TRY { + ret = H5Pset_fapl_splitter(split_fapl_id, vfd_config); + } H5E_END_TRY; + if (SUCCEED == ret) { + ret_value = -1; + } + + if (H5Pclose(split_fapl_id) < 0) { + FAIL_PUTS_ERROR("Can't close contained FAPL") + } + split_fapl_id = H5I_INVALID_HID; + + HDfree(vfd_config); + + return ret_value; + +error: + H5E_BEGIN_TRY { + H5Pclose(split_fapl_id); + } H5E_END_TRY; + + HDfree(vfd_config); + + return -1; +} /* end driver_is_splitter_compatible() */ + + +/*------------------------------------------------------------------------- + * Function: splitter_RO_test + * + * Purpose: Verify Splitter VFD with the Read-Only access flag. + * + * Return: Success: 0 + * Failure: -1 + * + * Description: Attempt read-only opening of files with different + * permutations of files already existing on-disk. + * + *------------------------------------------------------------------------- + */ +static int +splitter_RO_test( + const struct splitter_dataset_def *data, + hid_t child_fapl_id) +{ + char *filename_rw = NULL; + H5FD_splitter_vfd_config_t *vfd_config = NULL; + hid_t fapl_id = H5I_INVALID_HID; + hid_t file_id = H5I_INVALID_HID; + int ret_value = 0; + + if (NULL == (vfd_config = HDcalloc(1, sizeof(H5FD_splitter_vfd_config_t)))) + SPLITTER_TEST_FAULT("memory allocation for vfd_config struct failed"); + if (NULL == (filename_rw = HDcalloc(H5FD_SPLITTER_PATH_MAX + 1, sizeof(char)))) + SPLITTER_TEST_FAULT("memory allocation for filename_rw string failed"); + + vfd_config->magic = H5FD_SPLITTER_MAGIC; + vfd_config->version = H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION; + vfd_config->ignore_wo_errs = FALSE; + vfd_config->rw_fapl_id = child_fapl_id; + vfd_config->wo_fapl_id = child_fapl_id; + + if (splitter_prepare_file_paths(vfd_config, filename_rw) < 0) { + SPLITTER_TEST_FAULT("can't prepare splitter file paths\n"); + } + + /* Create a new fapl to use the SPLITTER file driver */ + fapl_id = H5Pcreate(H5P_FILE_ACCESS); + if (H5I_INVALID_HID == fapl_id) { + SPLITTER_TEST_FAULT("can't create FAPL ID\n"); + } + if (H5Pset_fapl_splitter(fapl_id, vfd_config) < 0) { + SPLITTER_TEST_FAULT("can't set splitter FAPL\n"); + } + if (H5Pget_driver(fapl_id) != H5FD_SPLITTER) { + SPLITTER_TEST_FAULT("set FAPL not SPLITTER\n"); + } + + /* Attempt R/O open when both files are nonexistent + * Should fail. + */ + + H5E_BEGIN_TRY { + file_id = H5Fopen(filename_rw, H5F_ACC_RDONLY, fapl_id); + } H5E_END_TRY; + if (file_id >= 0) { + SPLITTER_TEST_FAULT("R/O open on nonexistent files unexpectedly successful\n"); + } + + /* Attempt R/O open when only W/O file exists + * Should fail. + */ + + if (splitter_create_single_file_at(vfd_config->wo_path, vfd_config->wo_fapl_id, data) < 0) { + SPLITTER_TEST_FAULT("can't write W/O file\n"); + } + H5E_BEGIN_TRY { + file_id = H5Fopen(filename_rw, H5F_ACC_RDONLY, fapl_id); + } H5E_END_TRY; + if (file_id >= 0) { + SPLITTER_TEST_FAULT("R/O open with extant W/O file unexpectedly successful\n"); + } + HDremove(vfd_config->wo_path); + + /* Attempt R/O open when only R/W file exists + * Should fail. + */ + + if (splitter_create_single_file_at(filename_rw, vfd_config->rw_fapl_id, data) < 0) { + SPLITTER_TEST_FAULT("can't create R/W file\n"); + } + H5E_BEGIN_TRY { + file_id = H5Fopen(filename_rw, H5F_ACC_RDONLY, fapl_id); + } H5E_END_TRY; + if (file_id >= 0) { + SPLITTER_TEST_FAULT("R/O open with extant R/W file unexpectedly successful\n"); + } + + /* Attempt R/O open when both R/W and W/O files exist + */ + + if (splitter_create_single_file_at(vfd_config->wo_path, vfd_config->wo_fapl_id, data) < 0) { + SPLITTER_TEST_FAULT("can't create W/O file\n"); + } + file_id = H5Fopen(filename_rw, H5F_ACC_RDONLY, fapl_id); + if (file_id < 0) { + SPLITTER_TEST_FAULT("R/O open on two extant files failed\n"); + } + if (splitter_compare_expected_data(file_id, data) < 0) { + SPLITTER_TEST_FAULT("data mismatch in R/W file\n"); + } + if (H5Fclose(file_id) < 0) { + SPLITTER_TEST_FAULT("can't close file(s)\n"); + } + file_id = H5I_INVALID_HID; + + /* Cleanup + */ + + if (H5Pclose(fapl_id) < 0) { + SPLITTER_TEST_FAULT("can't close FAPL ID\n"); + } + fapl_id = H5I_INVALID_HID; + +done: + if (ret_value < 0) { + H5E_BEGIN_TRY { + H5Pclose(fapl_id); + H5Fclose(file_id); + } H5E_END_TRY; + } + + HDfree(vfd_config); + HDfree(filename_rw); + + return ret_value; +} /* end splitter_RO_test() */ + + +/*------------------------------------------------------------------------- + * Function: splitter_prepare_file_paths + * + * Purpose: Get file paths ready for use by the Splitter VFD tests. + * + * Return: Success: 0 + * Failure: -1 + * + * Description: + * Use h5_fixname to adjust the splitter-relevant file paths + * from those given in FILENAMES. + * + * REMOVES EXISTING FILES AT THE PATH LOCATIONS PRIOR TO RETURN. + * + * The relevant file paths will be set in filename_rw_out and + * inside the config structure (wo_path, log_file_path). + * + * `filename_rw_out` must be at least H5FD_SPLITTER_PATH_MAX+1 + * characters long. + * + * `vfd_config` must have its child FAPL IDs preset. + * + *------------------------------------------------------------------------- + */ +static int +splitter_prepare_file_paths(H5FD_splitter_vfd_config_t *vfd_config, char *filename_rw_out) +{ + int ret_value = 0; + + if (vfd_config == NULL || vfd_config->magic != H5FD_SPLITTER_MAGIC) { + SPLITTER_TEST_FAULT("invalid splitter config pointer\n"); + } + if (filename_rw_out == NULL) { + SPLITTER_TEST_FAULT("NULL filename_rw pointer\n"); + } + + /* TODO: sanity-check fapl IDs? */ + + /* Build the r/w file, w/o file, and the log file paths. + * Output is stored in the associated string pointers. + */ + h5_fixname(FILENAME[11], vfd_config->rw_fapl_id, filename_rw_out, H5FD_SPLITTER_PATH_MAX); + h5_fixname(FILENAME[12], vfd_config->wo_fapl_id, vfd_config->wo_path, H5FD_SPLITTER_PATH_MAX); + h5_fixname_no_suffix(FILENAME[13], vfd_config->wo_fapl_id, vfd_config->log_file_path, H5FD_SPLITTER_PATH_MAX); + + /* Delete any existing files on disk. + */ + HDremove(filename_rw_out); + HDremove(vfd_config->wo_path); + HDremove(vfd_config->log_file_path); + +done: + return ret_value; +} /* end splitter_prepare_file_paths() */ + + +/*------------------------------------------------------------------------- + * Function: splitter_crate_single_file_at + * + * Purpose: Create a file, optionally w/ dataset. + * + * Return: Success: 0 + * Failure: -1 + * + * Description: + * Create a file at the given location with the given FAPL, + * and write data as defined in `data` in a pre-determined location in the file. + * + * If the dataset definition pointer is NULL, no data is written + * to the file. + * + * Will always overwrite an existing file with the given name/path. + * + *------------------------------------------------------------------------- + */ +static int +splitter_create_single_file_at( + const char *filename, + hid_t fapl_id, + const struct splitter_dataset_def *data) +{ + hid_t file_id = H5I_INVALID_HID; + hid_t space_id = H5I_INVALID_HID; + hid_t dset_id = H5I_INVALID_HID; + int ret_value = 0; + + if (filename == NULL || *filename == '\0') { + SPLITTER_TEST_FAULT("filename is invalid\n"); + } + /* TODO: sanity-check fapl id? */ + + file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + if (file_id < 0) { + SPLITTER_TEST_FAULT("can't create file\n"); + } + + if (data) { + /* TODO: sanity-check data, if it exists? */ + space_id = H5Screate_simple(data->n_dims, data->dims, NULL); + if (space_id < 0) { + SPLITTER_TEST_FAULT("can't create dataspace\n"); + } + + dset_id = H5Dcreate2( + file_id, + data->dset_name, + data->mem_type_id, + space_id, + H5P_DEFAULT, + H5P_DEFAULT, + H5P_DEFAULT); + if (dset_id < 0) { + SPLITTER_TEST_FAULT("can't create dataset\n"); + } + + if (H5Dwrite(dset_id, data->mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, data->buf) < 0) { + SPLITTER_TEST_FAULT("can't write data to dataset\n"); + } + + if (H5Dclose(dset_id) < 0) { + SPLITTER_TEST_FAULT("can't close dset\n"); + } + if (H5Sclose(space_id) < 0) { + SPLITTER_TEST_FAULT("can't close space\n"); + } + } /* end if data definition is provided */ + + if (H5Fclose(file_id) < 0) { + SPLITTER_TEST_FAULT("can't close file\n"); + } + +done: + if (ret_value < 0) { + H5E_BEGIN_TRY { + H5Dclose(dset_id); + H5Sclose(space_id); + H5Fclose(file_id); + } H5E_END_TRY; + } /* end if error */ + return ret_value; +} /* end splitter_create_single_file_at() */ + + +/*------------------------------------------------------------------------- + * Function: splitter_compare_expected_data + * + * Purpose: Compare data within a predermined dataset. + * + * Return: Success: 0 + * Failure: -1 + * + * Description: Read data from the file at a predetermined location, and + * compare its contents byte-for-byte with that expected in + * the `data` definition structure. + * + *------------------------------------------------------------------------- + */ +static int +splitter_compare_expected_data(hid_t file_id, + const struct splitter_dataset_def *data) +{ + hid_t dset_id = H5I_INVALID_HID; + int buf[SPLITTER_SIZE][SPLITTER_SIZE]; + int expected[SPLITTER_SIZE][SPLITTER_SIZE]; + size_t i = 0; + size_t j = 0; + int ret_value = 0; + + if (sizeof((void *)buf) != sizeof(data->buf)) { + SPLITTER_TEST_FAULT("invariant size of expected data does not match that received!\n"); + } + HDmemcpy(expected, data->buf, sizeof(expected)); + + dset_id = H5Dopen2(file_id, data->dset_name, H5P_DEFAULT); + if (dset_id < 0) { + SPLITTER_TEST_FAULT("can't open dataset\n"); + } + + if (H5Dread(dset_id, data->mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, (void *)buf) < 0) { + SPLITTER_TEST_FAULT("can't read dataset\n"); + } + + for (i=0; i < SPLITTER_SIZE; i++) { + for (j=0; j < SPLITTER_SIZE; j++) { + if (buf[i][j] != expected[i][j]) { + SPLITTER_TEST_FAULT("mismatch in expected data\n"); + } + } + } + + if (H5Dclose(dset_id) < 0) { + SPLITTER_TEST_FAULT("can't close dataset\n"); + } + +done: + if (ret_value < 0) { + H5E_BEGIN_TRY { + H5Dclose(dset_id); + } H5E_END_TRY; + } + return ret_value; +} /* end splitter_compare_expected_data() */ + + +/*------------------------------------------------------------------------- + * Function: splitter_tentative_open_test() + * + * Purpose: Verifies Splitter behavior with "tentative" H5F_open. + * + * Return: Success: 0 + * Failure: -1 + * + * Description: + * H5F_open() has a two-stage opening process when given a + * Read/Write access flag -- first it performs a "tentative + * open", where it checks to see whether files already exist + * on the system, done in such a way as to not "alter its state" + * (i.e., truncate). + * This can cause problems with the Splitter VFD, as the + * file on the R/W channel might exist already, but that on the + * W/O channel will not, and vice-versa. + * + * This test exists to verify that in any event, files will be + * created as required. + * + *------------------------------------------------------------------------- + */ +static int +splitter_tentative_open_test(hid_t child_fapl_id) +{ + const char *filename_tmp = "splitter_tmp.h5"; + char *filename_rw = NULL; + H5FD_splitter_vfd_config_t *vfd_config = NULL; + hid_t fapl_id = H5I_INVALID_HID; + hid_t file_id = H5I_INVALID_HID; + int buf[SPLITTER_SIZE][SPLITTER_SIZE]; /* for comparison */ + hsize_t dims[2] = { SPLITTER_SIZE, SPLITTER_SIZE }; /* for comparison */ + int i = 0; /* for comparison */ + int j = 0; /* for comparison */ + struct splitter_dataset_def data; /* for comparison */ + int ret_value = 0; + + if (NULL == (vfd_config = HDcalloc(1, sizeof(H5FD_splitter_vfd_config_t)))) + SPLITTER_TEST_FAULT("memory allocation for vfd_config struct failed"); + if (NULL == (filename_rw = HDcalloc(H5FD_SPLITTER_PATH_MAX + 1, sizeof(char)))) + SPLITTER_TEST_FAULT("memory allocation for filename_rw string failed"); + + /* pre-fill data buffer to write */ + for (i=0; i < SPLITTER_SIZE; i++) { + for (j=0; j < SPLITTER_SIZE; j++) { + buf[i][j] = i*100+j; + } + } + + /* Dataset info */ + data.buf = (void *)buf; + data.mem_type_id = H5T_NATIVE_INT; + data.dims = dims; + data.n_dims = 2; + data.dset_name = SPLITTER_DATASET_NAME; + + vfd_config->magic = H5FD_SPLITTER_MAGIC; + vfd_config->version = H5FD_CURR_SPLITTER_VFD_CONFIG_VERSION; + vfd_config->ignore_wo_errs = FALSE; + vfd_config->rw_fapl_id = child_fapl_id; + vfd_config->wo_fapl_id = child_fapl_id; + + if (splitter_prepare_file_paths(vfd_config, filename_rw) < 0) { + SPLITTER_TEST_FAULT("can't prepare splitter file paths\n"); + } + + /* Create a new fapl to use the SPLITTER file driver */ + if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) == H5I_INVALID_HID) { + SPLITTER_TEST_FAULT("can't create FAPL ID\n"); + } + if (H5Pset_fapl_splitter(fapl_id, vfd_config) < 0) { + SPLITTER_TEST_FAULT("can't set splitter FAPL\n"); + } + if (H5Pget_driver(fapl_id) != H5FD_SPLITTER) { + SPLITTER_TEST_FAULT("set FAPL not SPLITTER\n"); + } + + /* Create instance of file on disk. + * Will be copied verbatim as needed, to avoid issues where differences in + * the creation time would befoul comparisons. + */ + if (splitter_create_single_file_at(filename_tmp, child_fapl_id, &data) < 0) { + SPLITTER_TEST_FAULT("can't write W/O file\n"); + } + + /* + * H5Fopen() with RDWR access. + * Neither file exist already + * Should fail. + */ + + H5E_BEGIN_TRY { + file_id = H5Fopen(filename_rw, H5F_ACC_RDWR, fapl_id); + } H5E_END_TRY; + if (file_id != H5I_INVALID_HID) { + SPLITTER_TEST_FAULT("open with both nonexistent files unexpectedly succeeded\n"); + } + if (file_exists(filename_rw, child_fapl_id)) { + SPLITTER_TEST_FAULT("R/W file unexpectedly created\n"); + } + if (file_exists(vfd_config->wo_path, child_fapl_id)) { + SPLITTER_TEST_FAULT("W/O file unexpectedly created\n"); + } + + /* + * H5Fopen() with RDWR access. + * Only W/O file present. + * Should fail. + */ + + if (h5_duplicate_file_by_bytes(filename_tmp, vfd_config->wo_path) < 0) { + SPLITTER_TEST_FAULT("Can't create W/O file copy.\n"); + } + H5E_BEGIN_TRY { + file_id = H5Fopen(filename_rw, H5F_ACC_RDWR, fapl_id); + } H5E_END_TRY; + if (file_id != H5I_INVALID_HID) { + SPLITTER_TEST_FAULT("open with nonexistent R/W file unexpectedly succeeded\n"); + } + if (file_exists(filename_rw, child_fapl_id)) { + SPLITTER_TEST_FAULT("R/W file unexpectedly created\n"); + } + if (!file_exists(vfd_config->wo_path, child_fapl_id)) { + SPLITTER_TEST_FAULT("W/O file mysteriously disappeared\n"); + } + HDremove(vfd_config->wo_path); + if (file_exists(vfd_config->wo_path, child_fapl_id)) { + SPLITTER_TEST_FAULT("failed to remove W/O file\n"); + } + + /* + * H5Fopen() with RDWR access. + * Only R/W file present. + * Should fail. + */ + + if (h5_duplicate_file_by_bytes(filename_tmp, filename_rw) < 0) { + SPLITTER_TEST_FAULT("Can't create R/W file copy.\n"); + } + H5E_BEGIN_TRY { + file_id = H5Fopen(filename_rw, H5F_ACC_RDWR, fapl_id); + } H5E_END_TRY; + if (file_id != H5I_INVALID_HID) { + SPLITTER_TEST_FAULT("open with nonexistent W/O unexpectedly succeeded\n"); + } + if (!file_exists(filename_rw, child_fapl_id)) { + SPLITTER_TEST_FAULT("R/W file mysteriously disappeared\n"); + } + if (file_exists(vfd_config->wo_path, child_fapl_id)) { + SPLITTER_TEST_FAULT("W/O file unexpectedly created\n"); + } + + /* + * H5Fopen() with RDWR access. + * Both files present. + */ + + if (h5_duplicate_file_by_bytes(filename_tmp, vfd_config->wo_path) < 0) { + SPLITTER_TEST_FAULT("Can't create W/O file copy.\n"); + } + file_id = H5Fopen(filename_rw, H5F_ACC_RDWR, fapl_id); + if (file_id == H5I_INVALID_HID) { + SPLITTER_TEST_FAULT("file-open failed with both present\n"); + } + /* Open successful; close file then inspect presence again */ + if (H5Fclose(file_id) < 0) { + SPLITTER_TEST_FAULT("can't close file ID\n"); + } + if (!file_exists(filename_rw, child_fapl_id)) { + SPLITTER_TEST_FAULT("R/W file mysteriously disappared\n"); + } + if (!file_exists(vfd_config->wo_path, child_fapl_id)) { + SPLITTER_TEST_FAULT("W/O file mysteriously disappeared\n"); + } + + /* + * H5Fcreate() with TRUNC access. + * Both files present. + */ + + file_id = H5Fcreate(filename_rw, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + if (file_id == H5I_INVALID_HID) { + SPLITTER_TEST_FAULT("file-open failed with both present\n"); + } + /* Open successful; close file then inspect presence again */ + if (H5Fclose(file_id) < 0) { + SPLITTER_TEST_FAULT("can't close file ID\n"); + } + if (!file_exists(filename_rw, child_fapl_id)) { + SPLITTER_TEST_FAULT("R/W file mysteriously disappared\n"); + } + if (!file_exists(vfd_config->wo_path, child_fapl_id)) { + SPLITTER_TEST_FAULT("W/O file mysteriously disappeared\n"); + } + if (h5_compare_file_bytes(filename_rw, vfd_config->wo_path) < 0) { + SPLITTER_TEST_FAULT("files are not byte-for-byte equivalent\n"); + } + HDremove(filename_rw); + HDremove(vfd_config->wo_path); + + /* + * H5Fcreate() with TRUNC access. + * R/W already exists. + */ + + if (h5_duplicate_file_by_bytes(filename_tmp, filename_rw) < 0) { + SPLITTER_TEST_FAULT("Can't create R/W file copy.\n"); + } + if (file_exists(vfd_config->wo_path, child_fapl_id)) { + SPLITTER_TEST_FAULT("failed to remove W/O file\n"); + } + file_id = H5Fcreate(filename_rw, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + if (file_id == H5I_INVALID_HID) { + SPLITTER_TEST_FAULT("file-open failed with both present\n"); + } + /* Open successful; close file then inspect presence again */ + if (H5Fclose(file_id) < 0) { + SPLITTER_TEST_FAULT("can't close file ID\n"); + } + if (!file_exists(filename_rw, child_fapl_id)) { + SPLITTER_TEST_FAULT("R/W file mysteriously disappared\n"); + } + if (!file_exists(vfd_config->wo_path, child_fapl_id)) { + SPLITTER_TEST_FAULT("W/O file mysteriously disappeared\n"); + } + if (h5_compare_file_bytes(filename_rw, vfd_config->wo_path) < 0) { + SPLITTER_TEST_FAULT("files are not byte-for-byte equivalent\n"); + } + HDremove(filename_rw); + HDremove(vfd_config->wo_path); + + /* + * H5Fcreate() with TRUNC access. + * Only W/O present. + */ + + if (h5_duplicate_file_by_bytes(filename_tmp, vfd_config->wo_path) < 0) { + SPLITTER_TEST_FAULT("Can't create W/O file copy.\n"); + } + if (file_exists(filename_rw, child_fapl_id)) { + SPLITTER_TEST_FAULT("failed to remove R/W file\n"); + } + file_id = H5Fcreate(filename_rw, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + if (file_id == H5I_INVALID_HID) { + SPLITTER_TEST_FAULT("file-open failed with both present\n"); + } + /* Open successful; close file then inspect presence again */ + if (H5Fclose(file_id) < 0) { + SPLITTER_TEST_FAULT("can't close file ID\n"); + } + if (!file_exists(filename_rw, child_fapl_id)) { + SPLITTER_TEST_FAULT("R/W file mysteriously disappared\n"); + } + if (!file_exists(vfd_config->wo_path, child_fapl_id)) { + SPLITTER_TEST_FAULT("W/O file mysteriously disappeared\n"); + } + if (h5_compare_file_bytes(filename_rw, vfd_config->wo_path) < 0) { + SPLITTER_TEST_FAULT("files are not byte-for-byte equivalent\n"); + } + HDremove(filename_rw); + HDremove(vfd_config->wo_path); + + /* H5Fcreate with both files absent is tested elsewhere */ + + /* + * Cleanup + */ + + if (H5Pclose(fapl_id) < 0) { + SPLITTER_TEST_FAULT("can't close splitter FAPL ID\n"); + } + +done: + if (ret_value < 0) { + H5E_BEGIN_TRY { + H5Pclose(fapl_id); + H5Fclose(file_id); + } H5E_END_TRY; + } + + HDfree(vfd_config); + HDfree(filename_rw); + + return ret_value; +} /* end splitter_tentative_open_test() */ + + +/*------------------------------------------------------------------------- + * Function: file_exists() + * + * Purpose: Determine whether a file exists on-system + * + * Return: Non-zero (1) if it exists (H5Fopen successful), + * zero (0) if absent (cannot be opened). + * + * Description: Attempt H5Fopen with the given FAPL ID and RDONLY access flag. + * + *------------------------------------------------------------------------- + */ +static int +file_exists(const char *filename, hid_t fapl_id) +{ + hid_t file_id = H5I_INVALID_HID; + int ret_value = 0; + + H5E_BEGIN_TRY { + file_id = H5Fopen(filename, H5F_ACC_RDONLY, fapl_id); + } H5E_END_TRY; + if (file_id != H5I_INVALID_HID) { + ret_value = 1; + if (H5Fclose(file_id) < 0) { + FAIL_PUTS_ERROR("can't close file ID\n"); + } + } + + return ret_value; + +error: + H5E_BEGIN_TRY { + H5Fclose(file_id); + } H5E_END_TRY; + return ret_value; +} /* end file_exists() */ + + +/*------------------------------------------------------------------------- + * Function: test_splitter + * + * Purpose: Tests the Splitter VFD + * + * Return: Success: 0 + * Failure: -1 + * + * Description: + * This test function uses the Splitter VFD to produce a r/w + * file and a w/o file. It will verify that the two files + * are identical. + * + *------------------------------------------------------------------------- + */ +static herr_t +test_splitter(void) +{ + int buf[SPLITTER_SIZE][SPLITTER_SIZE]; + hsize_t dims[2] = { SPLITTER_SIZE, SPLITTER_SIZE }; + hid_t child_fapl_id = H5I_INVALID_HID; + int i = 0; + int j = 0; + struct splitter_dataset_def data; + + TESTING("SPLITTER file driver"); + + /* pre-fill data buffer to write */ + for (i=0; i < SPLITTER_SIZE; i++) { + for (j=0; j < SPLITTER_SIZE; j++) { + buf[i][j] = i*100+j; + } + } + + /* Dataset info */ + data.buf = (void *)buf; + data.mem_type_id = H5T_NATIVE_INT; + data.dims = dims; + data.n_dims = 2; + data.dset_name = SPLITTER_DATASET_NAME; + + /* Stand-in for manual FAPL creation + * Enables verification with arbitrary VFDs via `make check-vfd` + */ + child_fapl_id = h5_fileaccess(); + if (child_fapl_id < 0) { + TEST_ERROR; + } + + if (!driver_is_splitter_compatible(child_fapl_id)) { + SKIPPED(); + HDprintf(" given driver is not Splitter W/O compatible.\n"); + return 0; + } + + /* Test Read-Only access, including when a file on the W/O channel + * does not exist. + */ + if (splitter_RO_test(&data, child_fapl_id) < 0) { + TEST_ERROR; + } + + /* Test opening of files when the W/O channel does not exist. + */ + if (splitter_tentative_open_test(child_fapl_id) < 0) { + TEST_ERROR; + } + + /* Test file creation, utilizing different child FAPLs (default vs. + * specified), logfile, and Write Channel error ignoring behavior. + */ + for (i=0; i < 4; i++) { + hbool_t ignore_wo_errors = (i & 1) ? TRUE : FALSE; + hbool_t provide_logfile_path = (i & 2) ? TRUE : FALSE; + hid_t child_fapl_ids[2] = { H5P_DEFAULT, H5P_DEFAULT }; + + /* Test child driver definition/default combination */ + for (j=0; j < 4; j++) { + + child_fapl_ids[0] = (j & 1) ? child_fapl_id : H5P_DEFAULT; + child_fapl_ids[1] = (j & 2) ? child_fapl_id : H5P_DEFAULT; + + if (run_splitter_test(&data, ignore_wo_errors, provide_logfile_path, child_fapl_ids) < 0) { + TEST_ERROR; + } + + } /* end for child fapl definition/pairing */ + + } /* end for behavior-flag loops */ + +/* TODO: SWMR open? */ +/* Concurrent opens with both drivers using the Splitter */ + + if (H5Pclose(child_fapl_id) == FAIL) { + TEST_ERROR; + } + + PASSED(); + return 0; + +error: + if (child_fapl_id != H5I_INVALID_HID) + H5Pclose(child_fapl_id); + + return -1; +} /* end test_splitter() */ + +#undef SPLITTER_TEST_FAULT + + /*------------------------------------------------------------------------- * Function: main * @@ -2085,18 +3343,20 @@ main(void) nerrors += test_direct() < 0 ? 1 : 0; nerrors += test_family() < 0 ? 1 : 0; nerrors += test_family_compat() < 0 ? 1 : 0; + nerrors += test_family_member_fapl() < 0 ? 1 : 0; nerrors += test_multi() < 0 ? 1 : 0; nerrors += test_multi_compat() < 0 ? 1 : 0; nerrors += test_log() < 0 ? 1 : 0; nerrors += test_stdio() < 0 ? 1 : 0; nerrors += test_windows() < 0 ? 1 : 0; nerrors += test_ros3() < 0 ? 1 : 0; + nerrors += test_splitter() < 0 ? 1 : 0; if(nerrors) { HDprintf("***** %d Virtual File Driver TEST%s FAILED! *****\n", nerrors, nerrors > 1 ? "S" : ""); return EXIT_FAILURE; - } /* end if */ + } HDprintf("All Virtual File Driver tests passed.\n"); |