/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Purpose: Tests closing the library after reference counts have been * manipulated. */ #include "h5test.h" #define APPREF_DSET "test_dset" #define APPREF_ATTR "test_attr" #define APPREF_GROUP "test_grp" #define ERR_WIDTH 40 /* Width of output for the SIGABRT handler */ #define MAX_NINC 16 /* Maximum increments of a reference count */ /* Macro to increment the reference count on id a random number of times (from * 1 to MAX_NINC). Assumes integers i and ninc are in scope. */ #define RAND_INC(id) \ do { \ ninc = (HDrand() % MAX_NINC) + 1; \ \ for (i = 0; i < ninc; i++) \ if (H5Iinc_ref(ids[id]) != i + 2) \ TEST_ERROR; \ \ rc[id] = ninc + 1; \ } while (0) typedef enum { T_FILE, T_PLIST, T_PCLASS, T_TYPE, T_SPACE, T_DSET, T_ATTR, T_GROUP, T_ECLASS, T_EMSG, T_ESTACK, T_NUMCLASSES } id_class_t; static const char *FILENAME[] = {"app_ref", NULL}; static const char *IDNAME[T_NUMCLASSES] = {"File", "Property List", "Property Class", "Datatype", "Dataspace", "Dataset", "Attribute", "Group", "Error Class", "Error Message", "Error Stack"}; static int rc[T_NUMCLASSES]; void Abrt_Handler(int sig); /* Handler for SIGABRT - prints the reference count on each id */ void Abrt_Handler(int H5_ATTR_UNUSED sig) { int i, n; const char *string = " ID reference count: "; for (i = 0; i < T_NUMCLASSES; i++) { fprintf(stderr, "%s%s", IDNAME[i], string); n = (int)(strlen(IDNAME[i]) + strlen(string)); fprintf(stderr, "%*d\n", (n < ERR_WIDTH) ? (ERR_WIDTH - n) : 0, rc[i]); } } /* Main test routine */ int main(void) { const char *env_h5_drvr; /* File Driver value from environment */ hid_t ids[T_NUMCLASSES]; hid_t fapl; /* File Access Property List */ int ninc; int i; char filename[1024]; h5_reset(); h5_fixname(FILENAME[0], H5P_DEFAULT, filename, sizeof filename); HDsrand((unsigned)HDtime(NULL)); TESTING("library shutdown with reference count > 1"); /* Get the VFD to use */ env_h5_drvr = getenv(HDF5_DRIVER); if (env_h5_drvr == NULL) env_h5_drvr = "nomatch"; /* Don't run this test with the multi/split VFD. A bug in library shutdown * ordering causes problems with the multi VFD when IDs are left dangling. */ if (!strcmp(env_h5_drvr, "multi") || !strcmp(env_h5_drvr, "split")) { puts("\n -- SKIPPED for incompatible VFD --"); return 0; } /* Create the file */ if ((ids[T_FILE] = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR; RAND_INC(T_FILE); /* Create the property list */ if ((ids[T_PLIST] = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR; RAND_INC(T_PLIST); /* Create a property class */ if ((ids[T_PCLASS] = H5Pcreate_class(H5P_DATASET_CREATE, "foo", NULL, NULL, NULL, NULL, NULL, NULL)) < 0) TEST_ERROR; RAND_INC(T_PCLASS); /* Create a datatype */ if ((ids[T_TYPE] = H5Tcreate(H5T_OPAQUE, (size_t)16)) < 0) TEST_ERROR; RAND_INC(T_TYPE); /* Create a dataspace */ if ((ids[T_SPACE] = H5Screate(H5S_SCALAR)) < 0) TEST_ERROR; RAND_INC(T_SPACE); /* Create a dataset */ if ((ids[T_DSET] = H5Dcreate2(ids[T_FILE], APPREF_DSET, H5T_NATIVE_INT, ids[T_SPACE], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR; RAND_INC(T_DSET); /* Create an attribute */ if ((ids[T_ATTR] = H5Acreate2(ids[T_DSET], APPREF_ATTR, H5T_NATIVE_INT, ids[T_SPACE], H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR; RAND_INC(T_ATTR); /* Create a group */ if ((ids[T_GROUP] = H5Gcreate2(ids[T_FILE], APPREF_GROUP, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR; RAND_INC(T_GROUP); /* Create an error class */ if ((ids[T_ECLASS] = H5Eregister_class("foo", "bar", "baz")) < 0) TEST_ERROR; RAND_INC(T_ECLASS); /* Create an error message */ if ((ids[T_EMSG] = H5Ecreate_msg(ids[T_ECLASS], H5E_MAJOR, "mumble")) < 0) TEST_ERROR; RAND_INC(T_EMSG); /* Create an error stack */ if ((ids[T_ESTACK] = H5Eget_current_stack()) < 0) TEST_ERROR; RAND_INC(T_ESTACK); HDsignal(SIGABRT, &Abrt_Handler); if (H5close() < 0) TEST_ERROR; PASSED(); /* Restore the default error handler (set in h5_reset()) */ h5_restore_err(); /* Clean up any file(s) created */ h5_reset(); fapl = H5Pcreate(H5P_FILE_ACCESS); h5_cleanup(FILENAME, fapl); return EXIT_SUCCESS; error: puts("***** APPLICATION REFERENCE COUNT TESTS FAILED *****"); return EXIT_FAILURE; }