mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-12-27 08:01:04 +08:00
58f3d6664e
lseek on Windows uses __int64 for both the offset and return type instead of off_t like most POSIX systems. This changes ensures we use HDoff_t (which is typdef'd correctly on Windows) w/ lseek.
1386 lines
47 KiB
C
1386 lines
47 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* 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: file_image
|
|
*
|
|
* Test setting file images
|
|
*
|
|
*************************************************************/
|
|
|
|
#include "h5test.h"
|
|
#include "H5Fprivate.h" /* required to test property removals */
|
|
#define VERIFY(condition, string) \
|
|
do { \
|
|
if (!(condition)) \
|
|
FAIL_PUTS_ERROR(string); \
|
|
} while (0)
|
|
|
|
/* Values for callback bit field */
|
|
#define MALLOC 0x01
|
|
#define MEMCPY 0x02
|
|
#define REALLOC 0x04
|
|
#define FREE 0x08
|
|
#define UDATA_COPY 0x10
|
|
#define UDATA_FREE 0x20
|
|
|
|
#define RANK 2
|
|
#define DIM0 1024
|
|
#define DIM1 32
|
|
#define DSET_NAME "test_dset"
|
|
|
|
#define FAMILY_SIZE (2 * 1024)
|
|
|
|
#define USERBLOCK_SIZE 512
|
|
|
|
static const char *FILENAME[] = {"file_image_core_test", NULL};
|
|
|
|
/* need a second file name array, as the first file name array contains
|
|
* files we don't want to delete on cleanup.
|
|
*/
|
|
static const char *FILENAME2[] = {"sec2_get_file_image_test",
|
|
"stdio_get_file_image_test",
|
|
"core_get_file_image_test",
|
|
"family_get_file_image_test",
|
|
"multi_get_file_image_test",
|
|
"split_get_file_image_test",
|
|
"get_file_image_error_rejection_test",
|
|
NULL};
|
|
|
|
typedef struct {
|
|
unsigned char used_callbacks; /* Bitfield for tracking callbacks */
|
|
H5FD_file_image_op_t malloc_src; /* Source of file image callbacks */
|
|
H5FD_file_image_op_t memcpy_src;
|
|
H5FD_file_image_op_t realloc_src;
|
|
H5FD_file_image_op_t free_src;
|
|
} udata_t;
|
|
|
|
/******************************************************************************
|
|
* Function: test_properties
|
|
*
|
|
* Purpose: Tests that the file image properties (buffer pointer and length)
|
|
* are set properly. Image callbacks are not set in this test.
|
|
*
|
|
* Returns: Success: 0
|
|
* Failure: 1
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
static int
|
|
test_properties(void)
|
|
{
|
|
hid_t fapl_1 = H5I_INVALID_HID;
|
|
hid_t fapl_2 = H5I_INVALID_HID;
|
|
char *buffer = 0;
|
|
int count = 10;
|
|
void *temp = 0;
|
|
char *temp2 = 0;
|
|
int i;
|
|
size_t size;
|
|
size_t temp_size;
|
|
int retval = 1;
|
|
|
|
TESTING("File image property list functions");
|
|
|
|
/* Initialize file image buffer
|
|
*
|
|
* Note: this image will not contain a valid HDF5 file, as it complicates testing
|
|
* property list functions. In the file driver tests further down, this will
|
|
* not be the case.
|
|
*/
|
|
size = (size_t)count * sizeof(char);
|
|
if (NULL == (buffer = (char *)malloc(size)))
|
|
TEST_ERROR;
|
|
for (i = 0; i < count - 1; i++)
|
|
buffer[i] = (char)(65 + i);
|
|
buffer[count - 1] = '\0';
|
|
|
|
/* Create fapl */
|
|
if ((fapl_1 = H5Pcreate(H5P_FILE_ACCESS)) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Get file image stuff */
|
|
if (H5Pget_file_image(fapl_1, (void **)&temp, &temp_size) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Check default values */
|
|
VERIFY(temp == NULL, "Default pointer is wrong");
|
|
VERIFY(temp_size == 0, "Default size is wrong");
|
|
|
|
/* Set file image stuff */
|
|
if (H5Pset_file_image(fapl_1, (void *)buffer, size) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Get the same */
|
|
if (H5Pget_file_image(fapl_1, (void **)&temp, &temp_size) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Check that sizes are the same, and that the buffers are identical but separate */
|
|
VERIFY(temp != NULL, "temp is null!");
|
|
VERIFY(temp_size == size, "Sizes of buffers don't match");
|
|
VERIFY(temp != buffer, "Retrieved buffer is the same as original");
|
|
VERIFY(0 == memcmp(temp, buffer, size), "Buffers contain different data");
|
|
|
|
/* Copy the fapl */
|
|
if ((fapl_2 = H5Pcopy(fapl_1)) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Get values from the new fapl */
|
|
if (H5Pget_file_image(fapl_2, (void **)&temp2, &temp_size) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Check that sizes are the same, and that the buffers are identical but separate */
|
|
VERIFY(temp_size == size, "Sizes of buffers don't match");
|
|
VERIFY(temp2 != NULL, "Received buffer not set");
|
|
VERIFY(temp2 != buffer, "Retrieved buffer is the same as original");
|
|
VERIFY(temp2 != temp, "Retrieved buffer is the same as previously retrieved buffer");
|
|
VERIFY(0 == memcmp(temp2, buffer, size), "Buffers contain different data");
|
|
|
|
retval = 0;
|
|
|
|
error:
|
|
|
|
/* Close everything */
|
|
if (H5Pclose(fapl_1) < 0)
|
|
retval = 1;
|
|
if (H5Pclose(fapl_2) < 0)
|
|
retval = 1;
|
|
free(buffer);
|
|
H5free_memory(temp);
|
|
H5free_memory(temp2);
|
|
|
|
if (retval == 0)
|
|
PASSED();
|
|
|
|
return retval;
|
|
} /* end test_properties() */
|
|
|
|
/******************************************************************************
|
|
* Function: malloc_cb
|
|
*
|
|
* Purpose: This function allows calls to the malloc callback to be tracked.
|
|
*
|
|
* Returns: The result of a standard malloc
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
static void *
|
|
malloc_cb(size_t size, H5FD_file_image_op_t op, void *udata)
|
|
{
|
|
udata_t *u = (udata_t *)udata;
|
|
|
|
u->used_callbacks |= MALLOC;
|
|
u->malloc_src = op;
|
|
return malloc(size);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: memcpy_cb
|
|
*
|
|
* Purpose: This function allows calls to the memcpy callback to be tracked.
|
|
*
|
|
* Returns: The result of a standard memcpy
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
static void *
|
|
memcpy_cb(void *dest, const void *src, size_t size, H5FD_file_image_op_t op, void *udata)
|
|
{
|
|
udata_t *u = (udata_t *)udata;
|
|
|
|
u->used_callbacks |= MEMCPY;
|
|
u->memcpy_src = op;
|
|
return memcpy(dest, src, size);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: realloc_cb
|
|
*
|
|
* Purpose: This function allows calls to the realloc callback to be tracked.
|
|
*
|
|
* Returns: The result of a standard realloc
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
static void *
|
|
realloc_cb(void *ptr, size_t size, H5FD_file_image_op_t op, void *udata)
|
|
{
|
|
udata_t *u = (udata_t *)udata;
|
|
|
|
u->used_callbacks |= REALLOC;
|
|
u->realloc_src = op;
|
|
return realloc(ptr, size);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: free_cb
|
|
*
|
|
* Purpose: This function allows calls to the free callback to be tracked.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
static herr_t
|
|
free_cb(void *ptr, H5FD_file_image_op_t op, void *udata)
|
|
{
|
|
udata_t *u = (udata_t *)udata;
|
|
|
|
u->used_callbacks |= FREE;
|
|
u->free_src = op;
|
|
free(ptr);
|
|
return (SUCCEED);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: udata_copy_cb
|
|
*
|
|
* Purpose: This function allows calls to the udata_copy callback to be tracked.
|
|
* No copying actually takes place; it is easier to deal with only one
|
|
* instance of the udata.
|
|
*
|
|
* Returns: A pointer to the same udata that was passed in.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
static void *
|
|
udata_copy_cb(void *udata)
|
|
{
|
|
udata_t *u = (udata_t *)udata;
|
|
|
|
u->used_callbacks |= UDATA_COPY;
|
|
return udata;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: udata_free_cb
|
|
*
|
|
* Purpose: This function allows calls to the udata_free callback to be tracked.
|
|
*
|
|
* Note: this callback doesn't actually do anything. Since the
|
|
* udata_copy callback doesn't copy, only one instance of the udata
|
|
* is kept alive and such it must be freed explicitly at the end of the tests.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
static herr_t
|
|
udata_free_cb(void *udata)
|
|
{
|
|
udata_t *u = (udata_t *)udata;
|
|
|
|
u->used_callbacks |= UDATA_FREE;
|
|
return (SUCCEED);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: reset_udata
|
|
*
|
|
* Purpose: Resets the udata to default values. This facilitates storing only
|
|
* the results of a single operation in the udata.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
static void
|
|
reset_udata(udata_t *u)
|
|
{
|
|
u->used_callbacks = 0;
|
|
u->malloc_src = u->memcpy_src = u->realloc_src = u->free_src = H5FD_FILE_IMAGE_OP_NO_OP;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function: test_callbacks
|
|
*
|
|
* Purpose: Tests that callbacks are called properly in property list functions.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
static int
|
|
test_callbacks(void)
|
|
{
|
|
H5FD_file_image_callbacks_t real_callbacks = {&malloc_cb, &memcpy_cb, &realloc_cb, &free_cb,
|
|
&udata_copy_cb, &udata_free_cb, NULL};
|
|
H5FD_file_image_callbacks_t null_callbacks = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
|
H5FD_file_image_callbacks_t callbacks;
|
|
hid_t fapl_1;
|
|
hid_t fapl_2;
|
|
udata_t *udata = NULL;
|
|
char *file_image = NULL;
|
|
char *temp_file_image;
|
|
int count = 10;
|
|
int i;
|
|
size_t size;
|
|
size_t temp_size;
|
|
|
|
TESTING("Callback use in property list operations");
|
|
|
|
/* Allocate and initialize udata */
|
|
udata = (udata_t *)malloc(sizeof(udata_t));
|
|
VERIFY(udata != NULL, "udata malloc failed");
|
|
reset_udata(udata);
|
|
|
|
/* copy the address of the user data into read_callbacks */
|
|
real_callbacks.udata = (void *)udata;
|
|
|
|
/* Allocate and initialize file image buffer */
|
|
size = (size_t)count * sizeof(char);
|
|
file_image = (char *)malloc(size);
|
|
VERIFY(file_image != NULL, "file_image malloc failed");
|
|
for (i = 0; i < count - 1; i++)
|
|
file_image[i] = (char)(65 + i);
|
|
file_image[count - 1] = '\0';
|
|
|
|
/* Create fapl */
|
|
if ((fapl_1 = H5Pcreate(H5P_FILE_ACCESS)) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Get file image stuff */
|
|
callbacks = real_callbacks;
|
|
if (H5Pget_file_image_callbacks(fapl_1, &callbacks) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Check default values */
|
|
VERIFY(callbacks.image_malloc == NULL, "Default malloc callback is wrong");
|
|
VERIFY(callbacks.image_memcpy == NULL, "Default memcpy callback is wrong");
|
|
VERIFY(callbacks.image_realloc == NULL, "Default realloc callback is wrong");
|
|
VERIFY(callbacks.image_free == NULL, "Default free callback is wrong");
|
|
VERIFY(callbacks.udata_copy == NULL, "Default udata copy callback is wrong");
|
|
VERIFY(callbacks.udata_free == NULL, "Default udata free callback is wrong");
|
|
VERIFY(callbacks.udata == NULL, "Default udata is wrong");
|
|
|
|
/* Set file image callbacks */
|
|
callbacks = real_callbacks;
|
|
if (H5Pset_file_image_callbacks(fapl_1, &callbacks) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Get file image callbacks */
|
|
callbacks = null_callbacks;
|
|
if (H5Pget_file_image_callbacks(fapl_1, &callbacks) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Verify values */
|
|
VERIFY(callbacks.image_malloc == &malloc_cb, "malloc callback was not set or retrieved properly");
|
|
VERIFY(callbacks.image_memcpy == &memcpy_cb, "memcpy callback was not set or retrieved properly");
|
|
VERIFY(callbacks.image_realloc == &realloc_cb, "realloc callback was not set or retrieved properly");
|
|
VERIFY(callbacks.image_free == &free_cb, "free callback was not set or retrieved properly");
|
|
VERIFY(callbacks.udata_copy == &udata_copy_cb, "udata copy callback was not set or retrieved properly");
|
|
VERIFY(callbacks.udata_free == &udata_free_cb, "udata free callback was not set or retrieved properly");
|
|
VERIFY(callbacks.udata == udata, "udata was not set or retrieved properly");
|
|
|
|
/*
|
|
* Check callbacks in internal function without a previously set file image
|
|
*/
|
|
|
|
/* Copy fapl */
|
|
reset_udata(udata);
|
|
if ((fapl_2 = H5Pcopy(fapl_1)) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Verify that the property's copy callback used the correct image callbacks */
|
|
VERIFY(udata->used_callbacks == (UDATA_COPY), "Copying a fapl with no image used incorrect callbacks");
|
|
|
|
/* Close fapl */
|
|
reset_udata(udata);
|
|
if (H5Pclose(fapl_2) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Verify that the udata free callback was used */
|
|
VERIFY(udata->used_callbacks == (UDATA_FREE), "Closing a fapl with no image used incorrect callbacks");
|
|
|
|
/* Copy again */
|
|
if ((fapl_2 = H5Pcopy(fapl_1)) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Remove property from fapl */
|
|
reset_udata(udata);
|
|
if (H5Premove(fapl_2, H5F_ACS_FILE_IMAGE_INFO_NAME) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Verify that the property's delete callback was called using the correct image callbacks */
|
|
VERIFY(udata->used_callbacks == (UDATA_FREE),
|
|
"Removing a property from a fapl with no image used incorrect callbacks");
|
|
|
|
/* Close it again */
|
|
if (H5Pclose(fapl_2) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Get file image */
|
|
reset_udata(udata);
|
|
if (H5Pget_file_image(fapl_1, (void **)&temp_file_image, &temp_size) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Verify that the correct callbacks were used */
|
|
VERIFY(udata->used_callbacks == 0,
|
|
"attempting to retrieve the image from a fapl without an image has an unexpected callback");
|
|
|
|
/* Set file image */
|
|
reset_udata(udata);
|
|
if (H5Pset_file_image(fapl_1, (void *)file_image, size) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
VERIFY(udata->used_callbacks == (MALLOC | MEMCPY),
|
|
"Setting a file image (first time) used incorrect callbacks");
|
|
|
|
/*
|
|
* Check callbacks in internal functions with a previously set file image
|
|
*/
|
|
|
|
/* Copy fapl */
|
|
reset_udata(udata);
|
|
if ((fapl_2 = H5Pcopy(fapl_1)) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Verify that the property's copy callback used the correct image callbacks */
|
|
VERIFY(udata->used_callbacks == (MALLOC | MEMCPY | UDATA_COPY),
|
|
"Copying a fapl with an image used incorrect callbacks");
|
|
VERIFY(udata->malloc_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, "malloc callback has wrong source");
|
|
VERIFY(udata->memcpy_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, "memcpy callback has wrong source");
|
|
|
|
/* Close fapl */
|
|
reset_udata(udata);
|
|
if (H5Pclose(fapl_2) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Verify that the udata free callback was used */
|
|
VERIFY(udata->used_callbacks == (FREE | UDATA_FREE),
|
|
"Closing a fapl with an image used incorrect callbacks");
|
|
VERIFY(udata->free_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, "free callback has wrong source");
|
|
|
|
/* Copy again */
|
|
if ((fapl_2 = H5Pcopy(fapl_1)) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Remove property from fapl */
|
|
reset_udata(udata);
|
|
if (H5Premove(fapl_2, H5F_ACS_FILE_IMAGE_INFO_NAME) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Verify that the property's delete callback was called using the correct image callbacks */
|
|
VERIFY(udata->used_callbacks == (FREE | UDATA_FREE),
|
|
"Removing a property from a fapl with an image used incorrect callbacks");
|
|
VERIFY(udata->free_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, "free callback has wrong source");
|
|
|
|
/* Close it again */
|
|
if (H5Pclose(fapl_2) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Get file image */
|
|
reset_udata(udata);
|
|
if (H5Pget_file_image(fapl_1, (void **)&temp_file_image, &temp_size) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Verify that the correct callbacks were used */
|
|
VERIFY(udata->used_callbacks == (MALLOC | MEMCPY),
|
|
"attempting to retrieve the image from a fapl with an image has an unexpected callback");
|
|
VERIFY(udata->malloc_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, "malloc callback has wrong source");
|
|
VERIFY(udata->memcpy_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, "memcpy callback has wrong source");
|
|
|
|
/* Set file image */
|
|
reset_udata(udata);
|
|
if (H5Pset_file_image(fapl_1, (void *)file_image, size) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
VERIFY(udata->used_callbacks == (FREE | MALLOC | MEMCPY),
|
|
"Setting a file image (second time) used incorrect callbacks");
|
|
VERIFY(udata->malloc_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, "malloc callback has wrong source");
|
|
VERIFY(udata->memcpy_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, "memcpy callback has wrong source");
|
|
VERIFY(udata->free_src == H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, "freec callback has wrong source");
|
|
|
|
/* Close stuff */
|
|
if (H5Pclose(fapl_1) < 0)
|
|
FAIL_STACK_ERROR;
|
|
free(file_image);
|
|
free(temp_file_image);
|
|
free(udata);
|
|
|
|
PASSED();
|
|
return 0;
|
|
|
|
error:
|
|
free(file_image);
|
|
free(udata);
|
|
|
|
return 1;
|
|
} /* test_callbacks() */
|
|
|
|
/******************************************************************************
|
|
* Function: test_core
|
|
*
|
|
* Purpose: Tests that callbacks are called properly in the core VFD and
|
|
* that the initial file image works properly.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
static int
|
|
test_core(void)
|
|
{
|
|
hid_t fapl;
|
|
hid_t file;
|
|
hid_t dset;
|
|
hid_t space;
|
|
udata_t *udata;
|
|
unsigned char *file_image;
|
|
char filename[1024];
|
|
char copied_filename[1024];
|
|
const char *tmp = NULL;
|
|
size_t size;
|
|
hsize_t dims[2];
|
|
int fd;
|
|
h5_stat_t sb;
|
|
herr_t ret;
|
|
H5FD_file_image_callbacks_t callbacks = {&malloc_cb, &memcpy_cb, &realloc_cb, &free_cb,
|
|
&udata_copy_cb, &udata_free_cb, NULL};
|
|
|
|
TESTING("Initial file image and callbacks in Core VFD");
|
|
|
|
/* Create fapl */
|
|
fapl = h5_fileaccess();
|
|
VERIFY(fapl >= 0, "fapl creation failed");
|
|
|
|
/* Set up the core VFD */
|
|
ret = H5Pset_fapl_core(fapl, (size_t)0, 0);
|
|
VERIFY(ret >= 0, "setting core driver in fapl failed");
|
|
|
|
tmp = h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
|
|
VERIFY(tmp != NULL, "h5_fixname failed");
|
|
|
|
/* Append ".copy" to the filename from the source directory */
|
|
VERIFY(strlen(filename) < (1023 - 5), "file name too long.");
|
|
strncpy(copied_filename, filename, (size_t)1023);
|
|
copied_filename[1023] = '\0';
|
|
strcat(copied_filename, ".copy");
|
|
|
|
/* Make a copy of the data file from svn. */
|
|
ret = h5_make_local_copy(filename, copied_filename);
|
|
VERIFY(ret >= 0, "h5_make_local_copy");
|
|
|
|
/* Allocate and initialize udata */
|
|
udata = (udata_t *)malloc(sizeof(udata_t));
|
|
VERIFY(udata != NULL, "udata malloc failed");
|
|
|
|
/* copy the address of the udata into the callbacks structure */
|
|
callbacks.udata = (void *)udata;
|
|
|
|
/* Set file image callbacks */
|
|
ret = H5Pset_file_image_callbacks(fapl, &callbacks);
|
|
VERIFY(ret >= 0, "set image callbacks failed");
|
|
|
|
/* Test open (no file image) */
|
|
reset_udata(udata);
|
|
file = H5Fopen(copied_filename, H5F_ACC_RDONLY, fapl);
|
|
VERIFY(file >= 0, "H5Fopen failed");
|
|
VERIFY((udata->used_callbacks == MALLOC) || (udata->used_callbacks == (MALLOC | UDATA_COPY | UDATA_FREE)),
|
|
"opening a core file used the wrong callbacks");
|
|
VERIFY(udata->malloc_src == H5FD_FILE_IMAGE_OP_FILE_OPEN,
|
|
"Malloc callback came from wrong source in core open");
|
|
|
|
/* Close file */
|
|
reset_udata(udata);
|
|
ret = H5Fclose(file);
|
|
VERIFY(ret >= 0, "H5Fclose failed");
|
|
VERIFY(udata->used_callbacks == FREE, "Closing a core file used the wrong callbacks");
|
|
VERIFY(udata->free_src == H5FD_FILE_IMAGE_OP_FILE_CLOSE,
|
|
"Free callback came from wrong source in core close");
|
|
|
|
/* Reopen file */
|
|
file = H5Fopen(copied_filename, H5F_ACC_RDWR, fapl);
|
|
VERIFY(file >= 0, "H5Fopen failed");
|
|
|
|
/* Set up a new dset */
|
|
dims[0] = DIM0;
|
|
dims[1] = DIM1;
|
|
space = H5Screate_simple(RANK, dims, dims);
|
|
VERIFY(space >= 0, "H5Screate failed");
|
|
|
|
/* Create new dset, invoking H5FD_core_write */
|
|
reset_udata(udata);
|
|
dset = H5Dcreate2(file, DSET_NAME, H5T_NATIVE_INT, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
VERIFY(dset >= 0, "H5Dcreate failed");
|
|
|
|
/* Flush the write and check the realloc callback */
|
|
ret = H5Fflush(file, H5F_SCOPE_LOCAL);
|
|
VERIFY(ret >= 0, "H5Fflush failed");
|
|
VERIFY(udata->used_callbacks == (REALLOC), "core write used the wrong callbacks");
|
|
VERIFY(udata->realloc_src == H5FD_FILE_IMAGE_OP_FILE_RESIZE,
|
|
"Realloc callback came from wrong source in core write");
|
|
|
|
/* Close dset and space */
|
|
ret = H5Dclose(dset);
|
|
VERIFY(ret >= 0, "H5Dclose failed");
|
|
ret = H5Sclose(space);
|
|
VERIFY(ret >= 0, "H5Sclose failed");
|
|
|
|
/* Test file close */
|
|
reset_udata(udata);
|
|
ret = H5Fclose(file);
|
|
VERIFY(ret >= 0, "H5Fclose failed");
|
|
VERIFY(udata->used_callbacks == (FREE), "Closing a core file used the wrong callbacks");
|
|
VERIFY(udata->free_src == H5FD_FILE_IMAGE_OP_FILE_CLOSE,
|
|
"Free callback came from wrong source in core close");
|
|
|
|
/* Create file image buffer */
|
|
fd = HDopen(copied_filename, O_RDONLY);
|
|
VERIFY(fd > 0, "open failed");
|
|
ret = HDfstat(fd, &sb);
|
|
VERIFY(ret == 0, "fstat failed");
|
|
size = (size_t)sb.st_size;
|
|
file_image = (unsigned char *)malloc(size);
|
|
if (HDread(fd, file_image, size) < 0)
|
|
FAIL_PUTS_ERROR("unable to read from file descriptor");
|
|
ret = HDclose(fd);
|
|
VERIFY(ret == 0, "close failed");
|
|
|
|
/* Set file image in plist */
|
|
if (H5Pset_file_image(fapl, file_image, size) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Test open with file image */
|
|
if ((file = H5Fopen("dne.h5", H5F_ACC_RDONLY, fapl)) < 0)
|
|
FAIL_STACK_ERROR;
|
|
if (H5Fclose(file) < 0)
|
|
FAIL_STACK_ERROR;
|
|
|
|
/* Release resources */
|
|
h5_clean_files(FILENAME, fapl);
|
|
free(udata);
|
|
free(file_image);
|
|
HDremove(copied_filename);
|
|
|
|
PASSED();
|
|
|
|
return 0;
|
|
|
|
error:
|
|
return 1;
|
|
} /* end test_core() */
|
|
|
|
/******************************************************************************
|
|
* Function: test_get_file_image
|
|
*
|
|
* Purpose: Test the H5Fget_file_image() call.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
/* Disable warning for "format not a string literal" here -QAK */
|
|
/*
|
|
* This pragma only needs to surround the snprintf() calls with
|
|
* 'member_file_name' in the code below, but early (4.4.7, at least) gcc only
|
|
* allows diagnostic pragmas to be toggled outside of functions.
|
|
*/
|
|
H5_GCC_CLANG_DIAG_OFF("format-nonliteral")
|
|
static int
|
|
test_get_file_image(const char *test_banner, const int file_name_num, hid_t fapl, bool user)
|
|
{
|
|
char file_name[1024] = "\0";
|
|
void *insertion_ptr = NULL;
|
|
void *image_ptr = NULL;
|
|
void *file_image_ptr = NULL;
|
|
bool is_family_file = false;
|
|
bool identical;
|
|
int data[100];
|
|
int i;
|
|
int fd = -1;
|
|
int result;
|
|
hid_t driver = H5I_INVALID_HID;
|
|
hid_t file_id = H5I_INVALID_HID;
|
|
hid_t dset_id = H5I_INVALID_HID;
|
|
hid_t space_id = H5I_INVALID_HID;
|
|
hid_t core_fapl_id = H5I_INVALID_HID;
|
|
hid_t core_file_id = H5I_INVALID_HID;
|
|
herr_t err;
|
|
hsize_t dims[2];
|
|
ssize_t bytes_read;
|
|
ssize_t image_size;
|
|
ssize_t file_size;
|
|
h5_stat_t stat_buf;
|
|
hid_t fcpl = H5I_INVALID_HID;
|
|
herr_t ret;
|
|
|
|
TESTING(test_banner);
|
|
|
|
/* set flag if we are dealing with a family file */
|
|
driver = H5Pget_driver(fapl);
|
|
VERIFY(driver >= 0, "H5Pget_driver(fapl) failed");
|
|
|
|
if (driver == H5FD_FAMILY)
|
|
is_family_file = true;
|
|
|
|
/* setup the file name */
|
|
h5_fixname(FILENAME2[file_name_num], fapl, file_name, sizeof(file_name));
|
|
VERIFY(strlen(file_name) > 0, "h5_fixname failed");
|
|
|
|
fcpl = H5Pcreate(H5P_FILE_CREATE);
|
|
VERIFY(fcpl >= 0, "H5Pcreate");
|
|
if (user) {
|
|
ret = H5Pset_userblock(fcpl, (hsize_t)USERBLOCK_SIZE);
|
|
VERIFY(ret >= 0, "H5Pset_userblock");
|
|
}
|
|
|
|
/* create the file */
|
|
file_id = H5Fcreate(file_name, 0, fcpl, fapl);
|
|
VERIFY(file_id >= 0, "H5Fcreate() failed.");
|
|
|
|
/* Set up data space for new new data set */
|
|
dims[0] = 10;
|
|
dims[1] = 10;
|
|
space_id = H5Screate_simple(2, dims, dims);
|
|
VERIFY(space_id >= 0, "H5Screate() failed");
|
|
|
|
/* Create a dataset */
|
|
dset_id = H5Dcreate2(file_id, "dset 0", H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
VERIFY(dset_id >= 0, "H5Dcreate() failed");
|
|
|
|
/* write some data to the data set */
|
|
for (i = 0; i < 100; i++)
|
|
data[i] = i;
|
|
err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, (void *)data);
|
|
VERIFY(err >= 0, "H5Dwrite() failed.");
|
|
|
|
/* Flush the file */
|
|
err = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
|
|
VERIFY(err >= 0, "H5Fflush failed");
|
|
|
|
/* get the size of the file */
|
|
image_size = H5Fget_file_image(file_id, NULL, (size_t)0);
|
|
VERIFY(image_size > 0, "H5Fget_file_image(1) failed.");
|
|
|
|
/* allocate a buffer of the appropriate size */
|
|
image_ptr = malloc((size_t)image_size);
|
|
VERIFY(image_ptr != NULL, "malloc(1) failed.");
|
|
|
|
/* load the image of the file into the buffer */
|
|
bytes_read = H5Fget_file_image(file_id, image_ptr, (size_t)image_size);
|
|
VERIFY(bytes_read == image_size, "H5Fget_file_image(2) failed.");
|
|
|
|
/* Close dset and space */
|
|
err = H5Dclose(dset_id);
|
|
VERIFY(err >= 0, "H5Dclose failed");
|
|
err = H5Sclose(space_id);
|
|
VERIFY(err >= 0, "H5Sclose failed");
|
|
|
|
/* close the test file */
|
|
err = H5Fclose(file_id);
|
|
VERIFY(err == SUCCEED, "H5Fclose(file_id) failed.");
|
|
|
|
if (is_family_file) {
|
|
char member_file_name[1024];
|
|
ssize_t bytes_to_read;
|
|
ssize_t member_size;
|
|
ssize_t size_remaining;
|
|
|
|
/*
|
|
* Modifications need to be made to accommodate userblock when
|
|
* H5Fget_file_image() works for family driver
|
|
*/
|
|
i = 0;
|
|
file_size = 0;
|
|
|
|
do {
|
|
snprintf(member_file_name, (size_t)1024, file_name, i);
|
|
|
|
/* get the size of the member file */
|
|
result = HDstat(member_file_name, &stat_buf);
|
|
VERIFY(result == 0, "HDstat() failed.");
|
|
|
|
member_size = (ssize_t)stat_buf.st_size;
|
|
|
|
i++;
|
|
file_size += member_size;
|
|
} while (member_size > 0);
|
|
|
|
/* Since we use the eoa to calculate the image size, the file size
|
|
* may be larger. This is OK, as long as (in this specialized instance)
|
|
* the remainder of the file is all '\0's.
|
|
*/
|
|
VERIFY(file_size >= image_size, "file size != image size.");
|
|
|
|
/* allocate a buffer for the test file image */
|
|
file_image_ptr = malloc((size_t)file_size);
|
|
VERIFY(file_image_ptr != NULL, "malloc(2f) failed.");
|
|
|
|
size_remaining = image_size;
|
|
insertion_ptr = file_image_ptr;
|
|
i = 0;
|
|
|
|
while (size_remaining > 0) {
|
|
/* construct the member file name */
|
|
snprintf(member_file_name, 1024, file_name, i);
|
|
|
|
/* open the test file using standard I/O calls */
|
|
fd = HDopen(member_file_name, O_RDONLY);
|
|
VERIFY(fd >= 0, "HDopen() failed.");
|
|
|
|
if (size_remaining >= FAMILY_SIZE) {
|
|
bytes_to_read = FAMILY_SIZE;
|
|
size_remaining -= FAMILY_SIZE;
|
|
}
|
|
else {
|
|
bytes_to_read = size_remaining;
|
|
size_remaining = 0;
|
|
}
|
|
|
|
/* read the member file from disk into the buffer */
|
|
bytes_read = HDread(fd, insertion_ptr, (size_t)bytes_to_read);
|
|
VERIFY(bytes_read == bytes_to_read, "HDread() failed.");
|
|
|
|
insertion_ptr = (void *)(((char *)insertion_ptr) + bytes_to_read);
|
|
|
|
i++;
|
|
|
|
/* close the test file */
|
|
result = HDclose(fd);
|
|
VERIFY(result == 0, "HDclose() failed.");
|
|
}
|
|
}
|
|
else {
|
|
/* get the size of the test file */
|
|
result = HDstat(file_name, &stat_buf);
|
|
VERIFY(result == 0, "HDstat() failed.");
|
|
|
|
/* Since we use the eoa to calculate the image size, the file size
|
|
* may be larger. This is OK, as long as (in this specialized instance)
|
|
* the remainder of the file is all '\0's.
|
|
*/
|
|
file_size = (ssize_t)stat_buf.st_size;
|
|
if (user) {
|
|
VERIFY(file_size > USERBLOCK_SIZE, "file size !> userblock size.");
|
|
file_size -= USERBLOCK_SIZE;
|
|
}
|
|
|
|
/* with latest mods to truncate call in core file drive,
|
|
* file size should match image size
|
|
*/
|
|
VERIFY(file_size == image_size, "file size != image size.");
|
|
|
|
/* allocate a buffer for the test file image */
|
|
file_image_ptr = malloc((size_t)file_size);
|
|
VERIFY(file_image_ptr != NULL, "malloc(2) failed.");
|
|
|
|
/* open the test file using standard I/O calls */
|
|
fd = HDopen(file_name, O_RDONLY);
|
|
VERIFY(fd >= 0, "HDopen() failed.");
|
|
|
|
if (user) {
|
|
HDoff_t off;
|
|
|
|
/* Position at userblock */
|
|
off = HDlseek(fd, (HDoff_t)USERBLOCK_SIZE, SEEK_SET);
|
|
VERIFY(off >= 0, "HDlseek() failed.");
|
|
}
|
|
|
|
/* read the test file from disk into the buffer */
|
|
bytes_read = HDread(fd, file_image_ptr, (size_t)file_size);
|
|
VERIFY(bytes_read == file_size, "HDread() failed.");
|
|
|
|
/* close the test file */
|
|
result = HDclose(fd);
|
|
VERIFY(result == 0, "HDclose() failed.");
|
|
}
|
|
|
|
/* verify that the file and the image contain the same data */
|
|
identical = true;
|
|
i = 0;
|
|
while ((i < (int)image_size) && identical) {
|
|
if (((char *)image_ptr)[i] != ((char *)file_image_ptr)[i])
|
|
identical = false;
|
|
i++;
|
|
}
|
|
VERIFY(identical, "file and image differ.");
|
|
|
|
/* finally, verify that we can use the core file driver to open the image */
|
|
|
|
/* create fapl for core file driver */
|
|
core_fapl_id = H5Pcreate(H5P_FILE_ACCESS);
|
|
VERIFY(core_fapl_id >= 0, "H5Pcreate() failed");
|
|
|
|
/* setup core_fapl_id to use the core file driver */
|
|
err = H5Pset_fapl_core(core_fapl_id, (size_t)(64 * 1024), false);
|
|
VERIFY(err == SUCCEED, "H5Pset_fapl_core() failed.");
|
|
|
|
/* Set file image in core fapl */
|
|
err = H5Pset_file_image(core_fapl_id, image_ptr, (size_t)image_size);
|
|
VERIFY(err == SUCCEED, "H5Pset_file_image() failed.");
|
|
|
|
/* open the file image with the core file driver */
|
|
core_file_id = H5Fopen("nonesuch", H5F_ACC_RDWR, core_fapl_id);
|
|
VERIFY(core_file_id >= 0, "H5Fopen() of file image failed.");
|
|
|
|
/* close the file image with the core file driver */
|
|
err = H5Fclose(core_file_id);
|
|
VERIFY(err == SUCCEED, "H5Fclose(core_file_id) failed.");
|
|
|
|
/* discard core fapl */
|
|
err = H5Pclose(core_fapl_id);
|
|
VERIFY(err == SUCCEED, "H5Pclose(core_fapl_id) failed.");
|
|
|
|
/* tidy up */
|
|
h5_clean_files(FILENAME2, fapl);
|
|
|
|
/* discard the image buffer if it exists */
|
|
if (image_ptr != NULL)
|
|
free(image_ptr);
|
|
|
|
/* discard the image buffer if it exists */
|
|
if (file_image_ptr != NULL)
|
|
free(file_image_ptr);
|
|
|
|
PASSED();
|
|
|
|
return 0;
|
|
|
|
error:
|
|
return 1;
|
|
} /* end test_get_file_image() */
|
|
H5_GCC_CLANG_DIAG_ON("format-nonliteral")
|
|
|
|
/******************************************************************************
|
|
* Function: test_get_file_image_error_rejection
|
|
*
|
|
* Purpose: Verify that H5Fget_file_image() rejects invalid input.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
#define TYPE_SLICE ((haddr_t)0x10000LL)
|
|
|
|
static int
|
|
test_get_file_image_error_rejection(void)
|
|
{
|
|
const char *memb_name[H5FD_MEM_NTYPES];
|
|
char file_name[1024] = "\0";
|
|
void *image_ptr = NULL;
|
|
int data[100];
|
|
int i;
|
|
hid_t fapl_id = H5I_INVALID_HID;
|
|
hid_t file_id = H5I_INVALID_HID;
|
|
hid_t dset_id = H5I_INVALID_HID;
|
|
hid_t space_id = H5I_INVALID_HID;
|
|
herr_t err;
|
|
hsize_t dims[2];
|
|
ssize_t bytes_read;
|
|
ssize_t image_size;
|
|
hid_t memb_fapl[H5FD_MEM_NTYPES];
|
|
haddr_t memb_addr[H5FD_MEM_NTYPES];
|
|
H5FD_mem_t mt;
|
|
H5FD_mem_t memb_map[H5FD_MEM_NTYPES];
|
|
|
|
TESTING("H5Fget_file_image() error rejection");
|
|
|
|
/************************ Sub-Test #1 ********************************/
|
|
/* set up a test file, and try to get its image with a buffer that is
|
|
* too small. Call to H5Fget_file_image() should fail.
|
|
*
|
|
* Since we have already done the necessary setup, verify that
|
|
* H5Fget_file_image() will fail with:
|
|
*
|
|
* bad file id, or
|
|
*
|
|
* good id, but not a file id
|
|
*/
|
|
|
|
/* setup fapl -- driver type doesn't matter much, so make it stdio */
|
|
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
|
|
VERIFY(fapl_id >= 0, "H5Pcreate(1) failed");
|
|
|
|
err = H5Pset_fapl_stdio(fapl_id);
|
|
VERIFY(err >= 0, "H5Pset_fapl_stdio() failed");
|
|
|
|
/* setup the file name */
|
|
h5_fixname(FILENAME2[6], fapl_id, file_name, sizeof(file_name));
|
|
VERIFY(strlen(file_name) > 0, "h5_fixname failed");
|
|
|
|
/* create the file */
|
|
file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl_id);
|
|
VERIFY(file_id >= 0, "H5Fcreate() failed.");
|
|
|
|
/* Set up data space for new new data set */
|
|
dims[0] = 10;
|
|
dims[1] = 10;
|
|
space_id = H5Screate_simple(2, dims, dims);
|
|
VERIFY(space_id >= 0, "H5Screate() failed");
|
|
|
|
/* Create a dataset */
|
|
dset_id = H5Dcreate2(file_id, "dset 0", H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
VERIFY(dset_id >= 0, "H5Dcreate() failed");
|
|
|
|
/* write some data to the data set */
|
|
for (i = 0; i < 100; i++)
|
|
data[i] = i;
|
|
err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, (void *)data);
|
|
VERIFY(err >= 0, "H5Dwrite() failed.");
|
|
|
|
/* Flush the file */
|
|
err = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
|
|
VERIFY(err >= 0, "H5Fflush failed");
|
|
|
|
/* get the size of the file */
|
|
image_size = H5Fget_file_image(file_id, NULL, (size_t)0);
|
|
VERIFY(image_size > 0, "H5Fget_file_image(1 -- test 1) failed.");
|
|
|
|
/* allocate a buffer of the appropriate size */
|
|
image_ptr = malloc((size_t)image_size);
|
|
VERIFY(image_ptr != NULL, "malloc(1) failed.");
|
|
|
|
/* load the image of the file into the buffer */
|
|
H5E_BEGIN_TRY
|
|
{
|
|
bytes_read = H5Fget_file_image(file_id, image_ptr, (size_t)(image_size - 1));
|
|
}
|
|
H5E_END_TRY
|
|
VERIFY(bytes_read < 0, "H5Fget_file_image(2 -- test 1) succeeded.");
|
|
|
|
/* Call H5Fget_file_image() with good buffer and buffer size,
|
|
* but non-existent file_id. Should fail.
|
|
*/
|
|
H5E_BEGIN_TRY
|
|
{
|
|
bytes_read = H5Fget_file_image((hid_t)0, image_ptr, (size_t)(image_size));
|
|
}
|
|
H5E_END_TRY
|
|
VERIFY(bytes_read < 0, "H5Fget_file_image(3 -- test 1) succeeded.");
|
|
|
|
/* Call H5Fget_file_image() with good buffer and buffer size,
|
|
* but a file_id of the wrong type. Should fail.
|
|
*/
|
|
H5E_BEGIN_TRY
|
|
{
|
|
bytes_read = H5Fget_file_image(dset_id, image_ptr, (size_t)(image_size));
|
|
}
|
|
H5E_END_TRY
|
|
VERIFY(bytes_read < 0, "H5Fget_file_image(4 -- test 1) succeeded.");
|
|
|
|
/* Close dset and space */
|
|
err = H5Dclose(dset_id);
|
|
VERIFY(err >= 0, "H5Dclose failed");
|
|
err = H5Sclose(space_id);
|
|
VERIFY(err >= 0, "H5Sclose failed");
|
|
|
|
/* close the test file */
|
|
err = H5Fclose(file_id);
|
|
VERIFY(err == SUCCEED, "H5Fclose(file_id) failed.");
|
|
|
|
/* tidy up */
|
|
h5_clean_files(FILENAME2, fapl_id);
|
|
|
|
/* discard the image buffer if it exists */
|
|
if (image_ptr != NULL)
|
|
free(image_ptr);
|
|
|
|
/************************** Test #2 **********************************/
|
|
/* set up a multi file driver test file, and try to get its image
|
|
* with H5Fget_file_image(). Attempt should fail.
|
|
*/
|
|
|
|
/* setup parameters for multi file driver */
|
|
for (mt = (H5FD_mem_t)0; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) {
|
|
memb_addr[mt] = HADDR_UNDEF;
|
|
memb_fapl[mt] = H5P_DEFAULT;
|
|
memb_map[mt] = H5FD_MEM_DRAW;
|
|
memb_name[mt] = NULL;
|
|
}
|
|
|
|
memb_map[H5FD_MEM_SUPER] = H5FD_MEM_SUPER;
|
|
memb_fapl[H5FD_MEM_SUPER] = H5P_DEFAULT;
|
|
memb_name[H5FD_MEM_SUPER] = "%s-s.h5";
|
|
memb_addr[H5FD_MEM_SUPER] = 0;
|
|
|
|
memb_map[H5FD_MEM_BTREE] = H5FD_MEM_BTREE;
|
|
memb_fapl[H5FD_MEM_BTREE] = H5P_DEFAULT;
|
|
memb_name[H5FD_MEM_BTREE] = "%s-b.h5";
|
|
memb_addr[H5FD_MEM_BTREE] = memb_addr[H5FD_MEM_SUPER] + TYPE_SLICE;
|
|
|
|
memb_map[H5FD_MEM_DRAW] = H5FD_MEM_DRAW;
|
|
memb_fapl[H5FD_MEM_DRAW] = H5P_DEFAULT;
|
|
memb_name[H5FD_MEM_DRAW] = "%s-r.h5";
|
|
memb_addr[H5FD_MEM_DRAW] = memb_addr[H5FD_MEM_BTREE] + TYPE_SLICE;
|
|
|
|
memb_map[H5FD_MEM_GHEAP] = H5FD_MEM_GHEAP;
|
|
memb_fapl[H5FD_MEM_GHEAP] = H5P_DEFAULT;
|
|
memb_name[H5FD_MEM_GHEAP] = "%s-g.h5";
|
|
memb_addr[H5FD_MEM_GHEAP] = memb_addr[H5FD_MEM_DRAW] + TYPE_SLICE;
|
|
|
|
memb_map[H5FD_MEM_LHEAP] = H5FD_MEM_LHEAP;
|
|
memb_fapl[H5FD_MEM_LHEAP] = H5P_DEFAULT;
|
|
memb_name[H5FD_MEM_LHEAP] = "%s-l.h5";
|
|
memb_addr[H5FD_MEM_LHEAP] = memb_addr[H5FD_MEM_GHEAP] + TYPE_SLICE;
|
|
|
|
memb_map[H5FD_MEM_OHDR] = H5FD_MEM_OHDR;
|
|
memb_fapl[H5FD_MEM_OHDR] = H5P_DEFAULT;
|
|
memb_name[H5FD_MEM_OHDR] = "%s-o.h5";
|
|
memb_addr[H5FD_MEM_OHDR] = memb_addr[H5FD_MEM_LHEAP] + TYPE_SLICE;
|
|
|
|
/* setup fapl */
|
|
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
|
|
VERIFY(fapl_id >= 0, "H5Pcreate(2) failed");
|
|
|
|
/* setup the fapl for the multi file driver */
|
|
err = H5Pset_fapl_multi(fapl_id, memb_map, memb_fapl, memb_name, memb_addr, false);
|
|
VERIFY(err >= 0, "H5Pset_fapl_multi failed");
|
|
|
|
/* setup the file name */
|
|
h5_fixname(FILENAME2[4], fapl_id, file_name, sizeof(file_name));
|
|
VERIFY(strlen(file_name) > 0, "h5_fixname failed");
|
|
|
|
/* create the file */
|
|
file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl_id);
|
|
VERIFY(file_id >= 0, "H5Fcreate() failed.");
|
|
|
|
/* Set up data space for new new data set */
|
|
dims[0] = 10;
|
|
dims[1] = 10;
|
|
space_id = H5Screate_simple(2, dims, dims);
|
|
VERIFY(space_id >= 0, "H5Screate() failed");
|
|
|
|
/* Create a dataset */
|
|
dset_id = H5Dcreate2(file_id, "dset 0", H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
VERIFY(dset_id >= 0, "H5Dcreate() failed");
|
|
|
|
/* write some data to the data set */
|
|
for (i = 0; i < 100; i++)
|
|
data[i] = i;
|
|
err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, (void *)data);
|
|
VERIFY(err >= 0, "H5Dwrite() failed.");
|
|
|
|
/* Flush the file */
|
|
err = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
|
|
VERIFY(err >= 0, "H5Fflush failed");
|
|
|
|
/* attempt to get the size of the file -- should fail */
|
|
H5E_BEGIN_TRY
|
|
{
|
|
image_size = H5Fget_file_image(file_id, NULL, (size_t)0);
|
|
}
|
|
H5E_END_TRY
|
|
VERIFY(image_size == -1, "H5Fget_file_image(5) succeeded.");
|
|
|
|
/* Close dset and space */
|
|
err = H5Dclose(dset_id);
|
|
VERIFY(err >= 0, "H5Dclose failed");
|
|
err = H5Sclose(space_id);
|
|
VERIFY(err >= 0, "H5Sclose failed");
|
|
|
|
/* close the test file */
|
|
err = H5Fclose(file_id);
|
|
VERIFY(err == SUCCEED, "H5Fclose(2) failed.");
|
|
|
|
/* tidy up */
|
|
h5_clean_files(FILENAME2, fapl_id);
|
|
|
|
/************************** Test #3 **********************************/
|
|
/* set up a split file driver test file, and try to get its image
|
|
* with H5Fget_file_image(). Attempt should fail.
|
|
*/
|
|
|
|
/* create fapl */
|
|
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
|
|
VERIFY(fapl_id >= 0, "H5Pcreate(3) failed");
|
|
|
|
/* setup the fapl for the split file driver */
|
|
err = H5Pset_fapl_split(fapl_id, "-m.h5", H5P_DEFAULT, "-r.h5", H5P_DEFAULT);
|
|
VERIFY(err >= 0, "H5Pset_fapl_split failed");
|
|
|
|
/* setup the file name */
|
|
h5_fixname(FILENAME2[5], fapl_id, file_name, sizeof(file_name));
|
|
VERIFY(strlen(file_name) > 0, "h5_fixname failed");
|
|
|
|
/* create the file */
|
|
file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl_id);
|
|
VERIFY(file_id >= 0, "H5Fcreate() failed.");
|
|
|
|
/* Set up data space for new new data set */
|
|
dims[0] = 10;
|
|
dims[1] = 10;
|
|
space_id = H5Screate_simple(2, dims, dims);
|
|
VERIFY(space_id >= 0, "H5Screate() failed");
|
|
|
|
/* Create a dataset */
|
|
dset_id = H5Dcreate2(file_id, "dset 0", H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
VERIFY(dset_id >= 0, "H5Dcreate() failed");
|
|
|
|
/* write some data to the data set */
|
|
for (i = 0; i < 100; i++)
|
|
data[i] = i;
|
|
err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, (void *)data);
|
|
VERIFY(err >= 0, "H5Dwrite() failed.");
|
|
|
|
/* Flush the file */
|
|
err = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
|
|
VERIFY(err >= 0, "H5Fflush failed");
|
|
|
|
/* attempt to get the size of the file -- should fail */
|
|
H5E_BEGIN_TRY
|
|
{
|
|
image_size = H5Fget_file_image(file_id, NULL, (size_t)0);
|
|
}
|
|
H5E_END_TRY
|
|
VERIFY(image_size == -1, "H5Fget_file_image(6) succeeded.");
|
|
|
|
/* Close dset and space */
|
|
err = H5Dclose(dset_id);
|
|
VERIFY(err >= 0, "H5Dclose failed");
|
|
err = H5Sclose(space_id);
|
|
VERIFY(err >= 0, "H5Sclose failed");
|
|
|
|
/* close the test file */
|
|
err = H5Fclose(file_id);
|
|
VERIFY(err == SUCCEED, "H5Fclose(2) failed.");
|
|
|
|
/* tidy up */
|
|
h5_clean_files(FILENAME2, fapl_id);
|
|
|
|
/************************** Test #4 **********************************/
|
|
/* set up a family file driver test file, and try to get its image
|
|
* with H5Fget_file_image(). Attempt should fail.
|
|
*/
|
|
|
|
/* create fapl */
|
|
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
|
|
VERIFY(fapl_id >= 0, "H5Pcreate(3) failed");
|
|
|
|
err = H5Pset_fapl_family(fapl_id, (hsize_t)FAMILY_SIZE, H5P_DEFAULT);
|
|
VERIFY(err >= 0, "H5Pset_fapl_family failed");
|
|
|
|
h5_fixname(FILENAME2[3], fapl_id, file_name, sizeof(file_name));
|
|
VERIFY(strlen(file_name) > 0, "h5_fixname failed");
|
|
|
|
/* create the file */
|
|
file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl_id);
|
|
VERIFY(file_id >= 0, "H5Fcreate() failed.");
|
|
|
|
/* Set up data space for new new data set */
|
|
dims[0] = 10;
|
|
dims[1] = 10;
|
|
space_id = H5Screate_simple(2, dims, dims);
|
|
VERIFY(space_id >= 0, "H5Screate() failed");
|
|
|
|
/* Create a dataset */
|
|
dset_id = H5Dcreate2(file_id, "dset 0", H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
|
VERIFY(dset_id >= 0, "H5Dcreate() failed");
|
|
|
|
/* write some data to the data set */
|
|
for (i = 0; i < 100; i++)
|
|
data[i] = i;
|
|
err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, (void *)data);
|
|
VERIFY(err >= 0, "H5Dwrite() failed.");
|
|
|
|
/* Flush the file */
|
|
err = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
|
|
VERIFY(err >= 0, "H5Fflush failed");
|
|
|
|
/* attempt to get the size of the file -- should fail */
|
|
H5E_BEGIN_TRY
|
|
{
|
|
image_size = H5Fget_file_image(file_id, NULL, (size_t)0);
|
|
}
|
|
H5E_END_TRY
|
|
VERIFY(image_size == -1, "H5Fget_file_image(7) succeeded.");
|
|
|
|
/* Close dset and space */
|
|
err = H5Dclose(dset_id);
|
|
VERIFY(err >= 0, "H5Dclose failed");
|
|
err = H5Sclose(space_id);
|
|
VERIFY(err >= 0, "H5Sclose failed");
|
|
|
|
/* close the test file */
|
|
err = H5Fclose(file_id);
|
|
VERIFY(err == SUCCEED, "H5Fclose(2) failed.");
|
|
|
|
/* tidy up */
|
|
h5_clean_files(FILENAME2, fapl_id);
|
|
|
|
PASSED();
|
|
|
|
return 0;
|
|
|
|
error:
|
|
return 1;
|
|
} /* test_get_file_image_error_rejection() */
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
int errors = 0;
|
|
hid_t fapl;
|
|
bool driver_is_default_compatible;
|
|
unsigned user;
|
|
|
|
h5_reset();
|
|
|
|
printf("Testing File Image Functionality.\n");
|
|
|
|
errors += test_properties();
|
|
errors += test_callbacks();
|
|
|
|
if (h5_driver_is_default_vfd_compatible(H5P_DEFAULT, &driver_is_default_compatible) < 0)
|
|
errors++;
|
|
else if (driver_is_default_compatible) {
|
|
errors += test_core();
|
|
}
|
|
|
|
/* Perform tests with/without user block */
|
|
for (user = false; user <= true; user++) {
|
|
|
|
/* test H5Fget_file_image() with sec2 driver */
|
|
fapl = H5Pcreate(H5P_FILE_ACCESS);
|
|
if (H5Pset_fapl_sec2(fapl) < 0)
|
|
errors++;
|
|
else
|
|
errors += test_get_file_image("H5Fget_file_image() with sec2 driver", 0, fapl, user);
|
|
|
|
/* test H5Fget_file_image() with stdio driver */
|
|
fapl = H5Pcreate(H5P_FILE_ACCESS);
|
|
if (H5Pset_fapl_stdio(fapl) < 0)
|
|
errors++;
|
|
else
|
|
errors += test_get_file_image("H5Fget_file_image() with stdio driver", 1, fapl, user);
|
|
|
|
/* test H5Fget_file_image() with core driver */
|
|
fapl = H5Pcreate(H5P_FILE_ACCESS);
|
|
if (H5Pset_fapl_core(fapl, (size_t)(64 * 1024), true) < 0)
|
|
errors++;
|
|
else
|
|
errors += test_get_file_image("H5Fget_file_image() with core driver", 2, fapl, user);
|
|
|
|
} /* end for */
|
|
|
|
#if 0
|
|
/* at present, H5Fget_file_image() rejects files opened with the
|
|
* family file driver, due to the addition of a driver info message
|
|
* in the super block. This message prevents the image being opened
|
|
* with any driver other than the family file driver, which sort of
|
|
* defeats the purpose of the get file image operation.
|
|
*
|
|
* While this issues is quite fixable, we don't have time or resources
|
|
* for this right now. Once we do, the following code should be
|
|
* suitable for testing the fix.
|
|
*/
|
|
/* test H5Fget_file_image() with family file driver */
|
|
fapl = H5Pcreate(H5P_FILE_ACCESS);
|
|
if(H5Pset_fapl_family(fapl, (hsize_t)FAMILY_SIZE, H5P_DEFAULT) < 0)
|
|
errors++;
|
|
else
|
|
errors += test_get_file_image("H5Fget_file_image() with family driver",
|
|
3, fapl);
|
|
#endif
|
|
|
|
errors += test_get_file_image_error_rejection();
|
|
|
|
/* Restore the default error handler (set in h5_reset()) */
|
|
h5_restore_err();
|
|
|
|
if (errors) {
|
|
printf("***** %d File Image TEST%s FAILED! *****\n", errors, errors > 1 ? "S" : "");
|
|
return 1;
|
|
}
|
|
|
|
printf("All File Image tests passed.\n");
|
|
return 0;
|
|
}
|