summaryrefslogtreecommitdiffstats
path: root/test/tid.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/tid.c')
-rw-r--r--test/tid.c540
1 files changed, 516 insertions, 24 deletions
diff --git a/test/tid.c b/test/tid.c
index b3bef52..007ed69 100644
--- a/test/tid.c
+++ b/test/tid.c
@@ -20,7 +20,7 @@
#include "H5Ipkg.h"
static herr_t
-free_wrapper(void *p, void **_ctx)
+free_wrapper(void *p, void H5_ATTR_UNUSED **_ctx)
{
HDfree(p);
return SUCCEED;
@@ -575,9 +575,9 @@ out:
*/
/* Macro definitions */
-#define RCT_MAX_NOBJS 25 /* Maximum number of objects in the list */
+#define RCT_MAX_NOBJS 25 /* Maximum number of objects in the list */
#define RCT_MIN_NOBJS 5
-#define RCT_NITER 50 /* Number of times we cycle through object creation and deletion */
+#define RCT_NITER 50 /* Number of times we cycle through object creation and deletion */
/* Structure to hold the master list of objects */
typedef struct rct_obj_list_t {
@@ -595,10 +595,10 @@ typedef struct rct_obj_list_t {
/* Structure for an object */
typedef struct rct_obj_t {
/* The ID for this object */
- hid_t id;
+ hid_t id;
/* The number of times this object has been freed */
- int nfrees;
+ int nfrees;
/* Whether we are currently freeing this object directly
* through H5Idec_ref().
@@ -615,12 +615,12 @@ typedef struct rct_obj_t {
* master list of objects.
*/
static herr_t
-rct_free_cb(void *_obj, void **_ctx)
+rct_free_cb(void *_obj, void H5_ATTR_UNUSED **_ctx)
{
- rct_obj_t * obj = (rct_obj_t *)_obj;
- long remove_nth;
- long i;
- herr_t ret;
+ rct_obj_t *obj = (rct_obj_t *)_obj;
+ long remove_nth;
+ long i;
+ herr_t ret;
/* Mark this object as freed */
obj->nfrees++;
@@ -689,12 +689,12 @@ error:
static int
test_remove_clear_type(void)
{
- H5I_type_t obj_type;
- rct_obj_list_t obj_list;
- rct_obj_t * objects = NULL; /* Convenience pointer to objects stored in master list */
- size_t list_size;
- long i, j;
- herr_t ret; /* return value */
+ H5I_type_t obj_type;
+ rct_obj_list_t obj_list;
+ rct_obj_t * objects = NULL; /* Convenience pointer to objects stored in master list */
+ size_t list_size;
+ long i, j;
+ herr_t ret; /* return value */
/* Register a user-defined type with our custom ID-deleting callback */
obj_type = H5Iregister_type((size_t)8, 0, rct_free_cb);
@@ -703,7 +703,7 @@ test_remove_clear_type(void)
goto error;
/* Create an array to hold the objects in the master list */
- list_size = RCT_MAX_NOBJS * sizeof(rct_obj_t);
+ list_size = RCT_MAX_NOBJS * sizeof(rct_obj_t);
obj_list.objects = HDmalloc(list_size);
CHECK(obj_list.objects, NULL, "HDcalloc");
if (NULL == obj_list.objects)
@@ -734,9 +734,9 @@ test_remove_clear_type(void)
for (j = 0; j < obj_list.count; j++) {
/* Object setup */
- objects[j].nfrees = 0;
- objects[j].freeing = FALSE;
- objects[j].list = &obj_list;
+ objects[j].nfrees = 0;
+ objects[j].freeing = FALSE;
+ objects[j].list = &obj_list;
/* Register an ID for it */
objects[j].id = H5Iregister(obj_type, &objects[j]);
@@ -790,7 +790,7 @@ test_remove_clear_type(void)
/* Verify the number of unfreed objects we found during our scan
* matches the number stored in the list
- */
+ */
VERIFY(obj_list.remaining, found, "incorrect number of objects remaining");
if (obj_list.remaining != found)
goto error;
@@ -856,15 +856,505 @@ test_remove_clear_type(void)
error:
/* Cleanup. For simplicity, just destroy the types and ignore errors. */
- H5E_BEGIN_TRY {
- H5Idestroy_type(obj_type);
- } H5E_END_TRY
+ H5E_BEGIN_TRY { H5Idestroy_type(obj_type); }
+ H5E_END_TRY
HDfree(obj_list.objects);
return -1;
} /* end test_remove_clear_type() */
+/* Typedef for future objects */
+typedef struct {
+ H5I_type_t obj_type; /* ID type for actual object */
+} future_obj_t;
+
+/* Global (static) future ID object type */
+H5I_type_t future_obj_type_g = H5I_BADID;
+
+/* Callback to free the actual object for future object test */
+static herr_t
+free_actual_object(void *_p, void H5_ATTR_UNUSED **_ctx)
+{
+ int *p = (int *)_p;
+
+ if (7 != *p)
+ return FAIL;
+
+ HDfree(p);
+
+ return SUCCEED;
+}
+
+/* Callback to realize a future object */
+static herr_t
+realize_future_cb(void *_future_obj, hid_t *actual_id)
+{
+ future_obj_t *future_obj = (future_obj_t *)_future_obj; /* Future object */
+ int * actual_obj; /* Pointer to the actual object */
+
+ /* Check for bad future object */
+ if (NULL == future_obj)
+ return FAIL;
+
+ /* Determine type of object to realize */
+ if (H5I_DATASPACE == future_obj->obj_type) {
+ hsize_t dims = 13;
+
+ if ((*actual_id = H5Screate_simple(1, &dims, NULL)) < 0)
+ return FAIL;
+ }
+ else if (H5I_DATATYPE == future_obj->obj_type) {
+ if ((*actual_id = H5Tcopy(H5T_NATIVE_INT)) < 0)
+ return FAIL;
+ }
+ else if (H5I_GENPROP_LST == future_obj->obj_type) {
+ if ((*actual_id = H5Pcreate(H5P_DATASET_XFER)) < 0)
+ return FAIL;
+ }
+ else {
+ /* Create a new object (the 'actual object') of the correct type */
+ if (NULL == (actual_obj = HDmalloc(sizeof(int))))
+ return FAIL;
+ *actual_obj = 7;
+
+ /* Register actual object of the user-defined type */
+ *actual_id = H5Iregister(future_obj->obj_type, actual_obj);
+ CHECK(*actual_id, FAIL, "H5Iregister");
+ if (*actual_id == FAIL)
+ return FAIL;
+ }
+
+ return SUCCEED;
+}
+
+/* Callback to discard a future object */
+static herr_t
+discard_future_cb(void *future_obj)
+{
+ if (NULL == future_obj)
+ return FAIL;
+
+ HDfree(future_obj);
+
+ return SUCCEED;
+}
+
+/* Callback to realize a future object when future objects are NULL*/
+static herr_t
+realize_future_generate_cb(void *_future_obj, hid_t *actual_id)
+{
+ future_obj_t *future_obj = (future_obj_t *)_future_obj; /* Future object */
+ int * actual_obj; /* Pointer to the actual object */
+
+ if (NULL != future_obj)
+ return FAIL;
+ /* Create a new object (the 'actual object') of the correct type */
+ if (NULL == (actual_obj = HDmalloc(sizeof(int))))
+ return FAIL;
+ *actual_obj = 7;
+
+ /* Register actual object without using future object info */
+ *actual_id = H5Iregister(future_obj_type_g, actual_obj);
+ CHECK(*actual_id, FAIL, "H5Iregister");
+ if (*actual_id == FAIL)
+ return FAIL;
+
+ return SUCCEED;
+}
+
+/* Callback to discard a future object when future objects are NULL */
+static herr_t
+discard_future_generate_cb(void *future_obj)
+{
+ if (NULL != future_obj)
+ return FAIL;
+
+ return SUCCEED;
+}
+
+/* Test function */
+static int
+test_future_ids(void)
+{
+ H5I_type_t obj_type; /* New user-defined ID type */
+ hid_t future_id; /* ID for future object */
+ int fake_future_obj; /* "Fake" future object for tests */
+ future_obj_t *future_obj; /* Future object */
+ int * actual_obj; /* Actual object */
+ int * actual_obj2; /* Another actual object */
+ H5I_type_t id_type; /* Type of ID */
+ H5T_class_t type_class; /* Datatype class */
+ herr_t ret; /* Return value */
+
+ /* Register a user-defined type with our custom ID-deleting callback */
+ obj_type = H5Iregister_type((size_t)15, 0, free_actual_object);
+ CHECK(obj_type, H5I_BADID, "H5Iregister_type");
+ if (H5I_BADID == obj_type)
+ goto error;
+
+ /* Test basic error conditions */
+ fake_future_obj = 0;
+ H5E_BEGIN_TRY { future_id = H5Iregister_future(obj_type, &fake_future_obj, NULL, NULL); }
+ H5E_END_TRY
+ VERIFY(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID != future_id)
+ goto error;
+
+ H5E_BEGIN_TRY { future_id = H5Iregister_future(obj_type, &fake_future_obj, realize_future_cb, NULL); }
+ H5E_END_TRY
+ VERIFY(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID != future_id)
+ goto error;
+
+ H5E_BEGIN_TRY { future_id = H5Iregister_future(obj_type, &fake_future_obj, NULL, discard_future_cb); }
+ H5E_END_TRY
+ VERIFY(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID != future_id)
+ goto error;
+
+ H5E_BEGIN_TRY
+ {
+ future_id = H5Iregister_future(H5I_BADID, &fake_future_obj, realize_future_cb, discard_future_cb);
+ }
+ H5E_END_TRY
+ VERIFY(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID != future_id)
+ goto error;
+
+ /* Test base use-case: create a future object and destroy type without
+ * realizing the future object.
+ */
+ future_obj = HDmalloc(sizeof(future_obj_t));
+ future_obj->obj_type = obj_type;
+ future_id = H5Iregister_future(obj_type, future_obj, realize_future_cb, discard_future_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ /* Destroy the type */
+ ret = H5Idestroy_type(obj_type);
+ CHECK(ret, FAIL, "H5Idestroy_type");
+ if (FAIL == ret)
+ goto error;
+
+ /* Re-register a user-defined type with our custom ID-deleting callback */
+ obj_type = H5Iregister_type((size_t)15, 0, free_actual_object);
+ CHECK(obj_type, H5I_BADID, "H5Iregister_type");
+ if (H5I_BADID == obj_type)
+ goto error;
+
+ /* Test base use-case: create a future object and realize the actual object. */
+ future_obj = HDmalloc(sizeof(future_obj_t));
+ future_obj->obj_type = obj_type;
+ future_id = H5Iregister_future(obj_type, future_obj, realize_future_cb, discard_future_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ actual_obj = H5Iobject_verify(future_id, obj_type);
+ CHECK_PTR(actual_obj, "H5Iobject_verify");
+ if (NULL == actual_obj)
+ goto error;
+ VERIFY(*actual_obj, 7, "H5Iobject_verify");
+ if (7 != *actual_obj)
+ goto error;
+
+ /* Retrieve the object again and verify that it's the same actual object */
+ actual_obj2 = H5Iobject_verify(future_id, obj_type);
+ CHECK_PTR(actual_obj2, "H5Iobject_verify");
+ if (NULL == actual_obj2)
+ goto error;
+ VERIFY(*actual_obj2, 7, "H5Iobject_verify");
+ if (7 != *actual_obj2)
+ goto error;
+ VERIFY(actual_obj, actual_obj2, "H5Iobject_verify");
+ if (actual_obj != actual_obj2)
+ goto error;
+
+ /* Destroy the type */
+ ret = H5Idestroy_type(obj_type);
+ CHECK(ret, FAIL, "H5Idestroy_type");
+ if (FAIL == ret)
+ goto error;
+
+ /* Re-register a user-defined type with our custom ID-deleting callback */
+ obj_type = H5Iregister_type((size_t)15, 0, free_actual_object);
+ CHECK(obj_type, H5I_BADID, "H5Iregister_type");
+ if (H5I_BADID == obj_type)
+ goto error;
+
+ /* Set the global future object type */
+ future_obj_type_g = obj_type;
+
+ /* Test "actual object generator" use-case: create a future object with
+ * NULL object pointer, to create new object of predefined type when
+ * future object is realized.
+ */
+ future_id = H5Iregister_future(obj_type, NULL, realize_future_generate_cb, discard_future_generate_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ /* Realize the actual object, with will be dynamically allocated within
+ * the 'realize' callback.
+ */
+ actual_obj = H5Iobject_verify(future_id, obj_type);
+ CHECK_PTR(actual_obj, "H5Iobject_verify");
+ if (NULL == actual_obj)
+ goto error;
+ VERIFY(*actual_obj, 7, "H5Iobject_verify");
+ if (7 != *actual_obj)
+ goto error;
+
+ /* Reset the global future object type */
+ future_obj_type_g = H5I_BADID;
+
+ /* Retrieve the object again and verify that it's the same actual object */
+ /* (Will fail if global future object type used) */
+ actual_obj2 = H5Iobject_verify(future_id, obj_type);
+ CHECK_PTR(actual_obj2, "H5Iobject_verify");
+ if (NULL == actual_obj2)
+ goto error;
+ VERIFY(*actual_obj2, 7, "H5Iobject_verify");
+ if (7 != *actual_obj2)
+ goto error;
+ VERIFY(actual_obj, actual_obj2, "H5Iobject_verify");
+ if (actual_obj != actual_obj2)
+ goto error;
+
+ /* Destroy the type */
+ ret = H5Idestroy_type(obj_type);
+ CHECK(ret, FAIL, "H5Idestroy_type");
+ if (FAIL == ret)
+ goto error;
+
+ /* Test base use-case: create a future object for a pre-defined type */
+ /* (DATASPACE) */
+ future_obj = HDmalloc(sizeof(future_obj_t));
+ future_obj->obj_type = H5I_DATASPACE;
+ future_id = H5Iregister_future(H5I_DATASPACE, future_obj, realize_future_cb, discard_future_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ /* (Can't verify the type of the future ID, because the library's current
+ * implementation realizes the object during sanity checks on the ID)
+ */
+
+ /* Close future object for pre-defined type without realizing it */
+ ret = H5Idec_ref(future_id);
+ CHECK(ret, FAIL, "H5Idec_ref");
+ if (FAIL == ret)
+ goto error;
+
+ /* Test base use-case: create a future object for a pre-defined type */
+ future_obj = HDmalloc(sizeof(future_obj_t));
+ future_obj->obj_type = H5I_DATASPACE;
+ future_id = H5Iregister_future(H5I_DATASPACE, future_obj, realize_future_cb, discard_future_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ /* Verify that the application believes the future ID is a dataspace */
+ /* (Currently realizes the object "implicitly" during a sanity check) */
+ id_type = H5Iget_type(future_id);
+ CHECK(id_type, H5I_BADID, "H5Iget_type");
+ if (H5I_BADID == id_type)
+ goto error;
+ if (H5I_DATASPACE != id_type)
+ goto error;
+
+ /* Close future object for pre-defined type without realizing it */
+ ret = H5Idec_ref(future_id);
+ CHECK(ret, FAIL, "H5Idec_ref");
+ if (FAIL == ret)
+ goto error;
+
+ /* Test base use-case: create a future object for a pre-defined type */
+ future_obj = HDmalloc(sizeof(future_obj_t));
+ future_obj->obj_type = H5I_DATASPACE;
+ future_id = H5Iregister_future(H5I_DATASPACE, future_obj, realize_future_cb, discard_future_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ /* Realize future dataspace by requesting its rank */
+ ret = H5Sget_simple_extent_ndims(future_id);
+ CHECK(ret, FAIL, "H5Sget_simple_extent_ndims");
+ if (FAIL == ret)
+ goto error;
+ if (1 != ret)
+ goto error;
+
+ /* Verify that the application believes the ID is still a dataspace */
+ id_type = H5Iget_type(future_id);
+ CHECK(id_type, H5I_BADID, "H5Iget_type");
+ if (H5I_BADID == id_type)
+ goto error;
+ if (H5I_DATASPACE != id_type)
+ goto error;
+
+ /* Close future object for pre-defined type after realizing it */
+ ret = H5Idec_ref(future_id);
+ CHECK(ret, FAIL, "H5Idec_ref");
+ if (FAIL == ret)
+ goto error;
+
+ /* Test base use-case: create a future object for a pre-defined type */
+ /* (DATATYPE) */
+ future_obj = HDmalloc(sizeof(future_obj_t));
+ future_obj->obj_type = H5I_DATATYPE;
+ future_id = H5Iregister_future(H5I_DATATYPE, future_obj, realize_future_cb, discard_future_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ /* (Can't verify the type of the future ID, because the library's current
+ * implementation realizes the object during sanity checks on the ID)
+ */
+
+ /* Close future object for pre-defined type without realizing it */
+ ret = H5Idec_ref(future_id);
+ CHECK(ret, FAIL, "H5Idec_ref");
+ if (FAIL == ret)
+ goto error;
+
+ /* Test base use-case: create a future object for a pre-defined type */
+ future_obj = HDmalloc(sizeof(future_obj_t));
+ future_obj->obj_type = H5I_DATATYPE;
+ future_id = H5Iregister_future(H5I_DATATYPE, future_obj, realize_future_cb, discard_future_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ /* Verify that the application believes the future ID is a datatype */
+ /* (Currently realizes the object "implicitly" during a sanity check) */
+ id_type = H5Iget_type(future_id);
+ CHECK(id_type, H5I_BADID, "H5Iget_type");
+ if (H5I_BADID == id_type)
+ goto error;
+ if (H5I_DATATYPE != id_type)
+ goto error;
+
+ /* Close future object for pre-defined type without realizing it */
+ ret = H5Idec_ref(future_id);
+ CHECK(ret, FAIL, "H5Idec_ref");
+ if (FAIL == ret)
+ goto error;
+
+ /* Test base use-case: create a future object for a pre-defined type */
+ future_obj = HDmalloc(sizeof(future_obj_t));
+ future_obj->obj_type = H5I_DATATYPE;
+ future_id = H5Iregister_future(H5I_DATATYPE, future_obj, realize_future_cb, discard_future_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ /* Realize future datatype by requesting its class */
+ type_class = H5Tget_class(future_id);
+ CHECK(ret, FAIL, "H5Tget_class");
+ if (FAIL == ret)
+ goto error;
+ if (H5T_INTEGER != type_class)
+ goto error;
+
+ /* Verify that the application believes the ID is still a datatype */
+ id_type = H5Iget_type(future_id);
+ CHECK(id_type, H5I_BADID, "H5Iget_type");
+ if (H5I_BADID == id_type)
+ goto error;
+ if (H5I_DATATYPE != id_type)
+ goto error;
+
+ /* Close future object for pre-defined type after realizing it */
+ ret = H5Idec_ref(future_id);
+ CHECK(ret, FAIL, "H5Idec_ref");
+ if (FAIL == ret)
+ goto error;
+
+ /* Test base use-case: create a future object for a pre-defined type */
+ /* (PROPERTY LIST) */
+ future_obj = HDmalloc(sizeof(future_obj_t));
+ future_obj->obj_type = H5I_GENPROP_LST;
+ future_id = H5Iregister_future(H5I_GENPROP_LST, future_obj, realize_future_cb, discard_future_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ /* (Can't verify the type of the future ID, because the library's current
+ * implementation realizes the object during sanity checks on the ID)
+ */
+
+ /* Close future object for pre-defined type without realizing it */
+ ret = H5Idec_ref(future_id);
+ CHECK(ret, FAIL, "H5Idec_ref");
+ if (FAIL == ret)
+ goto error;
+
+ /* Test base use-case: create a future object for a pre-defined type */
+ future_obj = HDmalloc(sizeof(future_obj_t));
+ future_obj->obj_type = H5I_GENPROP_LST;
+ future_id = H5Iregister_future(H5I_GENPROP_LST, future_obj, realize_future_cb, discard_future_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ /* Verify that the application believes the future ID is a property list */
+ /* (Currently realizes the object "implicitly" during a sanity check) */
+ id_type = H5Iget_type(future_id);
+ CHECK(id_type, H5I_BADID, "H5Iget_type");
+ if (H5I_BADID == id_type)
+ goto error;
+ if (H5I_GENPROP_LST != id_type)
+ goto error;
+
+ /* Close future object for pre-defined type without realizing it */
+ ret = H5Idec_ref(future_id);
+ CHECK(ret, FAIL, "H5Idec_ref");
+ if (FAIL == ret)
+ goto error;
+
+ /* Test base use-case: create a future object for a pre-defined type */
+ future_obj = HDmalloc(sizeof(future_obj_t));
+ future_obj->obj_type = H5I_GENPROP_LST;
+ future_id = H5Iregister_future(H5I_GENPROP_LST, future_obj, realize_future_cb, discard_future_cb);
+ CHECK(future_id, H5I_INVALID_HID, "H5Iregister_future");
+ if (H5I_INVALID_HID == future_id)
+ goto error;
+
+ /* Realize future property list by verifying its class */
+ ret = H5Pisa_class(future_id, H5P_DATASET_XFER);
+ CHECK(ret, FAIL, "H5Pisa_class");
+ if (FAIL == ret)
+ goto error;
+ if (TRUE != ret)
+ goto error;
+
+ /* Verify that the application believes the ID is still a property list */
+ id_type = H5Iget_type(future_id);
+ CHECK(id_type, H5I_BADID, "H5Iget_type");
+ if (H5I_BADID == id_type)
+ goto error;
+ if (H5I_GENPROP_LST != id_type)
+ goto error;
+
+ /* Close future object for pre-defined type after realizing it */
+ ret = H5Idec_ref(future_id);
+ CHECK(ret, FAIL, "H5Idec_ref");
+ if (FAIL == ret)
+ goto error;
+
+ return 0;
+
+error:
+ /* Cleanup. For simplicity, just destroy the types and ignore errors. */
+ H5E_BEGIN_TRY { H5Idestroy_type(obj_type); }
+ H5E_END_TRY
+
+ return -1;
+} /* end test_future_ids() */
+
void
test_ids(void)
{
@@ -883,4 +1373,6 @@ test_ids(void)
TestErrPrintf("ID type list test failed\n");
if (test_remove_clear_type() < 0)
TestErrPrintf("ID remove during H5Iclear_type test failed\n");
+ if (test_future_ids() < 0)
+ TestErrPrintf("Future ID test failed\n");
}