/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * This file is modified based on earray.c. */ #include "h5test.h" /* * This file needs to access private datatypes from the H5FA package. * This file also needs to access the fixed array testing code. */ #define H5FA_FRIEND /*suppress error about including H5FApkg */ #define H5FA_TESTING #include "H5FApkg.h" /* Fixed Arrays */ /* Other private headers that this test requires */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Iprivate.h" /* IDs */ #include "H5VMprivate.h" /* Vectors and arrays */ #include "H5VLprivate.h" /* Virtual Object Layer */ /* Local macros */ /* Max. testfile name length */ #define FARRAY_FILENAME_LEN 1024 /* Fixed array creation values */ #define ELMT_SIZE sizeof(uint64_t) #define MAX_DBLOCK_PAGE_NELMTS_BITS 10 /* 2^10 = 1024 elements per data block page */ /* Testing # of elements in the Fixed Array */ #define TEST_NELMTS 20000 /* Convenience macros for computing earray state */ #define FA_HDR_SIZE 28 /* hard-coded */ #define DBLOCK_PREFIX 18 /* hard-coded */ /* 4 giga-elements: max chunk size */ #define MAX_NELMTS ((unsigned long long)4 * 1024 * 1024 * 1024) /* 4 giga-elements */ /* Iterator parameter values */ #define FA_CYC_COUNT 4 /* Local typedefs */ /* Types of tests to perform */ typedef enum { FARRAY_TEST_NORMAL, /* "Normal" test, with no testing parameters set */ FARRAY_TEST_REOPEN, /* Set the reopen_array flag */ FARRAY_TEST_NTESTS /* The number of test types, must be last */ } farray_test_type_t; /* Types of iteration to perform */ typedef enum { FARRAY_ITER_FW, /* "Forward" iteration */ FARRAY_ITER_RV, /* "Reverse" iteration */ FARRAY_ITER_RND, /* "Random" iteration */ FARRAY_ITER_CYC, /* "Cyclic" iteration */ FARRAY_ITER_NITERS /* The number of iteration types, must be last */ } farray_iter_type_t; /* Fixed array state information */ typedef struct farray_state_t { hsize_t hdr_size; /* Size of header */ hsize_t dblk_size; /* Size of data block */ hsize_t nelmts; /* # of elements */ } farray_state_t; /* Forward decl. */ typedef struct farray_test_param_t farray_test_param_t; /* Fixed array iterator class */ typedef struct farray_iter_t { void *(*init)(const H5FA_create_t *cparam, const farray_test_param_t *tparam, hsize_t cnt); /* Initialize/allocate iterator private info */ hssize_t (*next)(void *info); /* Get the next element to test */ herr_t (*term)(void *info); /* Shutdown/free iterator private info */ } farray_iter_t; /* Testing parameters */ struct farray_test_param_t { farray_test_type_t reopen_array; /* Whether to re-open the array during the test */ hsize_t nelmts; /* # of elements to set for the fixed array */ const farray_iter_t *fiter; /* Iterator to use for this test */ }; /* Local variables */ const char *FILENAME[] = {"farray", "farray_tmp", NULL}; /* Filename to use for all tests */ char filename_g[FARRAY_FILENAME_LEN]; /* Empty file size */ h5_stat_size_t empty_size_g; /*------------------------------------------------------------------------- * Function: init_cparam * * Purpose: Initialize array creation parameter structure * * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ static herr_t init_cparam(H5FA_create_t *cparam, farray_test_param_t *tparam) { /* Wipe out background */ HDmemset(cparam, 0, sizeof(*cparam)); cparam->cls = H5FA_CLS_TEST; cparam->raw_elmt_size = ELMT_SIZE; cparam->max_dblk_page_nelmts_bits = MAX_DBLOCK_PAGE_NELMTS_BITS; cparam->nelmts = tparam->nelmts; return SUCCEED; } /* init_cparam() */ /*------------------------------------------------------------------------- * Function: create_file * * Purpose: Create file and retrieve pointer to internal file object * * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ static herr_t create_file(hid_t fapl_id, hid_t *fid, H5F_t **f) { /* Create the file to work on */ if ((*fid = H5Fcreate(filename_g, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0) FAIL_STACK_ERROR; /* Get a pointer to the internal file object */ if (NULL == (*f = (H5F_t *)H5VL_object(*fid))) FAIL_STACK_ERROR; /* Ignore metadata tags in the file's cache */ if (H5AC_ignore_tags(*f) < 0) FAIL_STACK_ERROR; /* Success */ return SUCCEED; error: return FAIL; } /* create_file() */ /*------------------------------------------------------------------------- * Function: check_stats * * Purpose: Verify stats for a fixed array * * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ static herr_t check_stats(const H5FA_t *fa, const farray_state_t *state) { H5FA_stat_t farray_stats; /* Statistics about the array */ /* Get statistics for fixed array and verify they are correct */ if (H5FA_get_stats(fa, &farray_stats) < 0) FAIL_STACK_ERROR /* Compare information */ if (farray_stats.hdr_size != state->hdr_size) { HDfprintf(stdout, "farray_stats.hdr_size = %" PRIuHSIZE ", state->hdr_size = %" PRIuHSIZE "\n", farray_stats.hdr_size, state->hdr_size); TEST_ERROR } if (farray_stats.dblk_size != state->dblk_size) { HDfprintf(stdout, "farray_stats.dblk_size = %" PRIuHSIZE ", state->dblk_size = %" PRIuHSIZE "\n", farray_stats.dblk_size, state->dblk_size); TEST_ERROR } if (farray_stats.nelmts != state->nelmts) { HDfprintf(stdout, "farray_stats.nelmts = %" PRIuHSIZE ", state->nelmts = %" PRIuHSIZE "\n", farray_stats.nelmts, state->nelmts); TEST_ERROR } /* Success */ return SUCCEED; error: return FAIL; } /* check_stats() */ /*------------------------------------------------------------------------- * Function: set_fa_state * * Purpose: Set the state of the Fixed Array * * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ static herr_t set_fa_state(const H5FA_create_t *cparam, farray_state_t *state) { size_t dblk_page_nelmts; /* # of elements per page */ /* Sanity check */ HDassert(cparam); HDassert(state); /* Compute the state of the fixed array */ state->hdr_size = FA_HDR_SIZE; state->nelmts = cparam->nelmts; dblk_page_nelmts = (size_t)1 << cparam->max_dblk_page_nelmts_bits; if (state->nelmts > dblk_page_nelmts) { size_t npages = (size_t)(((state->nelmts + dblk_page_nelmts) - 1) / dblk_page_nelmts); size_t dblk_page_init_size = (npages + 7) / 8; hsize_t checksum_size = npages * 4; state->dblk_size = DBLOCK_PREFIX + dblk_page_init_size + checksum_size + state->nelmts * cparam->raw_elmt_size; } else state->dblk_size = DBLOCK_PREFIX + state->nelmts * cparam->raw_elmt_size; return SUCCEED; } /* end set_fa_state() */ /*------------------------------------------------------------------------- * Function: reopen_file * * Purpose: Perform common "re-open" operations on file & array for testing * * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ static int reopen_file(hid_t *fid, H5F_t **f, hid_t fapl_id, H5FA_t **fa, haddr_t fa_addr, const farray_test_param_t *tparam) { /* Check for closing & re-opening the array */ /* (actually will close & re-open the file as well) */ if (tparam->reopen_array) { /* Close array, if given */ if (fa && *fa) { if (H5FA_close(*fa) < 0) FAIL_STACK_ERROR *fa = NULL; } /* Close file */ if (*fid) { if (H5Fclose(*fid) < 0) FAIL_STACK_ERROR *fid = H5I_INVALID_HID; *f = NULL; } /* Re-open the file */ if ((*fid = H5Fopen(filename_g, H5F_ACC_RDWR, fapl_id)) < 0) FAIL_STACK_ERROR /* Get a pointer to the internal file object */ if (NULL == (*f = (H5F_t *)H5VL_object(*fid))) FAIL_STACK_ERROR; /* Ignore metadata tags in the file's cache */ if (H5AC_ignore_tags(*f) < 0) FAIL_STACK_ERROR /* Re-open array, if given */ if (fa) if (NULL == (*fa = H5FA_open(*f, fa_addr, NULL))) FAIL_STACK_ERROR } /* Success */ return SUCCEED; error: return FAIL; } /* reopen_file() */ /*------------------------------------------------------------------------- * Function: create_array * * Purpose: Create a fixed array and perform initial checks * * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ static herr_t create_array(H5F_t *f, const H5FA_create_t *cparam, H5FA_t **fa, haddr_t *fa_addr) { farray_state_t state; /* State of extensible array */ /* Create array */ if (NULL == (*fa = H5FA_create(f, cparam, NULL))) FAIL_STACK_ERROR /* Check status of array */ if (H5FA_get_addr(*fa, fa_addr) < 0) FAIL_STACK_ERROR if (!H5F_addr_defined(*fa_addr)) TEST_ERROR /* Check array stats */ HDmemset(&state, 0, sizeof(state)); state.hdr_size = FA_HDR_SIZE; state.nelmts = cparam->nelmts; if (check_stats(*fa, &state)) TEST_ERROR /* Success */ return SUCCEED; error: return FAIL; } /* create_array() */ /*------------------------------------------------------------------------- * Function: verify_cparam * * Purpose: Verify creation parameters are correct * * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ static herr_t verify_cparam(const H5FA_t *fa, const H5FA_create_t *cparam) { H5FA_create_t test_cparam; /* Creation parameters for array */ /* Retrieve creation parameters */ HDmemset(&test_cparam, 0, sizeof(H5FA_create_t)); if (H5FA__get_cparam_test(fa, &test_cparam) < 0) FAIL_STACK_ERROR /* Verify creation parameters */ if (H5FA__cmp_cparam_test(cparam, &test_cparam)) TEST_ERROR /* Success */ return SUCCEED; error: return FAIL; } /* verify_cparam() */ /*------------------------------------------------------------------------- * Function: finish * * Purpose: Close array, delete array, close file and verify that file * is empty size * * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ static herr_t finish(hid_t fid, hid_t fapl_id, H5F_t *f, H5FA_t *fa, haddr_t fa_addr) { h5_stat_size_t file_size; /* File size, after deleting array */ /* Close the fixed array */ if (H5FA_close(fa) < 0) FAIL_STACK_ERROR /* Delete array */ if (H5FA_delete(f, fa_addr, NULL) < 0) FAIL_STACK_ERROR /* Close the file */ if (H5Fclose(fid) < 0) FAIL_STACK_ERROR /* Get the size of the file */ if ((file_size = h5_get_file_size(filename_g, fapl_id)) < 0) TEST_ERROR /* Verify the file is correct size */ if (file_size != empty_size_g) TEST_ERROR /* Success */ return SUCCEED; error: return FAIL; } /* finish() */ /*------------------------------------------------------------------------- * Function: test_create * * Purpose: Test creating fixed array * * Return: Success: 0 * Failure: 1 * *------------------------------------------------------------------------- */ static unsigned test_create(hid_t fapl, H5FA_create_t *cparam, farray_test_param_t H5_ATTR_UNUSED *tparam) { hid_t file = -1; /* File ID */ H5F_t *f = NULL; /* Internal file object pointer */ H5FA_t *fa = NULL; /* Fixed array wrapper */ haddr_t fa_addr = HADDR_UNDEF; /* Array address in file */ /* Create file & retrieve pointer to internal file object */ if (create_file(fapl, &file, &f) < 0) TEST_ERROR /* * Display testing message */ TESTING("invalid fixed array creation parameters"); #ifndef NDEBUG { H5FA_create_t test_cparam; /* Creation parameters for array */ /* Set invalid element size */ HDmemcpy(&test_cparam, cparam, sizeof(test_cparam)); test_cparam.raw_elmt_size = 0; H5E_BEGIN_TRY { fa = H5FA_create(f, &test_cparam, NULL); } H5E_END_TRY; if (fa) { /* Close opened fixed array */ H5FA_close(fa); fa = NULL; /* Indicate error */ TEST_ERROR } /* end if */ /* Set invalid max. # of elements bits */ HDmemcpy(&test_cparam, cparam, sizeof(test_cparam)); test_cparam.max_dblk_page_nelmts_bits = 0; H5E_BEGIN_TRY { fa = H5FA_create(f, &test_cparam, NULL); } H5E_END_TRY; if (fa) { /* Close opened fixed array */ H5FA_close(fa); fa = NULL; /* Indicate error */ TEST_ERROR } /* end if */ /* Set invalid max. # of elements */ HDmemcpy(&test_cparam, cparam, sizeof(test_cparam)); test_cparam.nelmts = 0; H5E_BEGIN_TRY { fa = H5FA_create(f, &test_cparam, NULL); } H5E_END_TRY; if (fa) { /* Close opened fixed array */ H5FA_close(fa); fa = NULL; /* Indicate error */ TEST_ERROR } /* end if */ PASSED(); } #else /* NDEBUG */ SKIPPED(); HDputs(" Not tested when assertions are disabled"); #endif /* NDEBUG */ /* * Display testing message */ TESTING("fixed array creation"); /* Create array */ if (create_array(f, cparam, &fa, &fa_addr) < 0) TEST_ERROR PASSED(); /* Verify the creation parameters */ TESTING("verify array creation parameters"); /* Verify the creation parameters */ if (verify_cparam(fa, cparam) < 0) TEST_ERROR /* Close array, delete array, close file & verify file is empty */ if (finish(file, fapl, f, fa, fa_addr) < 0) TEST_ERROR /* All tests passed */ PASSED(); return 0; error: H5E_BEGIN_TRY { if (fa) H5FA_close(fa); H5Fclose(file); } H5E_END_TRY; return 1; } /* end test_create() */ /*------------------------------------------------------------------------- * Function: test_reopen * * Purpose: Create & reopen a fixed array * * Return: Success: 0 * Failure: 1 * *------------------------------------------------------------------------- */ static unsigned test_reopen(hid_t fapl, H5FA_create_t *cparam, farray_test_param_t *tparam) { hid_t file = -1; /* File ID */ H5F_t *f = NULL; /* Internal file object pointer */ H5FA_t *fa = NULL; /* Fixed array wrapper */ haddr_t fa_addr = HADDR_UNDEF; /* Array address in file */ /* Create file & retrieve pointer to internal file object */ if (create_file(fapl, &file, &f) < 0) TEST_ERROR /* * Display testing message */ TESTING("create, close & reopen fixed array"); /* Create array */ if (create_array(f, cparam, &fa, &fa_addr) < 0) TEST_ERROR /* Close the fixed array */ if (H5FA_close(fa) < 0) FAIL_STACK_ERROR /* Check for closing & re-opening the file */ if (reopen_file(&file, &f, fapl, NULL, HADDR_UNDEF, tparam) < 0) TEST_ERROR /* Re-open the array */ if (NULL == (fa = H5FA_open(f, fa_addr, NULL))) FAIL_STACK_ERROR /* Verify the creation parameters */ if (verify_cparam(fa, cparam) < 0) TEST_ERROR /* Close array, delete array, close file & verify file is empty */ if (finish(file, fapl, f, fa, fa_addr) < 0) TEST_ERROR /* All tests passed */ PASSED(); return 0; error: H5E_BEGIN_TRY { if (fa) H5FA_close(fa); H5Fclose(file); } H5E_END_TRY; return 1; } /* test_reopen() */ /*------------------------------------------------------------------------- * Function: test_open_twice * * Purpose: Open an extensible array twice * * Return: Success: 0 * Failure: 1 * *------------------------------------------------------------------------- */ static unsigned test_open_twice(hid_t fapl_id, H5FA_create_t *cparam, farray_test_param_t *tparam) { hid_t fid = H5I_INVALID_HID; /* File ID */ hid_t fid2 = H5I_INVALID_HID; /* File ID */ H5F_t *f = NULL; /* Internal file object pointer */ H5F_t *f2 = NULL; /* Internal file object pointer */ H5FA_t *fa = NULL; /* Fixed array wrapper */ H5FA_t *fa2 = NULL; /* Fixed array wrapper */ haddr_t fa_addr = HADDR_UNDEF; /* Array address in file */ /* Create file & retrieve pointer to internal file object */ if (create_file(fapl_id, &fid, &f) < 0) TEST_ERROR /* Display testing message */ TESTING("open fixed array twice"); /* Create array */ if (create_array(f, cparam, &fa, &fa_addr) < 0) TEST_ERROR /* Open the array again, through the first file handle */ if (NULL == (fa2 = H5FA_open(f, fa_addr, NULL))) FAIL_STACK_ERROR /* Verify the creation parameters */ if (verify_cparam(fa, cparam) < 0) TEST_ERROR if (verify_cparam(fa2, cparam) < 0) TEST_ERROR /* Close the second fixed array wrapper */ if (H5FA_close(fa2) < 0) FAIL_STACK_ERROR fa2 = NULL; /* Check for closing & re-opening the file */ if (reopen_file(&fid, &f, fapl_id, &fa, fa_addr, tparam) < 0) TEST_ERROR /* Re-open the file */ if ((fid2 = H5Freopen(fid)) < 0) FAIL_STACK_ERROR /* Get a pointer to the internal file object */ if (NULL == (f2 = (H5F_t *)H5VL_object(fid2))) FAIL_STACK_ERROR; /* Open the fixed array through the second file handle */ if (NULL == (fa2 = H5FA_open(f2, fa_addr, NULL))) FAIL_STACK_ERROR /* Verify the creation parameters */ if (verify_cparam(fa, cparam) < 0) TEST_ERROR /* Close the first extensible array wrapper */ if (H5FA_close(fa) < 0) FAIL_STACK_ERROR fa = NULL; /* Close the first file */ /* (close before second file, to detect error on internal array header's * shared file information) */ if (H5Fclose(fid) < 0) FAIL_STACK_ERROR /* Close array, delete array, close file & verify file is empty */ if (finish(fid2, fapl_id, f2, fa2, fa_addr) < 0) TEST_ERROR /* All tests passed */ PASSED(); return 0; error: H5E_BEGIN_TRY { if (fa) H5FA_close(fa); if (fa2) H5FA_close(fa2); H5Fclose(fid); H5Fclose(fid2); } H5E_END_TRY; return 1; } /* test_open_twice() */ /*------------------------------------------------------------------------- * Function: test_open_twice_diff * * Purpose: Open a fixed array twice, through different "top" file * handles, with an intermediate file open that takes the "shared" * file handle from the first fixed array's file pointer. * * Return: Success: 0 * Failure: 1 * * Programmer: Quincey Koziol * Friday, December 18, 2015 * *------------------------------------------------------------------------- */ static unsigned test_open_twice_diff(hid_t fapl_id, H5FA_create_t *cparam, farray_test_param_t *tparam) { char filename_tmp[FARRAY_FILENAME_LEN]; /* Temporary file name */ hid_t fid = H5I_INVALID_HID; /* File ID */ hid_t fid2 = H5I_INVALID_HID; /* File ID */ hid_t fid0 = H5I_INVALID_HID; /* File ID */ hid_t fid00 = H5I_INVALID_HID; /* File ID */ H5F_t *f = NULL; /* Internal file object pointer */ H5F_t *f2 = NULL; /* Internal file object pointer */ H5FA_t *fa = NULL; /* Fixed array wrapper */ H5FA_t *fa2 = NULL; /* Fixed array wrapper */ haddr_t fa_addr = HADDR_UNDEF; /* Array address in file */ /* Display testing message */ TESTING("open fixed array twice, through different file handles"); /* Create file & retrieve pointer to internal file object */ if (create_file(fapl_id, &fid, &f) < 0) TEST_ERROR /* Create array */ if (create_array(f, cparam, &fa, &fa_addr) < 0) TEST_ERROR /* Open the array again, through the first file handle */ if (NULL == (fa2 = H5FA_open(f, fa_addr, NULL))) FAIL_STACK_ERROR /* Verify the creation parameters */ if (verify_cparam(fa, cparam) < 0) TEST_ERROR if (verify_cparam(fa2, cparam) < 0) TEST_ERROR /* Close the second fixed array wrapper */ if (H5FA_close(fa2) < 0) FAIL_STACK_ERROR fa2 = NULL; /* Re-open the file */ /* (So that there is something holding the file open when the extensible * array is closed) */ if ((fid0 = H5Fopen(filename_g, H5F_ACC_RDWR, fapl_id)) < 0) FAIL_STACK_ERROR /* Check for closing & re-opening the file */ if (reopen_file(&fid, &f, fapl_id, &fa, fa_addr, tparam) < 0) TEST_ERROR /* Close the first fixed array wrapper */ if (H5FA_close(fa) < 0) FAIL_STACK_ERROR fa = NULL; /* Close the first file */ /* (close before second file, to detect error on internal array header's * shared file information) */ if (H5Fclose(fid) < 0) FAIL_STACK_ERROR fid = H5I_INVALID_HID; /* Open a different file */ /* (This re-allocates the 'top' file pointer and assigns it a different * 'shared' file pointer, making the file pointer in the fixed array's * header stale) */ h5_fixname(FILENAME[1], fapl_id, filename_tmp, sizeof(filename_tmp)); if ((fid00 = H5Fcreate(filename_tmp, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0) FAIL_STACK_ERROR /* Re-open the file with the fixed array */ if ((fid2 = H5Fopen(filename_g, H5F_ACC_RDWR, fapl_id)) < 0) FAIL_STACK_ERROR /* Get a pointer to the internal file object */ if (NULL == (f2 = (H5F_t *)H5VL_object(fid2))) FAIL_STACK_ERROR; /* Open the fixed array through the second file handle */ if (NULL == (fa2 = H5FA_open(f2, fa_addr, NULL))) FAIL_STACK_ERROR /* Verify the creation parameters */ if (verify_cparam(fa2, cparam) < 0) TEST_ERROR /* Close the extra file handles */ if (H5Fclose(fid0) < 0) FAIL_STACK_ERROR if (H5Fclose(fid00) < 0) FAIL_STACK_ERROR /* Close array, delete array, close file & verify file is empty */ if (finish(fid2, fapl_id, f2, fa2, fa_addr) < 0) TEST_ERROR /* All tests passed */ PASSED(); return 0; error: H5E_BEGIN_TRY { if (fa) H5FA_close(fa); if (fa2) H5FA_close(fa2); H5Fclose(fid); H5Fclose(fid2); H5Fclose(fid0); H5Fclose(fid00); } H5E_END_TRY; return 1; } /* test_open_twice_diff() */ /*------------------------------------------------------------------------- * Function: test_delete_open * * Purpose: Delete opened fixed array (& open deleted array) * * Return: Success: 0 * Failure: 1 * *------------------------------------------------------------------------- */ static unsigned test_delete_open(hid_t fapl, H5FA_create_t *cparam, farray_test_param_t *tparam) { hid_t file = -1; /* File ID */ H5F_t *f = NULL; /* Internal file object pointer */ H5FA_t *fa = NULL; /* Fixed array wrapper */ H5FA_t *fa2 = NULL; /* Fixed array wrapper */ haddr_t fa_addr = HADDR_UNDEF; /* Array address in file */ h5_stat_size_t file_size; /* File size, after deleting array */ /* Create file & retrieve pointer to internal file object */ if (create_file(fapl, &file, &f) < 0) TEST_ERROR /* * Display testing message */ TESTING("deleting open fixed array"); /* Create array */ if (create_array(f, cparam, &fa, &fa_addr) < 0) TEST_ERROR /* Open the array again */ if (NULL == (fa2 = H5FA_open(f, fa_addr, NULL))) FAIL_STACK_ERROR /* Request that the array be deleted */ if (H5FA_delete(f, fa_addr, NULL) < 0) FAIL_STACK_ERROR /* Verify the creation parameters */ if (verify_cparam(fa, cparam) < 0) TEST_ERROR if (verify_cparam(fa2, cparam) < 0) TEST_ERROR /* Close the second fixed array wrapper */ if (H5FA_close(fa2) < 0) FAIL_STACK_ERROR fa2 = NULL; /* Try re-opening the array again (should fail, as array will be deleted) */ H5E_BEGIN_TRY { fa2 = H5FA_open(f, fa_addr, NULL); } H5E_END_TRY; if (fa2) { /* Close opened array */ H5FA_close(fa2); /* Indicate error */ TEST_ERROR } /* end if */ /* Close the first fixed array wrapper */ if (H5FA_close(fa) < 0) FAIL_STACK_ERROR fa = NULL; /* Check for closing & re-opening the file */ if (reopen_file(&file, &f, fapl, NULL, HADDR_UNDEF, tparam) < 0) TEST_ERROR /* Try re-opening the array again (should fail, as array is now deleted) */ H5E_BEGIN_TRY { fa = H5FA_open(f, fa_addr, NULL); } H5E_END_TRY; if (fa) { /* Close opened array */ H5FA_close(fa); /* Indicate error */ TEST_ERROR } /* end if */ /* Close the file */ if (H5Fclose(file) < 0) FAIL_STACK_ERROR /* Get the size of the file */ if ((file_size = h5_get_file_size(filename_g, fapl)) < 0) TEST_ERROR /* Verify the file is correct size */ if (file_size != empty_size_g) TEST_ERROR /* All tests passed */ PASSED(); return 0; error: H5E_BEGIN_TRY { if (fa) H5FA_close(fa); if (fa2) H5FA_close(fa2); H5Fclose(file); } H5E_END_TRY; return 1; } /* test_delete_open() */ /* Fixed array iterator info for forward iteration */ typedef struct fiter_fw_t { hsize_t idx; /* Index of next array location */ } fiter_fw_t; /*------------------------------------------------------------------------- * Function: fiter_fw_init * * Purpose: Initialize element iterator (forward iteration) * * Return: Success: Pointer to iteration status object * Failure: NULL * *------------------------------------------------------------------------- */ static void * fiter_fw_init(const H5FA_create_t H5_ATTR_UNUSED *cparam, const farray_test_param_t H5_ATTR_UNUSED *tparam, hsize_t H5_ATTR_UNUSED cnt) { fiter_fw_t *fiter; /* Forward element iteration object */ /* Allocate space for the element iteration object */ fiter = (fiter_fw_t *)HDmalloc(sizeof(fiter_fw_t)); HDassert(fiter); /* Initialize the element iteration object */ fiter->idx = 0; /* Return iteration object */ return (fiter); } /* end fiter_fw_init() */ /*------------------------------------------------------------------------- * Function: fiter_fw_next * * Purpose: Get next element index (forward iteration) * * Return: Success: Non-negative * Failure: Negative * *------------------------------------------------------------------------- */ static hssize_t fiter_fw_next(void *_fiter) { fiter_fw_t *fiter = (fiter_fw_t *)_fiter; hssize_t ret_val; /* Sanity check */ HDassert(fiter); /* Get the next array index to test */ ret_val = (hssize_t)fiter->idx++; return (ret_val); } /* end fiter_fw_next() */ /*------------------------------------------------------------------------- * Function: fiter_term * * Purpose: Shut down element iterator (simple iterators) * * Return: Success: 0 * Failure: -1 * *------------------------------------------------------------------------- */ static int fiter_term(void *fiter) { /* Sanity check */ HDassert(fiter); /* Free iteration object */ HDfree(fiter); return (0); } /* end fiter_term() */ /* Fixed array iterator class for forward iteration */ static const farray_iter_t fa_iter_fw = { fiter_fw_init, /* Iterator init */ fiter_fw_next, /* Next array index */ fiter_term /* Iterator term */ }; /* Fixed array iterator info for reverse iteration */ typedef struct fiter_rv_t { hsize_t idx; /* Index of next array location */ } fiter_rv_t; /*------------------------------------------------------------------------- * Function: fiter_rv_init * * Purpose: Initialize element iterator (reverse iteration) * * Return: Success: Pointer to iteration status object * Failure: NULL * *------------------------------------------------------------------------- */ static void * fiter_rv_init(const H5FA_create_t *cparam, const farray_test_param_t H5_ATTR_UNUSED *tparam, hsize_t H5_ATTR_UNUSED cnt) { fiter_rv_t *fiter; /* Reverse element iteration object */ /* Allocate space for the element iteration object */ fiter = (fiter_rv_t *)HDmalloc(sizeof(fiter_rv_t)); HDassert(fiter); /* Initialize reverse iteration info */ fiter->idx = cparam->nelmts - 1; /* Return iteration object */ return (fiter); } /* end fiter_rv_init() */ /*------------------------------------------------------------------------- * Function: fiter_rv_next * * Purpose: Get next element index (reverse iteration) * * Return: Success: Non-negative * Failure: Negative * *------------------------------------------------------------------------- */ static hssize_t fiter_rv_next(void *_fiter) { fiter_rv_t *fiter = (fiter_rv_t *)_fiter; hssize_t ret_val; /* Sanity check */ HDassert(fiter); /* Get the next array index to test */ ret_val = (hssize_t)fiter->idx--; return (ret_val); } /* end fiter_rv_next() */ /* Fixed array iterator class for reverse iteration */ static const farray_iter_t fa_iter_rv = { fiter_rv_init, /* Iterator init */ fiter_rv_next, /* Next array index */ fiter_term /* Iterator term */ }; /* Fixed array iterator info for random iteration */ typedef struct fiter_rnd_t { hsize_t pos; /* Position in shuffled array */ hsize_t *idx; /* Array of shuffled indices */ } fiter_rnd_t; /*------------------------------------------------------------------------- * Function: fiter_rnd_init * * Purpose: Initialize element iterator (random iteration) * * Return: Success: Pointer to iteration status object * Failure: NULL * *------------------------------------------------------------------------- */ static void * fiter_rnd_init(const H5FA_create_t H5_ATTR_UNUSED *cparam, const farray_test_param_t H5_ATTR_UNUSED *tparam, hsize_t cnt) { fiter_rnd_t *fiter; /* Random element iteration object */ size_t u; /* Local index variable */ /* Allocate space for the element iteration object */ fiter = (fiter_rnd_t *)HDmalloc(sizeof(fiter_rnd_t)); HDassert(fiter); /* Allocate space for the array of shuffled indices */ fiter->idx = (hsize_t *)HDmalloc(sizeof(hsize_t) * (size_t)cnt); HDassert(fiter->idx); /* Initialize reverse iteration info */ fiter->pos = 0; for (u = 0; u < (size_t)cnt; u++) fiter->idx[u] = (hsize_t)u; /* Randomly shuffle array indices */ if (cnt > 1) { for (u = 0; u < (size_t)cnt; u++) { size_t swap_idx; /* Location to swap with when shuffling */ hsize_t temp_idx; /* Temporary index */ swap_idx = ((size_t)HDrandom() % ((size_t)cnt - u)) + u; temp_idx = fiter->idx[u]; fiter->idx[u] = fiter->idx[swap_idx]; fiter->idx[swap_idx] = temp_idx; } /* end for */ } /* end if */ /* Return iteration object */ return (fiter); } /* end fiter_rnd_init() */ /*------------------------------------------------------------------------- * Function: fiter_rnd_next * * Purpose: Get next element index (random iteration) * * Return: Success: Non-negative * Failure: Negative * *------------------------------------------------------------------------- */ static hssize_t fiter_rnd_next(void *_fiter) { fiter_rnd_t *fiter = (fiter_rnd_t *)_fiter; hssize_t ret_val; /* Sanity check */ HDassert(fiter); /* Get the next array index to test */ ret_val = (hssize_t)fiter->idx[fiter->pos]; fiter->pos++; return (ret_val); } /* end fiter_rnd_next() */ /*------------------------------------------------------------------------- * Function: fiter_rnd_term * * Purpose: Shut down element iterator (random iteration) * * Return: Success: 0 * Failure: -1 * *------------------------------------------------------------------------- */ static int fiter_rnd_term(void *_fiter) { fiter_rnd_t *fiter = (fiter_rnd_t *)_fiter; /* Sanity check */ HDassert(fiter); HDassert(fiter->idx); /* Free shuffled index array */ HDfree(fiter->idx); /* Free iteration object */ HDfree(fiter); return (0); } /* end fiter_rnd_term() */ /* Fixed array iterator class for random iteration */ static const farray_iter_t fa_iter_rnd = { fiter_rnd_init, /* Iterator init */ fiter_rnd_next, /* Next array index */ fiter_rnd_term /* Iterator term */ }; /* Fixed array iterator info for cyclic iteration */ typedef struct fiter_cyc_t { hsize_t pos; /* Position in shuffled array */ hsize_t cnt; /* # of elements to store */ hsize_t cyc; /* Cycle of elements to choose from */ } fiter_cyc_t; /*------------------------------------------------------------------------- * Function: fiter_cyc_init * * Purpose: Initialize element iterator (cyclic iteration) * * Return: Success: Pointer to iteration status object * Failure: NULL * *------------------------------------------------------------------------- */ static void * fiter_cyc_init(const H5FA_create_t H5_ATTR_UNUSED *cparam, const farray_test_param_t H5_ATTR_UNUSED *tparam, hsize_t cnt) { fiter_cyc_t *fiter; /* Cyclic element iteration object */ /* Allocate space for the element iteration object */ fiter = (fiter_cyc_t *)HDmalloc(sizeof(fiter_cyc_t)); HDassert(fiter); /* Initialize reverse iteration info */ fiter->pos = 0; fiter->cnt = cnt; fiter->cyc = 0; /* Return iteration object */ return (fiter); } /* end fiter_cyc_init() */ /*------------------------------------------------------------------------- * Function: fiter_cyc_next * * Purpose: Get next element index (cyclic iteration) * * Return: Success: Non-negative * Failure: Negative * *------------------------------------------------------------------------- */ static hssize_t fiter_cyc_next(void *_fiter) { fiter_cyc_t *fiter = (fiter_cyc_t *)_fiter; hssize_t ret_val; /* Sanity check */ HDassert(fiter); /* Get the next array index to test */ ret_val = (hssize_t)fiter->pos; fiter->pos += FA_CYC_COUNT; if (fiter->pos >= fiter->cnt) fiter->pos = ++fiter->cyc; return (ret_val); } /* end fiter_cyc_next() */ /* Fixed array iterator class for cyclic iteration */ static const farray_iter_t fa_iter_cyc = { fiter_cyc_init, /* Iterator init */ fiter_cyc_next, /* Next array index */ fiter_term /* Iterator term */ }; /*------------------------------------------------------------------------- * Function: check_elmt * * Purpose: Check whether _relmt is the same as in _welmt * * Return: Success: 0 * Failure: 1 * * Programmer: Vailin Choi; 6th August, 2009 * *------------------------------------------------------------------------- */ static int check_elmt(void *_relmt, void *_welmt) { uint64_t *relmt = (uint64_t *)_relmt; uint64_t *welmt = (uint64_t *)_welmt; if (welmt == NULL) { /* check for fill value */ if (*relmt != H5FA_TEST_FILL) TEST_ERROR } /* end if */ else { if (*relmt != *welmt) TEST_ERROR } /* end else */ return (0); error: return (-1); } /* end check_elmt() */ /*------------------------------------------------------------------------- * Function: test_set_elmts * * Purpose: Set all elements from 0 to ('nelmts' - 1) in fixed array * ("nelmts" is the # of elements to be set in the fixed array) * * Return: Success: 0 * Failure: 1 * *------------------------------------------------------------------------- */ static unsigned test_set_elmts(hid_t fapl, H5FA_create_t *cparam, farray_test_param_t *tparam, hsize_t nelmts, const char *test_str) { hid_t file = -1; /* File ID */ H5F_t *f = NULL; /* Internal file object pointer */ H5FA_t *fa = NULL; /* Fixed array wrapper */ void *fiter_info; /* Fixed array iterator info */ farray_state_t state; /* State of fixed array */ uint64_t welmt; /* Element to write */ uint64_t relmt; /* Element to read */ hsize_t cnt; /* Count of array indices */ hssize_t sidx; /* Index value of next element in the fixed array */ hsize_t idx; /* Index value of next element in the fixed array */ hsize_t fa_nelmts; /* # of elements in fixed array */ haddr_t fa_addr = HADDR_UNDEF; /* Array address in file */ HDassert(nelmts); /* * Display testing message */ TESTING(test_str); /* Create file & retrieve pointer to internal file object */ if (create_file(fapl, &file, &f) < 0) TEST_ERROR /* Create array */ if (create_array(f, cparam, &fa, &fa_addr) < 0) TEST_ERROR /* Verify the creation parameters */ if (verify_cparam(fa, cparam) < 0) TEST_ERROR /* Check for closing & re-opening the file */ if (reopen_file(&file, &f, fapl, &fa, fa_addr, tparam) < 0) TEST_ERROR if (H5FA_get_nelmts(fa, &fa_nelmts) < 0) FAIL_STACK_ERROR if (nelmts > fa_nelmts) TEST_ERROR /* Verify array state */ HDmemset(&state, 0, sizeof(state)); state.hdr_size = FA_HDR_SIZE; state.nelmts = cparam->nelmts; state.dblk_size = 0; if (check_stats(fa, &state)) TEST_ERROR /* Get all elements from empty array */ /* Initialize iterator */ if (NULL == (fiter_info = tparam->fiter->init(cparam, tparam, nelmts))) TEST_ERROR /* Get elements of array */ for (cnt = 0; cnt < nelmts; cnt++) { /* Get the array index */ if ((sidx = tparam->fiter->next(fiter_info)) < 0) TEST_ERROR idx = (hsize_t)sidx; /* Retrieve element of array (not set yet) */ relmt = (uint64_t)0; if (H5FA_get(fa, idx, &relmt) < 0) FAIL_STACK_ERROR /* Verify that the retrieved is correct */ if (check_elmt(&relmt, NULL)) TEST_ERROR } /* end for */ /* Shutdown iterator */ if (tparam->fiter->term(fiter_info) < 0) TEST_ERROR /* Set (& get) all elements from empty array */ /* Initialize iterator */ if (NULL == (fiter_info = tparam->fiter->init(cparam, tparam, nelmts))) TEST_ERROR /* Set elements of array */ for (cnt = 0; cnt < nelmts; cnt++) { /* Get the array index */ if ((sidx = tparam->fiter->next(fiter_info)) < 0) TEST_ERROR idx = (hsize_t)sidx; relmt = (uint64_t)0; if (H5FA_get(fa, idx, &relmt) < 0) FAIL_STACK_ERROR /* Verify that the retrieved element is correct */ if (check_elmt(&relmt, NULL)) TEST_ERROR /* Set element of array */ welmt = (uint64_t)7 + idx; if (H5FA_set(fa, idx, &welmt) < 0) FAIL_STACK_ERROR /* Retrieve element of array (set now) */ relmt = (uint64_t)0; if (H5FA_get(fa, idx, &relmt) < 0) FAIL_STACK_ERROR /* Verify that the retrieved element is correct */ if (check_elmt(&relmt, &welmt)) TEST_ERROR } /* end for */ /* Verify array state */ HDmemset(&state, 0, sizeof(state)); set_fa_state(cparam, &state); if (check_stats(fa, &state)) TEST_ERROR /* Shutdown iterator */ if (tparam->fiter->term(fiter_info) < 0) TEST_ERROR /* Close array, delete array, close file & verify file is empty */ if (finish(file, fapl, f, fa, fa_addr) < 0) TEST_ERROR /* All tests passed */ PASSED(); return 0; error: H5E_BEGIN_TRY { if (fa) H5FA_close(fa); H5Fclose(file); } H5E_END_TRY; return 1; } /* test_set_elmts() */ /*------------------------------------------------------------------------- * Function: test_skip_elmts * * Purpose: Set the element "skip_elmts" in the fixed array * ("skip_elmts" is the index of the fixed array to be set.) * * Return: Success: 0 * Failure: 1 * *------------------------------------------------------------------------- */ static unsigned test_skip_elmts(hid_t fapl, H5FA_create_t *cparam, farray_test_param_t *tparam, hsize_t skip_elmts, hbool_t check_rest, const char *test_str) { hid_t file = -1; /* File ID */ H5F_t *f = NULL; /* Internal file object pointer */ H5FA_t *fa = NULL; /* Extensible array wrapper */ farray_state_t state; /* State of extensible array */ uint64_t welmt; /* Element to write */ uint64_t relmt; /* Element to read */ hsize_t idx; /* Index value of element to get */ hsize_t cnt; /* Count of array indices */ hsize_t fa_nelmts; /* # of elements in fixed array */ haddr_t fa_addr = HADDR_UNDEF; /* Array address in file */ /* * Display testing message */ TESTING(test_str); /* Create file & retrieve pointer to internal file object */ if (create_file(fapl, &file, &f) < 0) TEST_ERROR /* Create array */ if (create_array(f, cparam, &fa, &fa_addr) < 0) TEST_ERROR /* Verify the creation parameters */ if (verify_cparam(fa, cparam) < 0) TEST_ERROR /* Check for closing & re-opening the file */ if (reopen_file(&file, &f, fapl, &fa, fa_addr, tparam) < 0) TEST_ERROR if (H5FA_get_nelmts(fa, &fa_nelmts) < 0) FAIL_STACK_ERROR if (skip_elmts >= fa_nelmts) TEST_ERROR /* Verify array state */ HDmemset(&state, 0, sizeof(state)); state.hdr_size = FA_HDR_SIZE; state.nelmts = cparam->nelmts; state.dblk_size = 0; if (check_stats(fa, &state)) TEST_ERROR /* Set (& get) element after skipping elements */ idx = skip_elmts; /* Retrieve element of array (not set yet) */ relmt = (uint64_t)0; if (H5FA_get(fa, idx, &relmt) < 0) FAIL_STACK_ERROR /* Verify that the retrieved is correct */ if (check_elmt(&relmt, NULL)) TEST_ERROR /* Set element of array */ welmt = (uint64_t)7 + idx; if (H5FA_set(fa, idx, &welmt) < 0) FAIL_STACK_ERROR /* Verify array state */ HDmemset(&state, 0, sizeof(state)); set_fa_state(cparam, &state); if (check_stats(fa, &state)) TEST_ERROR /* Retrieve element of array (set now) */ relmt = (uint64_t)0; if (H5FA_get(fa, idx, &relmt) < 0) FAIL_STACK_ERROR /* Verify that the retrieved is correct */ if (check_elmt(&relmt, &welmt)) TEST_ERROR if (check_rest) { /* Get unset elements of array */ for (cnt = 0; cnt < skip_elmts; cnt++) { /* Retrieve element of array (not set yet) */ relmt = (uint64_t)0; if (H5FA_get(fa, cnt, &relmt) < 0) FAIL_STACK_ERROR /* Verify that the retrieved is correct */ if (check_elmt(&relmt, NULL)) TEST_ERROR } /* end for */ } /* end if */ /* Close array, delete array, close file & verify file is empty */ if (finish(file, fapl, f, fa, fa_addr) < 0) TEST_ERROR /* All tests passed */ PASSED(); return 0; error: H5E_BEGIN_TRY { if (fa) H5FA_close(fa); H5Fclose(file); } H5E_END_TRY; return 1; } /* test_skip_elmts() */ /*------------------------------------------------------------------------- * Function: main * * Purpose: Test the fixed array code * * Return: Success: 0 * Failure: 1 * *------------------------------------------------------------------------- */ int main(void) { H5FA_create_t cparam; /* Creation parameters for fixed array */ farray_test_param_t tparam; /* Testing parameters */ farray_test_type_t curr_test; /* Current test being worked on */ farray_iter_type_t curr_iter; /* Current iteration type being worked on */ hid_t fapl = -1; /* File access property list for data files */ unsigned nerrors = 0; /* Cumulative error count */ time_t curr_time; /* Current time, for seeding random number generator */ int ExpressMode; /* Test express value */ hbool_t api_ctx_pushed = FALSE; /* Whether API context pushed */ /* Reset library */ h5_reset(); fapl = h5_fileaccess(); ExpressMode = GetTestExpress(); if (ExpressMode > 1) HDprintf("***Express test mode on. Some tests may be skipped\n"); /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename_g, sizeof(filename_g)); /* Push API context */ if (H5CX_push() < 0) FAIL_STACK_ERROR api_ctx_pushed = TRUE; /* Seed random #'s */ curr_time = HDtime(NULL); HDsrandom((unsigned)curr_time); /* Create an empty file to retrieve size */ { hid_t file; /* File ID */ if ((file = H5Fcreate(filename_g, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) FAIL_STACK_ERROR /* Close file */ if (H5Fclose(file) < 0) FAIL_STACK_ERROR /* Get the size of a file w/no array */ if ((empty_size_g = h5_get_file_size(filename_g, fapl)) < 0) TEST_ERROR } /* Iterate over the testing parameters */ for (curr_test = FARRAY_TEST_NORMAL; curr_test < FARRAY_TEST_NTESTS; curr_test++) { /* Initialize the testing parameters */ HDmemset(&tparam, 0, sizeof(tparam)); tparam.nelmts = TEST_NELMTS; /* Set appropriate testing parameters for each test */ switch (curr_test) { /* "Normal" testing parameters */ case FARRAY_TEST_NORMAL: HDputs("Testing with NORMAL PARAMETERS"); break; /* "Re-open array" testing parameters */ case FARRAY_TEST_REOPEN: HDputs("Testing with reopen array flag set"); tparam.reopen_array = FARRAY_TEST_REOPEN; break; /* An unknown test? */ case FARRAY_TEST_NTESTS: default: goto error; } /* end switch */ /* Initialize fixed array creation parameters */ init_cparam(&cparam, &tparam); /* Basic capability tests */ nerrors += test_create(fapl, &cparam, &tparam); nerrors += test_reopen(fapl, &cparam, &tparam); nerrors += test_open_twice(fapl, &cparam, &tparam); nerrors += test_open_twice_diff(fapl, &cparam, &tparam); nerrors += test_delete_open(fapl, &cparam, &tparam); /* Iterate over the type of capacity tests */ for (curr_iter = FARRAY_ITER_FW; curr_iter < FARRAY_ITER_NITERS; curr_iter++) { /* Set appropriate parameters for each type of iteration */ switch (curr_iter) { /* "Forward" testing parameters */ case FARRAY_ITER_FW: HDputs("Testing with forward iteration"); tparam.fiter = &fa_iter_fw; break; /* "Reverse" testing parameters */ case FARRAY_ITER_RV: HDputs("Testing with reverse iteration"); tparam.fiter = &fa_iter_rv; break; /* "Random" testing parameters */ case FARRAY_ITER_RND: HDputs("Testing with random iteration"); tparam.fiter = &fa_iter_rnd; break; /* "Cyclic" testing parameters */ case FARRAY_ITER_CYC: HDputs("Testing with cyclic iteration"); tparam.fiter = &fa_iter_cyc; break; /* An unknown iteration? */ case FARRAY_ITER_NITERS: default: goto error; } /* end switch */ /* Basic capacity tests */ nerrors += test_set_elmts(fapl, &cparam, &tparam, (hsize_t)1, "setting 1 element of the array"); nerrors += test_set_elmts(fapl, &cparam, &tparam, (hsize_t)(tparam.nelmts / 2), "setting half of the array's elements "); nerrors += test_set_elmts(fapl, &cparam, &tparam, (hsize_t)tparam.nelmts, "setting all the array elements"); } /* end for */ /* Check skipping elements */ nerrors += test_skip_elmts(fapl, &cparam, &tparam, (hsize_t)1, TRUE, "skipping to first element"); nerrors += test_skip_elmts(fapl, &cparam, &tparam, ((hsize_t)1 << cparam.max_dblk_page_nelmts_bits), TRUE, "skipping to first element in data block page"); nerrors += test_skip_elmts(fapl, &cparam, &tparam, (hsize_t)(tparam.nelmts - 1), TRUE, "skipping to last element"); /* Create Fixed Array */ /* MAX_NELMTS succeeds on some platforms buy may fail on others: * * "H5FD_sec2_truncate(): unable to extend file properly" * * and * * "H5FD_sec2_truncate(): File too large" * * have both been seen. */ tparam.nelmts = MAX_NELMTS / 17; init_cparam(&cparam, &tparam); /* Set the last element in the Fixed Array */ nerrors += test_skip_elmts(fapl, &cparam, &tparam, (hsize_t)(tparam.nelmts - 1), FALSE, "skipping to last element"); } /* end for */ /* Verify symbol table messages are cached */ nerrors += (h5_verify_cached_stabs(FILENAME, fapl) < 0 ? 1 : 0); /* Pop API context */ if (api_ctx_pushed && H5CX_pop() < 0) FAIL_STACK_ERROR api_ctx_pushed = FALSE; if (nerrors) goto error; HDputs("All fixed array tests passed."); /* Clean up file used */ h5_cleanup(FILENAME, fapl); HDexit(EXIT_SUCCESS); error: HDputs("*** TESTS FAILED ***"); H5E_BEGIN_TRY { H5Pclose(fapl); } H5E_END_TRY; if (api_ctx_pushed) H5CX_pop(); HDexit(EXIT_FAILURE); } /* end main() */