summaryrefslogtreecommitdiffstats
path: root/test/API/titerate.c
diff options
context:
space:
mode:
authorjhendersonHDF <jhenderson@hdfgroup.org>2023-05-02 19:52:39 (GMT)
committerGitHub <noreply@github.com>2023-05-02 19:52:39 (GMT)
commitf8a1b3ceec485829ccdd3034ef2be68029f1a66e (patch)
tree5563ca3059b8cbda43f7f1e0ffedf7985f71a4bc /test/API/titerate.c
parent41fd8e66a9f837a1adf36a0253e29440d82ff522 (diff)
downloadhdf5-f8a1b3ceec485829ccdd3034ef2be68029f1a66e.zip
hdf5-f8a1b3ceec485829ccdd3034ef2be68029f1a66e.tar.gz
hdf5-f8a1b3ceec485829ccdd3034ef2be68029f1a66e.tar.bz2
Add initial version of HDF5 API tests (#2877)
Diffstat (limited to 'test/API/titerate.c')
-rw-r--r--test/API/titerate.c1263
1 files changed, 1263 insertions, 0 deletions
diff --git a/test/API/titerate.c b/test/API/titerate.c
new file mode 100644
index 0000000..6cbebbd
--- /dev/null
+++ b/test/API/titerate.c
@@ -0,0 +1,1263 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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://www.hdfgroup.org/licenses. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/***********************************************************
+ *
+ * Test program: titerate
+ *
+ * Test the Group & Attribute functionality
+ *
+ *************************************************************/
+
+#include "testhdf5.h"
+/* #include "H5srcdir.h" */
+
+#define DATAFILE "titerate.h5"
+
+/* Number of datasets for group iteration test */
+#define NDATASETS 50
+
+/* Number of attributes for attribute iteration test */
+#define NATTR 50
+
+/* Number of groups for second group iteration test */
+#define ITER_NGROUPS 150
+
+/* General maximum length of names used */
+#define NAMELEN 80
+
+/* 1-D dataset with fixed dimensions */
+#define SPACE1_RANK 1
+#define SPACE1_DIM1 4
+
+typedef enum { RET_ZERO, RET_TWO, RET_CHANGE, RET_CHANGE2 } iter_enum;
+
+/* Custom group iteration callback data */
+typedef struct {
+ char name[NAMELEN]; /* The name of the object */
+ H5O_type_t type; /* The type of the object */
+ iter_enum command; /* The type of return value */
+} iter_info;
+
+/* Definition for test_corrupted_attnamelen */
+#define CORRUPTED_ATNAMELEN_FILE "memleak_H5O_dtype_decode_helper_H5Odtype.h5"
+#define DSET_NAME "image"
+typedef struct searched_err_t {
+ char message[256];
+ hbool_t found;
+} searched_err_t;
+#if 0
+/* Call back function for test_corrupted_attnamelen */
+static int find_err_msg_cb(unsigned n, const H5E_error2_t *err_desc, void *_client_data);
+#endif
+/* Local functions */
+int iter_strcmp(const void *s1, const void *s2);
+int iter_strcmp2(const void *s1, const void *s2);
+#ifndef NO_ITERATION_RESTART
+static herr_t liter_cb(hid_t group, const char *name, const H5L_info2_t *info, void *op_data);
+static herr_t liter_cb2(hid_t group, const char *name, const H5L_info2_t *info, void *op_data);
+#endif
+herr_t aiter_cb(hid_t group, const char *name, const H5A_info_t *ainfo, void *op_data);
+
+/****************************************************************
+**
+** iter_strcmp(): String comparison routine for qsort
+**
+****************************************************************/
+H5_ATTR_PURE int
+iter_strcmp(const void *s1, const void *s2)
+{
+ return (HDstrcmp(*(const char *const *)s1, *(const char *const *)s2));
+}
+
+/****************************************************************
+**
+** liter_cb(): Custom link iteration callback routine.
+**
+****************************************************************/
+#ifndef NO_ITERATION_RESTART
+static herr_t
+liter_cb(hid_t H5_ATTR_UNUSED group, const char *name, const H5L_info2_t H5_ATTR_UNUSED *link_info,
+ void *op_data)
+{
+ iter_info *info = (iter_info *)op_data;
+ static int count = 0;
+ static int count2 = 0;
+
+ HDstrcpy(info->name, name);
+
+ switch (info->command) {
+ case RET_ZERO:
+ return (0);
+
+ case RET_TWO:
+ return (2);
+
+ case RET_CHANGE:
+ count++;
+ return (count > 10 ? 1 : 0);
+
+ case RET_CHANGE2:
+ count2++;
+ return (count2 > 10 ? 1 : 0);
+
+ default:
+ HDprintf("invalid iteration command");
+ return (-1);
+ } /* end switch */
+} /* end liter_cb() */
+#endif
+
+/****************************************************************
+**
+** test_iter_group(): Test group iteration functionality
+**
+****************************************************************/
+static void
+test_iter_group(hid_t fapl, hbool_t new_format)
+{
+#ifndef NO_ITERATION_RESTART
+ hid_t file; /* File ID */
+ hid_t dataset; /* Dataset ID */
+ hid_t datatype; /* Common datatype ID */
+ hid_t filespace; /* Common dataspace ID */
+ hid_t root_group, grp; /* Root group ID */
+ int i; /* counting variable */
+ hsize_t idx; /* Index in the group */
+ char name[NAMELEN]; /* temporary name buffer */
+ char *lnames[NDATASETS + 2]; /* Names of the links created */
+ char dataset_name[NAMELEN]; /* dataset name */
+ iter_info info; /* Custom iteration information */
+ H5G_info_t ginfo; /* Buffer for querying object's info */
+ herr_t ret; /* Generic return value */
+#else
+ (void)fapl;
+ (void)new_format;
+#endif
+
+ /* Output message about test being performed */
+ MESSAGE(
+ 5, ("Testing Group Iteration Functionality - SKIPPED for now due to no iteration restart support\n"));
+#ifndef NO_ITERATION_RESTART
+ /* Create the test file with the datasets */
+ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ CHECK(file, FAIL, "H5Fcreate");
+
+ /* Test iterating over empty group */
+ info.command = RET_ZERO;
+ idx = 0;
+ ret = H5Literate2(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info);
+ VERIFY(ret, SUCCEED, "H5Literate2");
+
+ datatype = H5Tcopy(H5T_NATIVE_INT);
+ CHECK(datatype, FAIL, "H5Tcopy");
+
+ filespace = H5Screate(H5S_SCALAR);
+ CHECK(filespace, FAIL, "H5Screate");
+
+ for (i = 0; i < NDATASETS; i++) {
+ HDsnprintf(name, sizeof(name), "Dataset %d", i);
+ dataset = H5Dcreate2(file, name, datatype, filespace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dcreate2");
+
+ /* Keep a copy of the dataset names around for later */
+ lnames[i] = HDstrdup(name);
+ CHECK_PTR(lnames[i], "strdup");
+
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+ } /* end for */
+
+ /* Create a group and named datatype under root group for testing */
+ grp = H5Gcreate2(file, "grp", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Gcreate2");
+
+ lnames[NDATASETS] = HDstrdup("grp");
+ CHECK_PTR(lnames[NDATASETS], "strdup");
+
+ ret = H5Tcommit2(file, "dtype", datatype, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Tcommit2");
+
+ lnames[NDATASETS + 1] = HDstrdup("dtype");
+ CHECK_PTR(lnames[NDATASETS], "strdup");
+
+ /* Close everything up */
+ ret = H5Tclose(datatype);
+ CHECK(ret, FAIL, "H5Tclose");
+
+ ret = H5Gclose(grp);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ ret = H5Sclose(filespace);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ ret = H5Fclose(file);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Sort the dataset names */
+ HDqsort(lnames, (size_t)(NDATASETS + 2), sizeof(char *), iter_strcmp);
+
+ /* Iterate through the datasets in the root group in various ways */
+ file = H5Fopen(DATAFILE, H5F_ACC_RDONLY, fapl);
+ CHECK(file, FAIL, "H5Fopen");
+
+ /* These two functions, H5Oget_info_by_idx and H5Lget_name_by_idx, actually
+ * iterate through B-tree for group members in internal library design.
+ */
+ root_group = H5Gopen2(file, "/", H5P_DEFAULT);
+ CHECK(root_group, FAIL, "H5Gopen2");
+
+ ret = H5Gget_info(root_group, &ginfo);
+ CHECK(ret, FAIL, "H5Gget_info");
+ VERIFY(ginfo.nlinks, (NDATASETS + 2), "H5Gget_info");
+
+ for (i = 0; i < (int)ginfo.nlinks; i++) {
+ H5O_info2_t oinfo; /* Object info */
+
+ ret = (herr_t)H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i,
+ dataset_name, (size_t)NAMELEN, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Lget_name_by_idx");
+
+ //! [H5Oget_info_by_idx3_snip]
+
+ ret = H5Oget_info_by_idx3(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, &oinfo,
+ H5O_INFO_BASIC, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Oget_info_by_idx");
+
+ //! [H5Oget_info_by_idx3_snip]
+
+ } /* end for */
+
+ H5E_BEGIN_TRY
+ {
+ ret =
+ (herr_t)H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)(NDATASETS + 3),
+ dataset_name, (size_t)NAMELEN, H5P_DEFAULT);
+ }
+ H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Lget_name_by_idx");
+
+ ret = H5Gclose(root_group);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ /* These two functions, H5Oget_info_by_idx and H5Lget_name_by_idx, actually
+ * iterate through B-tree for group members in internal library design.
+ * (Same as test above, but with the file ID instead of opening the root group)
+ */
+ ret = H5Gget_info(file, &ginfo);
+ CHECK(ret, FAIL, "H5Gget_info");
+ VERIFY(ginfo.nlinks, NDATASETS + 2, "H5Gget_info");
+
+ for (i = 0; i < (int)ginfo.nlinks; i++) {
+ H5O_info2_t oinfo; /* Object info */
+
+ ret = (herr_t)H5Lget_name_by_idx(file, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, dataset_name,
+ (size_t)NAMELEN, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Lget_name_by_idx");
+
+ ret = H5Oget_info_by_idx3(file, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, &oinfo, H5O_INFO_BASIC,
+ H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Oget_info_by_idx3");
+ } /* end for */
+
+ H5E_BEGIN_TRY
+ {
+ ret = (herr_t)H5Lget_name_by_idx(file, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)(NDATASETS + 3),
+ dataset_name, (size_t)NAMELEN, H5P_DEFAULT);
+ }
+ H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Lget_name_by_idx");
+
+ /* Test invalid indices for starting iteration */
+ info.command = RET_ZERO;
+ idx = (hsize_t)-1;
+ H5E_BEGIN_TRY
+ {
+ ret = H5Literate2(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info);
+ }
+ H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Literate2");
+
+ /* Test skipping exactly as many entries as in the group */
+ idx = NDATASETS + 2;
+ H5E_BEGIN_TRY
+ {
+ ret = H5Literate2(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info);
+ }
+ H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Literate2");
+
+ /* Test skipping more entries than are in the group */
+ idx = NDATASETS + 3;
+ H5E_BEGIN_TRY
+ {
+ ret = H5Literate2(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info);
+ }
+ H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Literate2");
+
+ /* Test all objects in group, when callback always returns 0 */
+ info.command = RET_ZERO;
+ idx = 0;
+ if ((ret = H5Literate2(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info)) > 0)
+ TestErrPrintf("Group iteration function didn't return zero correctly!\n");
+
+ /* Test all objects in group, when callback always returns 1 */
+ /* This also tests the "restarting" ability, because the index changes */
+ info.command = RET_TWO;
+ i = 0;
+ idx = 0;
+ memset(info.name, 0, NAMELEN);
+ while ((ret = H5Literate2(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info)) > 0) {
+ /* Verify return value from iterator gets propagated correctly */
+ VERIFY(ret, 2, "H5Literate2");
+
+ /* Increment the number of times "2" is returned */
+ i++;
+
+ /* Verify that the index is the correct value */
+ VERIFY(idx, (hsize_t)i, "H5Literate2");
+ if (idx != (hsize_t)i)
+ break;
+ if (idx > (NDATASETS + 2))
+ TestErrPrintf("Group iteration function walked too far!\n");
+
+ /* Verify that the correct name is retrieved */
+ if (HDstrncmp(info.name, lnames[(size_t)(idx - 1)], NAMELEN) != 0)
+ TestErrPrintf(
+ "Group iteration function didn't return name correctly for link - lnames[%u] = '%s'!\n",
+ (unsigned)(idx - 1), lnames[(size_t)(idx - 1)]);
+ } /* end while */
+ VERIFY(ret, -1, "H5Literate2");
+
+ if (i != (NDATASETS + 2))
+ TestErrPrintf("%u: Group iteration function didn't perform multiple iterations correctly!\n",
+ __LINE__);
+
+ /* Test all objects in group, when callback changes return value */
+ /* This also tests the "restarting" ability, because the index changes */
+ info.command = new_format ? RET_CHANGE2 : RET_CHANGE;
+ i = 0;
+ idx = 0;
+ memset(info.name, 0, NAMELEN);
+ while ((ret = H5Literate2(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info)) >= 0) {
+ /* Verify return value from iterator gets propagated correctly */
+ VERIFY(ret, 1, "H5Literate2");
+
+ /* Increment the number of times "1" is returned */
+ i++;
+
+ /* Verify that the index is the correct value */
+ VERIFY(idx, (hsize_t)(i + 10), "H5Literate2");
+ if (idx != (hsize_t)(i + 10))
+ break;
+ if (idx > (NDATASETS + 2))
+ TestErrPrintf("Group iteration function walked too far!\n");
+
+ /* Verify that the correct name is retrieved */
+ if (HDstrncmp(info.name, lnames[(size_t)(idx - 1)], NAMELEN) != 0)
+ TestErrPrintf(
+ "Group iteration function didn't return name correctly for link - lnames[%u] = '%s'!\n",
+ (unsigned)(idx - 1), lnames[(size_t)(idx - 1)]);
+ } /* end while */
+ VERIFY(ret, -1, "H5Literate2");
+
+ if (i != 42 || idx != 52)
+ TestErrPrintf("%u: Group iteration function didn't perform multiple iterations correctly!\n",
+ __LINE__);
+
+ ret = H5Fclose(file);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Free the dataset names */
+ for (i = 0; i < (NDATASETS + 2); i++)
+ HDfree(lnames[i]);
+#endif
+} /* test_iter_group() */
+
+/****************************************************************
+**
+** aiter_cb(): Custom group iteration callback routine.
+**
+****************************************************************/
+herr_t
+aiter_cb(hid_t H5_ATTR_UNUSED group, const char *name, const H5A_info_t H5_ATTR_UNUSED *ainfo, void *op_data)
+{
+ iter_info *info = (iter_info *)op_data;
+ static int count = 0;
+ static int count2 = 0;
+
+ HDstrcpy(info->name, name);
+
+ switch (info->command) {
+ case RET_ZERO:
+ return (0);
+
+ case RET_TWO:
+ return (2);
+
+ case RET_CHANGE:
+ count++;
+ return (count > 10 ? 1 : 0);
+
+ case RET_CHANGE2:
+ count2++;
+ return (count2 > 10 ? 1 : 0);
+
+ default:
+ HDprintf("invalid iteration command");
+ return (-1);
+ } /* end switch */
+} /* end aiter_cb() */
+
+/****************************************************************
+**
+** test_iter_attr(): Test attribute iteration functionality
+**
+****************************************************************/
+static void
+test_iter_attr(hid_t fapl, hbool_t new_format)
+{
+#ifndef NO_ITERATION_RESTART
+ hid_t file; /* File ID */
+ hid_t dataset; /* Common Dataset ID */
+ hid_t filespace; /* Common dataspace ID */
+ hid_t attribute; /* Attribute ID */
+ int i; /* counting variable */
+ hsize_t idx; /* Index in the attribute list */
+ char name[NAMELEN]; /* temporary name buffer */
+ char *anames[NATTR]; /* Names of the attributes created */
+ iter_info info; /* Custom iteration information */
+ herr_t ret; /* Generic return value */
+#else
+ (void)fapl;
+ (void)new_format;
+#endif
+
+ /* Output message about test being performed */
+ MESSAGE(
+ 5,
+ ("Testing Attribute Iteration Functionality - SKIPPED for no due to no iteration restart support\n"));
+#ifndef NO_ITERATION_RESTART
+ HDmemset(&info, 0, sizeof(iter_info));
+
+ /* Create the test file with the datasets */
+ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ CHECK(file, FAIL, "H5Fcreate");
+
+ filespace = H5Screate(H5S_SCALAR);
+ CHECK(filespace, FAIL, "H5Screate");
+
+ dataset = H5Dcreate2(file, "Dataset", H5T_NATIVE_INT, filespace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dcreate2");
+
+ for (i = 0; i < NATTR; i++) {
+ HDsnprintf(name, sizeof(name), "Attribute %02d", i);
+ attribute = H5Acreate2(dataset, name, H5T_NATIVE_INT, filespace, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(attribute, FAIL, "H5Acreate2");
+
+ /* Keep a copy of the attribute names around for later */
+ anames[i] = HDstrdup(name);
+ CHECK_PTR(anames[i], "strdup");
+
+ ret = H5Aclose(attribute);
+ CHECK(ret, FAIL, "H5Aclose");
+ } /* end for */
+
+ /* Close everything up */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ ret = H5Sclose(filespace);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ ret = H5Fclose(file);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Iterate through the attributes on the dataset in various ways */
+ file = H5Fopen(DATAFILE, H5F_ACC_RDONLY, fapl);
+ CHECK(file, FAIL, "H5Fopen");
+
+ dataset = H5Dopen2(file, "Dataset", H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dopen2");
+
+ /* Test invalid indices for starting iteration */
+ info.command = RET_ZERO;
+
+ /* Test skipping exactly as many attributes as there are */
+ idx = NATTR;
+ H5E_BEGIN_TRY
+ {
+ ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, &idx, aiter_cb, &info);
+ }
+ H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Aiterate2");
+
+ /* Test skipping more attributes than there are */
+ idx = NATTR + 1;
+ H5E_BEGIN_TRY
+ {
+ ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, &idx, aiter_cb, &info);
+ }
+ H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Aiterate2");
+
+ /* Test all attributes on dataset, when callback always returns 0 */
+ info.command = RET_ZERO;
+ idx = 0;
+ if ((ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, &idx, aiter_cb, &info)) > 0)
+ TestErrPrintf("Attribute iteration function didn't return zero correctly!\n");
+
+ /* Test all attributes on dataset, when callback always returns 2 */
+ /* This also tests the "restarting" ability, because the index changes */
+ info.command = RET_TWO;
+ i = 0;
+ idx = 0;
+ while ((ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, &idx, aiter_cb, &info)) > 0) {
+ /* Verify return value from iterator gets propagated correctly */
+ VERIFY(ret, 2, "H5Aiterate2");
+
+ /* Increment the number of times "2" is returned */
+ i++;
+
+ /* Verify that the index is the correct value */
+ VERIFY(idx, (unsigned)i, "H5Aiterate2");
+
+ /* Don't check name when new format is used */
+ if (!new_format) {
+ /* Verify that the correct name is retrieved */
+ if (idx > 0) {
+ if (HDstrcmp(info.name, anames[(size_t)idx - 1]) != 0)
+ TestErrPrintf("%u: Attribute iteration function didn't set names correctly, info.name = "
+ "'%s', anames[%u] = '%s'!\n",
+ __LINE__, info.name, (unsigned)(idx - 1), anames[(size_t)idx - 1]);
+ } /* end if */
+ else
+ TestErrPrintf("%u: 'idx' was not set correctly!\n", __LINE__);
+ } /* end if */
+ } /* end while */
+ VERIFY(ret, -1, "H5Aiterate2");
+ if (i != 50 || idx != 50)
+ TestErrPrintf("%u: Attribute iteration function didn't perform multiple iterations correctly!\n",
+ __LINE__);
+
+ /* Test all attributes on dataset, when callback changes return value */
+ /* This also tests the "restarting" ability, because the index changes */
+ info.command = new_format ? RET_CHANGE2 : RET_CHANGE;
+ i = 0;
+ idx = 0;
+ while ((ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, &idx, aiter_cb, &info)) > 0) {
+ /* Verify return value from iterator gets propagated correctly */
+ VERIFY(ret, 1, "H5Aiterate2");
+
+ /* Increment the number of times "1" is returned */
+ i++;
+
+ /* Verify that the index is the correct value */
+ VERIFY(idx, (unsigned)i + 10, "H5Aiterate2");
+
+ /* Don't check name when new format is used */
+ if (!new_format) {
+ /* Verify that the correct name is retrieved */
+ if (idx > 0) {
+ if (HDstrcmp(info.name, anames[(size_t)idx - 1]) != 0)
+ TestErrPrintf("%u: Attribute iteration function didn't set names correctly, info.name = "
+ "'%s', anames[%u] = '%s'!\n",
+ __LINE__, info.name, (unsigned)(idx - 1), anames[(size_t)idx - 1]);
+ }
+ else
+ TestErrPrintf("%u: 'idx' was not set correctly!\n", __LINE__);
+ } /* end if */
+ } /* end while */
+ VERIFY(ret, -1, "H5Aiterate2");
+ if (i != 40 || idx != 50)
+ TestErrPrintf("%u: Attribute iteration function didn't perform multiple iterations correctly!\n",
+ __LINE__);
+
+ ret = H5Fclose(file);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Free the attribute names */
+ for (i = 0; i < NATTR; i++)
+ HDfree(anames[i]);
+#endif
+} /* test_iter_attr() */
+
+/****************************************************************
+**
+** iter_strcmp2(): String comparison routine for qsort
+**
+****************************************************************/
+H5_ATTR_PURE int
+iter_strcmp2(const void *s1, const void *s2)
+{
+ return (HDstrcmp((const char *)s1, (const char *)s2));
+} /* end iter_strcmp2() */
+
+/****************************************************************
+**
+** liter_cb2(): Custom link iteration callback routine.
+**
+****************************************************************/
+#ifndef NO_ITERATION_RESTART
+static herr_t
+liter_cb2(hid_t loc_id, const char *name, const H5L_info2_t H5_ATTR_UNUSED *link_info, void *opdata)
+{
+ const iter_info *test_info = (const iter_info *)opdata;
+ H5O_info2_t oinfo;
+ herr_t ret; /* Generic return value */
+
+ if (HDstrcmp(name, test_info->name) != 0) {
+ TestErrPrintf("name = '%s', test_info = '%s'\n", name, test_info->name);
+ return (H5_ITER_ERROR);
+ } /* end if */
+
+ /*
+ * Get type of the object and check it.
+ */
+ ret = H5Oget_info_by_name3(loc_id, name, &oinfo, H5O_INFO_BASIC, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Oget_info_by_name3");
+
+ if (test_info->type != oinfo.type) {
+ TestErrPrintf("test_info->type = %d, oinfo.type = %d\n", test_info->type, (int)oinfo.type);
+ return (H5_ITER_ERROR);
+ } /* end if */
+
+ return (H5_ITER_STOP);
+} /* liter_cb2() */
+#endif
+
+/****************************************************************
+**
+** test_iter_group_large(): Test group iteration functionality
+** for groups with large #'s of objects
+**
+****************************************************************/
+static void
+test_iter_group_large(hid_t fapl)
+{
+#ifndef NO_ITERATION_RESTART
+ hid_t file; /* HDF5 File IDs */
+ hid_t dataset; /* Dataset ID */
+ hid_t group; /* Group ID */
+ hid_t sid; /* Dataspace ID */
+ hid_t tid; /* Datatype ID */
+ hsize_t dims[] = {SPACE1_DIM1};
+ herr_t ret; /* Generic return value */
+ char gname[20]; /* Temporary group name */
+ iter_info *names; /* Names of objects in the root group */
+ iter_info *curr_name; /* Pointer to the current name in the root group */
+ int i;
+
+ /* Compound datatype */
+ typedef struct s1_t {
+ unsigned int a;
+ unsigned int b;
+ float c;
+ } s1_t;
+
+ /* Allocate & initialize array */
+ names = (iter_info *)HDcalloc(sizeof(iter_info), (ITER_NGROUPS + 2));
+ CHECK_PTR(names, "HDcalloc");
+#else
+ (void)fapl;
+#endif
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing Large Group Iteration Functionality - SKIPPED for now due to no iteration restart "
+ "support\n"));
+#ifndef NO_ITERATION_RESTART
+ /* Create file */
+ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ CHECK(file, FAIL, "H5Fcreate");
+
+ /* Create dataspace for datasets */
+ sid = H5Screate_simple(SPACE1_RANK, dims, NULL);
+ CHECK(sid, FAIL, "H5Screate_simple");
+
+ /* Create a bunch of groups */
+ for (i = 0; i < ITER_NGROUPS; i++) {
+ HDsnprintf(gname, sizeof(gname), "Group_%d", i);
+
+ /* Add the name to the list of objects in the root group */
+ HDstrcpy(names[i].name, gname);
+ names[i].type = H5O_TYPE_GROUP;
+
+ /* Create a group */
+ group = H5Gcreate2(file, gname, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(group, FAIL, "H5Gcreate2");
+
+ /* Close a group */
+ ret = H5Gclose(group);
+ CHECK(ret, FAIL, "H5Gclose");
+ } /* end for */
+
+ /* Create a dataset */
+ dataset = H5Dcreate2(file, "Dataset1", H5T_STD_U32LE, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dcreate2");
+
+ /* Add the name to the list of objects in the root group */
+ HDstrcpy(names[ITER_NGROUPS].name, "Dataset1");
+ names[ITER_NGROUPS].type = H5O_TYPE_DATASET;
+
+ /* Close Dataset */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Close Dataspace */
+ ret = H5Sclose(sid);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ /* Create a datatype */
+ tid = H5Tcreate(H5T_COMPOUND, sizeof(s1_t));
+ CHECK(tid, FAIL, "H5Tcreate");
+
+ /* Insert fields */
+ ret = H5Tinsert(tid, "a", HOFFSET(s1_t, a), H5T_NATIVE_INT);
+ CHECK(ret, FAIL, "H5Tinsert");
+
+ ret = H5Tinsert(tid, "b", HOFFSET(s1_t, b), H5T_NATIVE_INT);
+ CHECK(ret, FAIL, "H5Tinsert");
+
+ ret = H5Tinsert(tid, "c", HOFFSET(s1_t, c), H5T_NATIVE_FLOAT);
+ CHECK(ret, FAIL, "H5Tinsert");
+
+ /* Save datatype for later */
+ ret = H5Tcommit2(file, "Datatype1", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Tcommit2");
+
+ /* Add the name to the list of objects in the root group */
+ HDstrcpy(names[ITER_NGROUPS + 1].name, "Datatype1");
+ names[ITER_NGROUPS + 1].type = H5O_TYPE_NAMED_DATATYPE;
+
+ /* Close datatype */
+ ret = H5Tclose(tid);
+ CHECK(ret, FAIL, "H5Tclose");
+
+ /* Need to sort the names in the root group, cause that's what the library does */
+ HDqsort(names, (size_t)(ITER_NGROUPS + 2), sizeof(iter_info), iter_strcmp2);
+
+ /* Iterate through the file to see members of the root group */
+ curr_name = &names[0];
+ ret = H5Literate2(file, H5_INDEX_NAME, H5_ITER_INC, NULL, liter_cb2, curr_name);
+ CHECK(ret, FAIL, "H5Literate2");
+ for (i = 1; i < 100; i++) {
+ hsize_t idx = (hsize_t)i;
+
+ curr_name = &names[i];
+ ret = H5Literate2(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb2, curr_name);
+ CHECK(ret, FAIL, "H5Literate2");
+ } /* end for */
+
+ /* Close file */
+ ret = H5Fclose(file);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Release memory */
+ HDfree(names);
+#endif
+} /* test_iterate_group_large() */
+
+/****************************************************************
+**
+** test_grp_memb_funcs(): Test group member information
+** functionality
+**
+****************************************************************/
+static void
+test_grp_memb_funcs(hid_t fapl)
+{
+ hid_t file; /* File ID */
+ hid_t dataset; /* Dataset ID */
+ hid_t datatype; /* Common datatype ID */
+ hid_t filespace; /* Common dataspace ID */
+ hid_t root_group, grp; /* Root group ID */
+ int i; /* counting variable */
+ char name[NAMELEN]; /* temporary name buffer */
+ char *dnames[NDATASETS + 2]; /* Names of the datasets created */
+ char *obj_names[NDATASETS + 2]; /* Names of the objects in group */
+ char dataset_name[NAMELEN]; /* dataset name */
+ ssize_t name_len; /* Length of object's name */
+ H5G_info_t ginfo; /* Buffer for querying object's info */
+ herr_t ret = SUCCEED; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing Group Member Information Functionality\n"));
+
+ /* Create the test file with the datasets */
+ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ CHECK(file, FAIL, "H5Fcreate");
+
+ datatype = H5Tcopy(H5T_NATIVE_INT);
+ CHECK(datatype, FAIL, "H5Tcopy");
+
+ filespace = H5Screate(H5S_SCALAR);
+ CHECK(filespace, FAIL, "H5Screate");
+
+ for (i = 0; i < NDATASETS; i++) {
+ HDsnprintf(name, sizeof(name), "Dataset %d", i);
+ dataset = H5Dcreate2(file, name, datatype, filespace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dcreate2");
+
+ /* Keep a copy of the dataset names around for later */
+ dnames[i] = HDstrdup(name);
+ CHECK_PTR(dnames[i], "strdup");
+
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+ } /* end for */
+
+ /* Create a group and named datatype under root group for testing */
+ grp = H5Gcreate2(file, "grp", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Gcreate2");
+
+ dnames[NDATASETS] = HDstrdup("grp");
+ CHECK_PTR(dnames[NDATASETS], "strdup");
+
+ ret = H5Tcommit2(file, "dtype", datatype, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Tcommit2");
+
+ dnames[NDATASETS + 1] = HDstrdup("dtype");
+ CHECK_PTR(dnames[NDATASETS], "strdup");
+
+ /* Close everything up */
+ ret = H5Tclose(datatype);
+ CHECK(ret, FAIL, "H5Tclose");
+
+ ret = H5Gclose(grp);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ ret = H5Sclose(filespace);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ ret = H5Fclose(file);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Sort the dataset names */
+ HDqsort(dnames, (size_t)(NDATASETS + 2), sizeof(char *), iter_strcmp);
+
+ /* Iterate through the datasets in the root group in various ways */
+ file = H5Fopen(DATAFILE, H5F_ACC_RDONLY, fapl);
+ CHECK(file, FAIL, "H5Fopen");
+
+ /* These two functions, H5Oget_info_by_idx and H5Lget_name_by_idx, actually
+ * iterate through B-tree for group members in internal library design.
+ */
+ root_group = H5Gopen2(file, "/", H5P_DEFAULT);
+ CHECK(root_group, FAIL, "H5Gopen2");
+
+ ret = H5Gget_info(root_group, &ginfo);
+ CHECK(ret, FAIL, "H5Gget_info");
+ VERIFY(ginfo.nlinks, (NDATASETS + 2), "H5Gget_info");
+
+ for (i = 0; i < (int)ginfo.nlinks; i++) {
+ H5O_info2_t oinfo; /* Object info */
+
+ /* Test with NULL for name, to query length */
+ name_len = H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, NULL,
+ (size_t)NAMELEN, H5P_DEFAULT);
+ CHECK(name_len, FAIL, "H5Lget_name_by_idx");
+
+ ret = (herr_t)H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i,
+ dataset_name, (size_t)(name_len + 1), H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Lget_name_by_idx");
+
+ /* Double-check that the length is the same */
+ VERIFY(ret, name_len, "H5Lget_name_by_idx");
+
+ /* Keep a copy of the dataset names around for later */
+ obj_names[i] = HDstrdup(dataset_name);
+ CHECK_PTR(obj_names[i], "strdup");
+
+ ret = H5Oget_info_by_idx3(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, &oinfo,
+ H5O_INFO_BASIC, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Oget_info_by_idx3");
+
+ if (!HDstrcmp(dataset_name, "grp"))
+ VERIFY(oinfo.type, H5O_TYPE_GROUP, "H5Lget_name_by_idx");
+ if (!HDstrcmp(dataset_name, "dtype"))
+ VERIFY(oinfo.type, H5O_TYPE_NAMED_DATATYPE, "H5Lget_name_by_idx");
+ if (!HDstrncmp(dataset_name, "Dataset", (size_t)7))
+ VERIFY(oinfo.type, H5O_TYPE_DATASET, "H5Lget_name_by_idx");
+ } /* end for */
+
+ H5E_BEGIN_TRY
+ {
+ ret =
+ (herr_t)H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)(NDATASETS + 3),
+ dataset_name, (size_t)NAMELEN, H5P_DEFAULT);
+ }
+ H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Lget_name_by_idx");
+
+ /* Sort the dataset names */
+ HDqsort(obj_names, (size_t)(NDATASETS + 2), sizeof(char *), iter_strcmp);
+
+ /* Compare object names */
+ for (i = 0; i < (int)ginfo.nlinks; i++) {
+ ret = HDstrcmp(dnames[i], obj_names[i]);
+ VERIFY(ret, 0, "HDstrcmp");
+ } /* end for */
+
+ ret = H5Gclose(root_group);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ ret = H5Fclose(file);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Free the dataset names */
+ for (i = 0; i < (NDATASETS + 2); i++) {
+ HDfree(dnames[i]);
+ HDfree(obj_names[i]);
+ } /* end for */
+} /* test_grp_memb_funcs() */
+
+/****************************************************************
+**
+** test_links(): Test soft and hard link iteration
+**
+****************************************************************/
+static void
+test_links(hid_t fapl)
+{
+ hid_t file; /* File ID */
+ char obj_name[NAMELEN]; /* Names of the object in group */
+ ssize_t name_len; /* Length of object's name */
+ hid_t gid, gid1;
+ H5G_info_t ginfo; /* Buffer for querying object's info */
+ hsize_t i;
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing Soft and Hard Link Iteration Functionality\n"));
+
+ /* Create the test file with the datasets */
+ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ CHECK(file, FAIL, "H5Fcreate");
+
+ /* create groups */
+ gid = H5Gcreate2(file, "/g1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(gid, FAIL, "H5Gcreate2");
+
+ gid1 = H5Gcreate2(file, "/g1/g1.1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(gid1, FAIL, "H5Gcreate2");
+
+ /* create soft and hard links to the group "/g1". */
+ ret = H5Lcreate_soft("something", gid, "softlink", H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Lcreate_soft");
+
+ ret = H5Lcreate_hard(gid, "/g1", H5L_SAME_LOC, "hardlink", H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Lcreate_hard");
+
+ ret = H5Gget_info(gid, &ginfo);
+ CHECK(ret, FAIL, "H5Gget_info");
+ VERIFY(ginfo.nlinks, 3, "H5Gget_info");
+
+ /* Test these two functions, H5Oget_info_by_idx and H5Lget_name_by_idx */
+ for (i = 0; i < ginfo.nlinks; i++) {
+ H5O_info2_t oinfo; /* Object info */
+ H5L_info2_t linfo; /* Link info */
+
+ /* Get link name */
+ name_len = H5Lget_name_by_idx(gid, ".", H5_INDEX_NAME, H5_ITER_INC, i, obj_name, (size_t)NAMELEN,
+ H5P_DEFAULT);
+ CHECK(name_len, FAIL, "H5Lget_name_by_idx");
+
+ /* Get link type */
+ ret = H5Lget_info_by_idx2(gid, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, &linfo, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Lget_info_by_idx2");
+
+ /* Get object type */
+ if (linfo.type == H5L_TYPE_HARD) {
+ ret = H5Oget_info_by_idx3(gid, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, &oinfo,
+ H5O_INFO_BASIC, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Oget_info_by_idx3");
+ } /* end if */
+
+ if (!HDstrcmp(obj_name, "g1.1"))
+ VERIFY(oinfo.type, H5O_TYPE_GROUP, "H5Lget_name_by_idx");
+ else if (!HDstrcmp(obj_name, "hardlink"))
+ VERIFY(oinfo.type, H5O_TYPE_GROUP, "H5Lget_name_by_idx");
+ else if (!HDstrcmp(obj_name, "softlink"))
+ VERIFY(linfo.type, H5L_TYPE_SOFT, "H5Lget_name_by_idx");
+ else
+ ERROR("unknown object name");
+ } /* end for */
+
+ ret = H5Gclose(gid);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ ret = H5Gclose(gid1);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ ret = H5Fclose(file);
+ CHECK(ret, FAIL, "H5Fclose");
+} /* test_links() */
+
+/*-------------------------------------------------------------------------
+ * Function: find_err_msg_cb
+ *
+ * Purpose: Callback function to find the given error message.
+ * Helper function for test_corrupted_attnamelen().
+ *
+ * Return: H5_ITER_STOP when the message is found
+ * H5_ITER_CONT, otherwise
+ *
+ *-------------------------------------------------------------------------
+ */
+#if 0
+static int
+find_err_msg_cb(unsigned H5_ATTR_UNUSED n, const H5E_error2_t *err_desc, void *_client_data)
+{
+ int status = H5_ITER_CONT;
+ searched_err_t *searched_err = (searched_err_t *)_client_data;
+
+ if (searched_err == NULL)
+ return H5_ITER_ERROR;
+
+ /* If the searched error message is found, stop the iteration */
+ if (err_desc->desc != NULL && HDstrcmp(err_desc->desc, searched_err->message) == 0) {
+ searched_err->found = TRUE;
+ status = H5_ITER_STOP;
+ }
+
+ return status;
+} /* end find_err_msg_cb() */
+#endif
+
+/**************************************************************************
+**
+** test_corrupted_attnamelen(): Test the fix for the JIRA issue HDFFV-10588,
+** where corrupted attribute's name length can be
+** detected and invalid read can be avoided.
+**
+**************************************************************************/
+#if 0
+static void
+test_corrupted_attnamelen(void)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t did = -1; /* Dataset ID */
+ searched_err_t err_caught; /* Data to be passed to callback func */
+ int err_status; /* Status returned by H5Aiterate2 */
+ herr_t ret; /* Return value */
+ hbool_t driver_is_default_compatible;
+ const char *testfile = H5_get_srcdir_filename(CORRUPTED_ATNAMELEN_FILE); /* Corrected test file name */
+
+ const char *err_message = "attribute name has different length than stored length";
+ /* the error message produced when the failure occurs */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing the Handling of Corrupted Attribute's Name Length\n"));
+
+ ret = h5_driver_is_default_vfd_compatible(H5P_DEFAULT, &driver_is_default_compatible);
+ CHECK(ret, FAIL, "h5_driver_is_default_vfd_compatible");
+
+ if (!driver_is_default_compatible) {
+ HDprintf("-- SKIPPED --\n");
+ return;
+ }
+
+ fid = H5Fopen(testfile, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Open the dataset */
+ did = H5Dopen2(fid, DSET_NAME, H5P_DEFAULT);
+ CHECK(did, FAIL, "H5Dopen2");
+
+ /* Call H5Aiterate2 to trigger the failure in HDFFV-10588. Failure should
+ occur in the decoding stage, so some arguments are not needed. */
+ err_status = H5Aiterate2(did, H5_INDEX_NAME, H5_ITER_INC, NULL, NULL, NULL);
+ VERIFY(err_status, FAIL, "H5Aiterate2");
+
+ /* Make sure the intended error was caught */
+ if (err_status == -1) {
+ /* Initialize client data */
+ HDstrcpy(err_caught.message, err_message);
+ err_caught.found = FALSE;
+
+ /* Look for the correct error message */
+ ret = H5Ewalk2(H5E_DEFAULT, H5E_WALK_UPWARD, find_err_msg_cb, &err_caught);
+ CHECK(ret, FAIL, "H5Ewalk2");
+
+ /* Fail if the indicated message is not found */
+ CHECK(err_caught.found, FALSE, "test_corrupted_attnamelen: Expected error not found");
+ }
+
+ /* Close the dataset and file */
+ ret = H5Dclose(did);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+} /* test_corrupted_attnamelen() */
+#endif
+
+#if 0
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+/****************************************************************
+**
+** test_links_deprec(): Test soft and hard link iteration
+**
+****************************************************************/
+static void
+test_links_deprec(hid_t fapl)
+{
+ hid_t file; /* File ID */
+ char obj_name[NAMELEN]; /* Names of the object in group */
+ ssize_t name_len; /* Length of object's name */
+ hid_t gid, gid1;
+ H5G_info_t ginfo; /* Buffer for querying object's info */
+ hsize_t i;
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing Soft and Hard Link Iteration Functionality Using Deprecated Routines\n"));
+
+ /* Create the test file with the datasets */
+ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
+ CHECK(file, FAIL, "H5Fcreate");
+
+ /* create groups */
+ gid = H5Gcreate2(file, "/g1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(gid, FAIL, "H5Gcreate2");
+
+ gid1 = H5Gcreate2(file, "/g1/g1.1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(gid1, FAIL, "H5Gcreate2");
+
+ /* create soft and hard links to the group "/g1". */
+ ret = H5Lcreate_soft("something", gid, "softlink", H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Lcreate_soft");
+
+ ret = H5Lcreate_hard(gid, "/g1", H5L_SAME_LOC, "hardlink", H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Lcreate_hard");
+
+ ret = H5Gget_info(gid, &ginfo);
+ CHECK(ret, FAIL, "H5Gget_info");
+ VERIFY(ginfo.nlinks, 3, "H5Gget_info");
+
+ /* Test these two functions, H5Oget_info_by_idx and H5Lget_name_by_idx */
+ for (i = 0; i < ginfo.nlinks; i++) {
+ H5O_info2_t oinfo; /* Object info */
+ H5L_info2_t linfo; /* Link info */
+
+ /* Get link name */
+ name_len = H5Lget_name_by_idx(gid, ".", H5_INDEX_NAME, H5_ITER_INC, i, obj_name, (size_t)NAMELEN,
+ H5P_DEFAULT);
+ CHECK(name_len, FAIL, "H5Lget_name_by_idx");
+
+ /* Get link type */
+ ret = H5Lget_info_by_idx2(gid, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, &linfo, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Lget_info_by_idx1");
+
+ /* Get object type */
+ if (linfo.type == H5L_TYPE_HARD) {
+ ret = H5Oget_info_by_idx3(gid, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, &oinfo,
+ H5O_INFO_BASIC, H5P_DEFAULT);
+ CHECK(ret, FAIL, "H5Oget_info_by_idx");
+ } /* end if */
+
+ if (!HDstrcmp(obj_name, "g1.1"))
+ VERIFY(oinfo.type, H5O_TYPE_GROUP, "H5Lget_name_by_idx");
+ else if (!HDstrcmp(obj_name, "hardlink"))
+ VERIFY(oinfo.type, H5O_TYPE_GROUP, "H5Lget_name_by_idx");
+ else if (!HDstrcmp(obj_name, "softlink"))
+ VERIFY(linfo.type, H5L_TYPE_SOFT, "H5Lget_name_by_idx");
+ else
+ ERROR("unknown object name");
+ } /* end for */
+
+ ret = H5Gclose(gid);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ ret = H5Gclose(gid1);
+ CHECK(ret, FAIL, "H5Gclose");
+
+ ret = H5Fclose(file);
+ CHECK(ret, FAIL, "H5Fclose");
+} /* test_links_deprec() */
+#endif
+#endif
+
+/****************************************************************
+**
+** test_iterate(): Main iteration testing routine.
+**
+****************************************************************/
+void
+test_iterate(void)
+{
+ hid_t fapl, fapl2; /* File access property lists */
+ unsigned new_format; /* Whether to use the new format or not */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing Iteration Operations\n"));
+
+ /* Get the default FAPL */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ CHECK(fapl, FAIL, "H5Pcreate");
+
+ /* Copy the file access property list */
+ fapl2 = H5Pcopy(fapl);
+ CHECK(fapl2, FAIL, "H5Pcopy");
+
+ /* Set the "use the latest version of the format" bounds for creating objects in the file */
+ ret = H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
+ CHECK(ret, FAIL, "H5Pset_libver_bounds");
+
+ /* These next tests use the same file */
+ for (new_format = FALSE; new_format <= TRUE; new_format++) {
+ test_iter_group(new_format ? fapl2 : fapl, new_format); /* Test group iteration */
+ test_iter_group_large(new_format ? fapl2 : fapl); /* Test group iteration for large # of objects */
+ test_iter_attr(new_format ? fapl2 : fapl, new_format); /* Test attribute iteration */
+ test_grp_memb_funcs(new_format ? fapl2 : fapl); /* Test group member information functions */
+ test_links(new_format ? fapl2 : fapl); /* Test soft and hard link iteration */
+#if 0
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ test_links_deprec(new_format ? fapl2 : fapl); /* Test soft and hard link iteration */
+#endif
+#endif
+ } /* end for */
+#if 0
+ /* Test the fix for issue HDFFV-10588 */
+ test_corrupted_attnamelen();
+#endif
+ /* Close FAPLs */
+ ret = H5Pclose(fapl);
+ CHECK(ret, FAIL, "H5Pclose");
+ ret = H5Pclose(fapl2);
+ CHECK(ret, FAIL, "H5Pclose");
+} /* test_iterate() */
+
+/*-------------------------------------------------------------------------
+ * Function: cleanup_iterate
+ *
+ * Purpose: Cleanup temporary test files
+ *
+ * Return: none
+ *
+ * Programmer: Quincey Koziol
+ * April 5, 2000
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+cleanup_iterate(void)
+{
+ H5Fdelete(DATAFILE, H5P_DEFAULT);
+}