hdf5/test/objcopy_ref.c
David Young 60756183d9 Change hdset_reg_ref_t and H5R_ref_t from arrays of unsigned char to
structs containing those arrays.  Encapsulating the arrays in this way
makes it easier to write and think about pointers to these types, casts
to/from these types, etc.

An interesting side-effect that we probably should *not* rely on is
that the struct-encapsulation changes the alignment so that some GCC
warnings about casts that increase the alignment requirement of the
operand go away.  Warnings like that have to be taken seriously:  I will
add -Werror=cast-align to the default compiler flags so that they stop
the build quickly.

GCC warnings led me to some surprising casts in test/trefer.c. I found
that it was possible to make many simplifications after introducing the
struct-encapsulation that I described, above.

In test objcopy_ref `same_file` is assigned but never used.  Delete it.
2019-12-05 14:41:45 -06:00

1732 lines
65 KiB
C

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* 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://support.hdfgroup.org/ftp/HDF5/releases. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Programmer: Peter X. Cao
* May 01, 2005
*
* Purpose: Test H5Ocopy() for references.
*/
#include "testhdf5.h"
#define H5F_FRIEND /*suppress error about including H5Fpkg */
#define H5F_TESTING
#include "H5Fpkg.h" /* File access */
const char *FILENAME[] = {
"objcopy_ref_src",
"objcopy_ref_dst",
"objcopy_ref_ext",
"objcopy_ref_src2",
"verbound_ref_src",
"verbound_ref_dst",
NULL
};
/* Configuration, really a series of bit flags. Maximum value is all three
* bit flags enabled.
*/
#define CONFIG_SHARE_SRC 1
#define CONFIG_SHARE_DST 2
#define CONFIG_SRC_NEW_FORMAT 4
#define CONFIG_DST_NEW_FORMAT 8
#define CONFIG_DENSE 16
#define MAX_CONFIGURATION 31
#define NAME_DATATYPE_SIMPLE "H5T_NATIVE_INT"
#define NAME_DATATYPE_SIMPLE2 "H5T_NATIVE_INT-2"
#define NAME_DATATYPE_VL "vlen of int"
#define NAME_DATATYPE_VL_VL "vlen of vlen of int"
#define NAME_DATASET_SIMPLE "dataset_simple"
#define NAME_DATASET_SIMPLE2 "dataset_simple_copy"
#define NAME_DATASET_SIMPLE3 "dataset_simple_another_copy"
#define NAME_DATASET_COMPOUND "dataset_compound"
#define NAME_DATASET_CHUNKED "dataset_chunked"
#define NAME_DATASET_CHUNKED_SINGLE "dataset_chunked_single"
#define NAME_DATASET_CHUNKED2 "dataset_chunked2"
#define NAME_DATASET_CHUNKED2_SINGLE "dataset_chunked2_single"
#define NAME_DATASET_CHUNKED3 "dataset_chunked3"
#define NAME_DATASET_CHUNKED3_SINGLE "dataset_chunked3_single"
#define NAME_DATASET_CHUNKED4 "dataset_chunked4"
#define NAME_DATASET_CHUNKED4_SINGLE "dataset_chunked4_single"
#define NAME_DATASET_COMPACT "dataset_compact"
#define NAME_DATASET_EXTERNAL "dataset_ext"
#define NAME_DATASET_NAMED_DTYPE "dataset_named_dtype"
#define NAME_DATASET_NAMED_DTYPE2 "dataset_named_dtype2"
#define NAME_DATASET_MULTI_OHDR "dataset_multi_ohdr"
#define NAME_DATASET_MULTI_OHDR2 "dataset_multi_ohdr2"
#define NAME_DATASET_VL "dataset_vl"
#define NAME_DATASET_VL2 "dataset_vl2"
#define NAME_DATASET_VL_VL "dataset_vl_vl"
#define NAME_DATASET_VL_VL2 "dataset_vl_vl2"
#define NAME_DATASET_CMPD_VL "dataset_cmpd_vl"
#define NAME_DATASET_SUB_SUB "/g0/g00/g000/dataset_simple"
#define NAME_GROUP_UNCOPIED "/uncopied"
#define NAME_GROUP_EMPTY "/empty"
#define NAME_GROUP_TOP "/g0"
#define NAME_GROUP_TOP2 "/g1"
#define NAME_GROUP_TOP3 "/g2"
#define NAME_GROUP_TOP4 "/g3"
#define NAME_GROUP_SUB "/g0/g00"
#define NAME_GROUP_SUB_2 "/g0/g01"
#define NAME_GROUP_SUB_SUB "/g0/g00/g000"
#define NAME_GROUP_SUB_SUB2 "g000"
#define NAME_GROUP_DATASET "/g0/dataset_simple"
#define NAME_GROUP_LINK "/g_links"
#define NAME_GROUP_LINK2 "/g_links2"
#define NAME_GROUP_LOOP "g_loop"
#define NAME_GROUP_LOOP2 "g_loop2"
#define NAME_GROUP_LOOP3 "g_loop3"
#define NAME_GROUP_REF "ref_grp"
#define NAME_LINK_DATASET "/g_links/dataset_simple"
#define NAME_LINK_HARD "/g_links/hard_link_to_dataset_simple"
#define NAME_LINK_SOFT "/g_links/soft_link_to_dataset_simple"
#define NAME_LINK_SOFT2 "/g_links2/soft_link_to_dataset_simple"
#define NAME_LINK_EXTERN "/g_links/external_link_to_dataset_simple"
#define NAME_LINK_EXTERN2 "/g_links2/external_link_to_dataset_simple"
#define NAME_LINK_SOFT_DANGLE "/g_links/soft_link_to_nowhere"
#define NAME_LINK_SOFT_DANGLE2 "/g_links2/soft_link_to_nowhere"
#define NAME_LINK_EXTERN_DANGLE "/g_links/external_link_to_nowhere"
#define NAME_LINK_EXTERN_DANGLE2 "/g_links2/external_link_to_nowhere"
#define NAME_OLD_FORMAT "/dset1"
#define NAME_BUF_SIZE 1024
#define ATTR_NAME_LEN 80
#define DIM_SIZE_1 12
#define DIM_SIZE_2 6
#define MAX_DIM_SIZE_1 100
#define MAX_DIM_SIZE_2 80
#define CHUNK_SIZE_1 5 /* Not an even fraction of dimension sizes, so we test copying partial chunks */
#define CHUNK_SIZE_2 5
#define NUM_SUB_GROUPS 20
#define NUM_WIDE_LOOP_GROUPS 10
#define NUM_DATASETS 10
unsigned num_attributes_g; /* Number of attributes created */
/* Table containing object id and object name */
/* (Used for detecting duplicate objects when comparing groups */
static struct {
size_t nalloc; /* number of slots allocated */
size_t nobjs; /* number of objects */
haddr_t *obj; /* Addresses of objects seen */
} idtab_g;
/* Local function prototypes */
static int
compare_data(hid_t parent1, hid_t parent2, hid_t pid, hid_t tid, size_t nelmts,
const void *buf1, const void *buf2, hid_t obj_owner);
static int
compare_datasets(hid_t did, hid_t did2, hid_t pid, const void *wbuf);
static int
compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth, unsigned copy_flags);
/*-------------------------------------------------------------------------
* Function: addr_insert
*
* Purpose: Add an address to the table.
*
* Return: void
*
* Programmer: Quincey Koziol
* Saturday, November 5, 2005
*
*-------------------------------------------------------------------------
*/
static void
addr_insert(H5O_info_t *oi)
{
size_t n;
/* Don't add it if the link count is 1 because such an object can only
* be encountered once. */
if(oi->rc < 2)
return;
/* Extend the table */
if(idtab_g.nobjs >= idtab_g.nalloc) {
idtab_g.nalloc = MAX(256, 2*idtab_g.nalloc);
idtab_g.obj = (haddr_t *)HDrealloc(idtab_g.obj, idtab_g.nalloc * sizeof(idtab_g.obj[0]));
} /* end if */
/* Insert the entry */
n = idtab_g.nobjs++;
idtab_g.obj[n] = oi->addr;
} /* end addr_insert() */
/*-------------------------------------------------------------------------
* Function: addr_lookup
*
* Purpose: Check if address has already been encountered
*
* Return: Success: TRUE/FALSE
*
* Failure: (can't fail)
*
* Programmer: Quincey Koziol
* Saturday, November 5, 2005
*
*-------------------------------------------------------------------------
*/
static H5_ATTR_PURE hbool_t
addr_lookup(H5O_info_t *oi)
{
size_t n;
if(oi->rc < 2) return FALSE; /*only one link possible*/
for(n = 0; n < idtab_g.nobjs; n++)
if(H5F_addr_eq(idtab_g.obj[n], oi->addr))
return TRUE;
return FALSE;
} /* end addr_lookup() */
/*-------------------------------------------------------------------------
* Function: addr_reset
*
* Purpose: Reset the address tracking data structures
*
* Return: void
*
* Programmer: Quincey Koziol
* Saturday, November 5, 2005
*
*-------------------------------------------------------------------------
*/
static void
addr_reset(void)
{
if(idtab_g.obj)
HDfree(idtab_g.obj);
idtab_g.obj = NULL;
idtab_g.nalloc = idtab_g.nobjs = 0;
} /* end addr_reset() */
/*-------------------------------------------------------------------------
* Function: attach_ref_attr
*
* Purpose: Create an attribute with object references
*
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
static herr_t
attach_ref_attr(hid_t file_id, hid_t loc_id)
{
char dsetname1[] = "dataset1_pointed_by_ref_attr";
char dsetname2[] = "dataset2_pointed_by_ref_attr";
hid_t did1 = (-1), did2 = (-1), aid = (-1), sid = (-1), sid_ref = (-1);
hsize_t dims[2] = {2,9};
hsize_t dims_ref[1] = {2};
H5R_ref_t ref[2];
int data1[2][9] = {{1,1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1,18}};
int data2[2][9] = {{2,2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2,18}};
/* creates two simple datasets */
if((sid = H5Screate_simple(2, dims, NULL)) < 0) TEST_ERROR
if((sid_ref = H5Screate_simple(1, dims_ref, NULL)) < 0) TEST_ERROR
if((did1 = H5Dcreate2(file_id, dsetname1, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Dwrite(did1, H5T_NATIVE_INT, H5S_ALL , H5S_ALL, H5P_DEFAULT,data1) < 0) TEST_ERROR
if((did2 = H5Dcreate2(file_id, dsetname2, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Dwrite(did2, H5T_NATIVE_INT, H5S_ALL , H5S_ALL, H5P_DEFAULT,data2) < 0) TEST_ERROR
/* create an attribute with two object references */
if(H5Rcreate_object(file_id, dsetname1, H5P_DEFAULT, &ref[0]) < 0) TEST_ERROR
if(H5Rcreate_object(file_id, dsetname2, H5P_DEFAULT, &ref[1]) < 0) TEST_ERROR
if((aid = H5Acreate2(loc_id, "obj_ref_attr", H5T_STD_REF, sid_ref, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Awrite(aid, H5T_STD_REF, ref) < 0) TEST_ERROR
if(H5Sclose(sid) < 0) TEST_ERROR
if(H5Sclose(sid_ref) < 0) TEST_ERROR
if(H5Dclose(did1) < 0) TEST_ERROR
if(H5Dclose(did2) < 0) TEST_ERROR
if(H5Aclose(aid) < 0) TEST_ERROR
if(H5Rdestroy(&ref[0]) < 0) TEST_ERROR
if(H5Rdestroy(&ref[1]) < 0) TEST_ERROR
return 0;
error:
H5E_BEGIN_TRY {
H5Sclose(sid);
H5Sclose(sid_ref);
H5Dclose(did1);
H5Dclose(did2);
H5Aclose(aid);
H5Rdestroy(&ref[0]);
H5Rdestroy(&ref[1]);
} H5E_END_TRY;
return(-1);
}
/*-------------------------------------------------------------------------
* Function: attach_reg_ref_attr
*
* Purpose: Create an attribute with object references
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Peter Cao
* Monday, March 5, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
attach_reg_ref_attr(hid_t file_id, hid_t loc_id)
{
const char dsetnamev[] = "dataset_pointed_by_reg_ref_attr";
hid_t aid = (-1);
hid_t space_id = (-1); /* dataspace identifiers */
hid_t spacer_id = (-1); /* dataspace identifiers */
hid_t dsetv_id = (-1); /*dataset identifiers*/
hsize_t dims[2] = {2,9};
hsize_t dimsr[1] = {2};
int rank = 2;
int rankr =1;
H5R_ref_t ref[2];
int data[2][9] = {{1,1,2,3,3,4,5,5,999},{1,2,2,3,4,4,5,6,999}};
hsize_t start[2] = {0, 3};
hsize_t count[2] = {2, 3};
hsize_t coord[3][2] = {{0, 0}, {1, 6}, {0, 8}};
size_t num_points = 3;
/* create a 2D dataset */
if((space_id = H5Screate_simple(rank, dims, NULL)) < 0) TEST_ERROR
if((spacer_id = H5Screate_simple(rankr, dimsr, NULL)) < 0) TEST_ERROR
if((dsetv_id = H5Dcreate2(file_id, dsetnamev, H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Dwrite(dsetv_id, H5T_NATIVE_INT, H5S_ALL , H5S_ALL, H5P_DEFAULT,data) < 0) TEST_ERROR
/* create reg_ref of block selection */
if(H5Sselect_hyperslab(space_id,H5S_SELECT_SET,start,NULL,count,NULL) < 0) TEST_ERROR
if(H5Rcreate_region(file_id, dsetnamev, space_id, H5P_DEFAULT, &ref[0]) < 0) TEST_ERROR
/* create reg_ref of point selection */
if(H5Sselect_none(space_id) < 0) TEST_ERROR
if(H5Sselect_elements(space_id, H5S_SELECT_SET, num_points, (const hsize_t *)coord) < 0) TEST_ERROR
if(H5Rcreate_region(file_id, dsetnamev, space_id, H5P_DEFAULT, &ref[1]) < 0) TEST_ERROR
/* create reg_ref attribute */
if((aid = H5Acreate2(loc_id, "reg_ref_attr", H5T_STD_REF, spacer_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Awrite(aid, H5T_STD_REF, ref) < 0) TEST_ERROR
/* attach the reg_ref attribute to the dataset itself */
if(H5Aclose(aid) < 0) TEST_ERROR
if((aid = H5Acreate2(dsetv_id, "reg_ref_attr", H5T_STD_REF, spacer_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Awrite(aid, H5T_STD_REF, ref) < 0) TEST_ERROR
if(H5Sclose(spacer_id) < 0) TEST_ERROR
if(H5Sclose(space_id) < 0) TEST_ERROR
if(H5Dclose(dsetv_id) < 0) TEST_ERROR
if(H5Aclose(aid) < 0) TEST_ERROR
if(H5Rdestroy(&ref[0]) < 0) TEST_ERROR
if(H5Rdestroy(&ref[1]) < 0) TEST_ERROR
return 0;
error:
H5E_BEGIN_TRY {
H5Sclose(spacer_id);
H5Sclose(space_id);
H5Dclose(dsetv_id);
H5Aclose(aid);
H5Rdestroy(&ref[0]);
H5Rdestroy(&ref[1]);
} H5E_END_TRY;
return(-1);
}
/*-------------------------------------------------------------------------
* Function: create_reg_ref_dataset
*
* Purpose: Create a dataset with region references
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Peter Cao
* Friday, August 4, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
create_reg_ref_dataset(hid_t file_id, hid_t loc_id)
{
const char dsetnamev[] = "dataset_pointed_by_ref_dset";
const char dsetnamer[] = "dataset_with_reg_ref";
const char dsetnamer1[] = "compact_dataset_with_reg_ref";
const char dsetnamer2[] = "compressed_dataset_with_reg_ref";
hid_t space_id = (-1); /* dataspace identifiers */
hid_t spacer_id = (-1);
hid_t dsetv_id = (-1); /*dataset identifiers*/
hid_t dsetr_id = (-1);
hsize_t dims[2] = {2,9};
hsize_t dimsr[1] = {2};
int rank = 2;
int rankr =1;
hsize_t chunk_size=1;
H5R_ref_t ref[2];
int data[2][9] = {{1,1,2,3,3,4,5,5,6},{1,2,2,3,4,4,5,6,6}};
hsize_t start[2];
hsize_t count[2];
hsize_t coord[3][2] = {{0, 0}, {1, 6}, {0, 8}};
size_t num_points = 3;
hid_t pid = (-1);
if((space_id = H5Screate_simple(rank, dims, NULL)) < 0) TEST_ERROR
if((spacer_id = H5Screate_simple(rankr, dimsr, NULL)) < 0) TEST_ERROR
if((dsetv_id = H5Dcreate2(file_id, dsetnamev, H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Dwrite(dsetv_id, H5T_NATIVE_INT, H5S_ALL , H5S_ALL, H5P_DEFAULT,data) < 0) TEST_ERROR
if((dsetr_id = H5Dcreate2(loc_id, dsetnamer, H5T_STD_REF, spacer_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
start[0] = 0;
start[1] = 3;
count[0] = 2;
count[1] = 3;
if(H5Sselect_hyperslab(space_id,H5S_SELECT_SET,start,NULL,count,NULL) < 0) TEST_ERROR
if(H5Rcreate_region(file_id, dsetnamev, space_id, H5P_DEFAULT, &ref[0]) < 0) TEST_ERROR
if(H5Sselect_none(space_id) < 0) TEST_ERROR
if(H5Sselect_elements(space_id, H5S_SELECT_SET, num_points, (const hsize_t *)coord) < 0) TEST_ERROR
if(H5Rcreate_region(file_id, dsetnamev, space_id, H5P_DEFAULT, &ref[1]) < 0) TEST_ERROR
if(H5Dwrite(dsetr_id, H5T_STD_REF, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref) < 0) TEST_ERROR
if(H5Dclose(dsetr_id) < 0) TEST_ERROR
/* create and set compact plist */
if((pid = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR
if(H5Pset_layout(pid, H5D_COMPACT) < 0) TEST_ERROR
if((dsetr_id = H5Dcreate2(loc_id, dsetnamer1, H5T_STD_REF, spacer_id, H5P_DEFAULT, pid, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Pclose(pid) < 0) TEST_ERROR
if(H5Dwrite(dsetr_id, H5T_STD_REF, H5S_ALL, H5S_ALL, H5P_DEFAULT, ref) < 0) TEST_ERROR
if(H5Dclose(dsetr_id) < 0) TEST_ERROR
/* create and set comp & chunk plist */
if((pid = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR
if(H5Pset_chunk(pid, 1, &chunk_size) < 0) TEST_ERROR
if(H5Pset_deflate(pid, 9) < 0) TEST_ERROR
if((dsetr_id = H5Dcreate2(loc_id, dsetnamer2, H5T_STD_REF, spacer_id, H5P_DEFAULT, pid, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Pclose(pid) < 0) TEST_ERROR
if(H5Dwrite(dsetr_id, H5T_STD_REF, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref) < 0) TEST_ERROR
if(H5Dclose(dsetr_id) < 0) TEST_ERROR
if(H5Sclose(space_id) < 0) TEST_ERROR
if(H5Sclose(spacer_id) < 0) TEST_ERROR
if(H5Dclose(dsetv_id) < 0) TEST_ERROR
if(H5Rdestroy(&ref[0]) < 0) TEST_ERROR
if(H5Rdestroy(&ref[1]) < 0) TEST_ERROR
return 0;
error:
H5E_BEGIN_TRY {
H5Sclose(space_id);
H5Sclose(spacer_id);
H5Dclose(dsetr_id);
H5Dclose(dsetv_id);
H5Pclose(pid);
H5Rdestroy(&ref[0]);
H5Rdestroy(&ref[1]);
} H5E_END_TRY;
return(-1);
}
/*-------------------------------------------------------------------------
* Function: test_copy_attach_attributes
*
* Purpose: Attach NUM_ATTRIBUTES attributes to the object to be copied
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Peter Cao
* Friday, September 30, 2005
*
*-------------------------------------------------------------------------
*/
static int
test_copy_attach_attributes(hid_t loc_id, hid_t type_id)
{
hid_t aid = -1, sid = -1;
char attr_name[ATTR_NAME_LEN];
int attr_data[2];
hsize_t dim1 = 2;
hid_t acpl = -1;
unsigned u;
int ret_value = -1;
if((sid = H5Screate_simple(1, &dim1, NULL)) < 0 )
goto done;
/* Create attribute creation plist */
if((acpl = H5Pcreate(H5P_ATTRIBUTE_CREATE)) < 0)
goto done;
for(u = 0; u < num_attributes_g; u++) {
HDsprintf(attr_name, "%u attr", u);
/* Set attribute data */
attr_data[0] = (int)(100 * u);
attr_data[1] = (int)(200 * u);
/* Set attribute character set (alternate) */
if(u % 2) {
if(H5Pset_char_encoding(acpl, H5T_CSET_ASCII) < 0)
goto done;
} /* end if */
else
if(H5Pset_char_encoding(acpl, H5T_CSET_UTF8) < 0)
goto done;
if((aid = H5Acreate2(loc_id, attr_name, type_id, sid, acpl, H5P_DEFAULT)) < 0)
goto done;
if(H5Awrite(aid, H5T_NATIVE_INT, attr_data) < 0)
goto done;
if(aid > 0)
H5Aclose(aid);
aid = -1;
}
ret_value = 0;
done:
if(sid > 0)
H5Sclose(sid);
if(aid > 0)
H5Aclose(aid);
if(acpl > 0)
H5Pclose(acpl);
return ret_value;
}
/*-------------------------------------------------------------------------
* Function: compare_attribute
*
* Purpose: Compare two attributes to check that they are equal
*
* Return: TRUE if attributes are equal/FALSE if they are different
*
* Programmer: Peter Cao
* Saturday, December 17, 2005
*
*-------------------------------------------------------------------------
*/
static int
compare_attribute(hid_t aid, hid_t aid2, hid_t pid, const void *wbuf, hid_t obj_owner)
{
hid_t sid = -1, sid2 = -1; /* Dataspace IDs */
hid_t tid = -1, tid2 = -1; /* Datatype IDs */
size_t elmt_size; /* Size of datatype */
htri_t is_committed; /* If the datatype is committed */
htri_t is_committed2; /* If the datatype is committed */
H5A_info_t ainfo; /* Attribute info */
H5A_info_t ainfo2; /* Attribute info */
hssize_t nelmts; /* # of elements in dataspace */
void *rbuf = NULL; /* Buffer for reading raw data */
void *rbuf2 = NULL; /* Buffer for reading raw data */
/* Check the character sets are equal */
if(H5Aget_info(aid, &ainfo) < 0) TEST_ERROR
if(H5Aget_info(aid2, &ainfo2) < 0) TEST_ERROR
if(ainfo.cset != ainfo2.cset) TEST_ERROR
/* Check the creation orders are equal (if appropriate) */
if(ainfo.corder_valid != ainfo2.corder_valid) TEST_ERROR
if(ainfo.corder_valid)
if(ainfo.corder != ainfo2.corder) TEST_ERROR
/* Check the datatypes are equal */
/* Open the datatype for the source attribute */
if((tid = H5Aget_type(aid)) < 0) TEST_ERROR
/* Open the datatype for the destination attribute */
if((tid2 = H5Aget_type(aid2)) < 0) TEST_ERROR
/* Check that both datatypes are committed/not committed */
if((is_committed = H5Tcommitted(tid)) < 0) TEST_ERROR
if((is_committed2 = H5Tcommitted(tid2)) < 0) TEST_ERROR
if(is_committed != is_committed2) TEST_ERROR
/* Compare the datatypes */
if(H5Tequal(tid, tid2) != TRUE) TEST_ERROR
/* Determine the size of datatype (for later) */
if((elmt_size = H5Tget_size(tid)) == 0) TEST_ERROR
/* Check the dataspaces are equal */
/* Open the dataspace for the source attribute */
if((sid = H5Aget_space(aid)) < 0) TEST_ERROR
/* Open the dataspace for the destination attribute */
if((sid2 = H5Aget_space(aid2)) < 0) TEST_ERROR
/* Compare the dataspaces */
if(H5Sextent_equal(sid, sid2) != TRUE) TEST_ERROR
/* Determine the number of elements in dataspace (for later) */
if((nelmts = H5Sget_simple_extent_npoints(sid2)) < 0) TEST_ERROR
/* Check the raw data is equal */
/* Allocate & initialize space for the raw data buffers */
if((rbuf = HDcalloc( elmt_size, (size_t)nelmts)) == NULL) TEST_ERROR
if((rbuf2 = HDcalloc( elmt_size, (size_t)nelmts)) == NULL) TEST_ERROR
/* Read data from the source attribute */
if(H5Aread(aid, tid, rbuf) < 0) TEST_ERROR
/* Read data from the destination attribute */
if(H5Aread(aid2, tid2, rbuf2) < 0) TEST_ERROR
/* Check raw data read in against data written out */
if(wbuf) {
if(!compare_data(aid, (hid_t)0, pid, tid, (size_t)nelmts, wbuf, rbuf, obj_owner)) TEST_ERROR
if(!compare_data(aid2, (hid_t)0, pid, tid2, (size_t)nelmts, wbuf, rbuf2, obj_owner)) TEST_ERROR
} /* end if */
/* Don't have written data, just compare data between the two attributes */
else
if(!compare_data(aid, aid2, pid, tid, (size_t)nelmts, rbuf, rbuf2, obj_owner)) TEST_ERROR
/* Reclaim vlen data, if necessary */
if(H5Tdetect_class(tid, H5T_VLEN) == TRUE || H5Tdetect_class(tid, H5T_REFERENCE) == TRUE)
if(H5Treclaim(tid, sid, H5P_DEFAULT, rbuf) < 0) TEST_ERROR
if(H5Tdetect_class(tid2, H5T_VLEN) == TRUE || H5Tdetect_class(tid2, H5T_REFERENCE) == TRUE)
if(H5Treclaim(tid2, sid2, H5P_DEFAULT, rbuf2) < 0) TEST_ERROR
/* Release raw data buffers */
HDfree(rbuf);
rbuf = NULL;
HDfree(rbuf2);
rbuf2 = NULL;
/* close the source dataspace */
if(H5Sclose(sid) < 0) TEST_ERROR
/* close the destination dataspace */
if(H5Sclose(sid2) < 0) TEST_ERROR
/* close the source datatype */
if(H5Tclose(tid) < 0) TEST_ERROR
/* close the destination datatype */
if(H5Tclose(tid2) < 0) TEST_ERROR
return TRUE;
error:
if(rbuf)
HDfree(rbuf);
if(rbuf2)
HDfree(rbuf2);
H5E_BEGIN_TRY {
H5Sclose(sid2);
H5Sclose(sid);
H5Tclose(tid2);
H5Tclose(tid);
} H5E_END_TRY;
return FALSE;
} /* end compare_attribute() */
/*-------------------------------------------------------------------------
* Function: compare_std_attributes
*
* Purpose: Compare "standard" attributes on two objects to check that they are equal
*
* Return: TRUE if objects have same attributes/FALSE if they are different
*
* Programmer: Quincey Koziol
* Monday, October 31, 2005
*
* Note: This isn't very general, the attributes are assumed to be
* those written in test_copy_attach_attributes().
*
*-------------------------------------------------------------------------
*/
static int
compare_std_attributes(hid_t oid, hid_t oid2, hid_t pid)
{
hid_t aid = -1, aid2 = -1; /* Attribute IDs */
H5O_info_t oinfo1, oinfo2; /* Object info */
unsigned cpy_flags; /* Object copy flags */
/* Retrieve the object copy flags from the property list, if it's non-DEFAULT */
if(pid != H5P_DEFAULT) {
if(H5Pget_copy_object(pid, &cpy_flags) < 0) TEST_ERROR
} /* end if */
else
cpy_flags = 0;
/* Check the number of attributes on source dataset */
if(H5Oget_info2(oid, &oinfo1, H5O_INFO_NUM_ATTRS) < 0) TEST_ERROR
/* Check the number of attributes on destination dataset */
if(H5Oget_info2(oid2, &oinfo2, H5O_INFO_NUM_ATTRS) < 0) TEST_ERROR
if(cpy_flags & H5O_COPY_WITHOUT_ATTR_FLAG) {
/* Check that the destination has no attributes */
if(oinfo2.num_attrs != 0) TEST_ERROR
} /* end if */
else {
char attr_name[ATTR_NAME_LEN]; /* Attribute name */
unsigned i; /* Local index variable */
/* Compare the number of attributes */
if(oinfo1.num_attrs != oinfo2.num_attrs) TEST_ERROR
/* Check the attributes are equal */
for(i = 0; i < (unsigned)oinfo1.num_attrs; i++) {
if((aid = H5Aopen_by_idx(oid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)i, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Aget_name(aid, (size_t)ATTR_NAME_LEN, attr_name) < 0) TEST_ERROR
if((aid2 = H5Aopen(oid2, attr_name, H5P_DEFAULT)) < 0) TEST_ERROR
/* Check the attributes are equal */
if(!compare_attribute(aid, aid2, pid, NULL, oid)) TEST_ERROR
/* Close the attributes */
if(H5Aclose(aid) < 0) TEST_ERROR
if(H5Aclose(aid2) < 0) TEST_ERROR
} /* end for */
} /* end if */
/* Objects should be the same. :-) */
return TRUE;
error:
H5E_BEGIN_TRY {
H5Aclose(aid2);
H5Aclose(aid);
} H5E_END_TRY;
return FALSE;
} /* end compare_std_attributes() */
/*-------------------------------------------------------------------------
* Function: compare_data
*
* Purpose: Compare two buffers of data to check that they are equal
*
* Return: TRUE if buffer are equal/FALSE if they are different
*
* Programmer: Quincey Koziol
* Monday, November 21, 2005
*
*-------------------------------------------------------------------------
*/
static int
compare_data(hid_t parent1, hid_t parent2, hid_t pid, hid_t tid, size_t nelmts,
const void *buf1, const void *buf2, hid_t obj_owner)
{
size_t elmt_size; /* Size of an element */
/* Check size of each element */
if((elmt_size = H5Tget_size(tid)) == 0) TEST_ERROR
/* If the type is a compound containing a vlen, loop over all elements for
* each compound member. Compounds containing reference are not supported
* yet. */
if((H5Tget_class(tid) == H5T_COMPOUND)
&& (H5Tdetect_class(tid, H5T_VLEN) == TRUE)) {
hid_t memb_id; /* Member id */
const uint8_t *memb1; /* Pointer to current member */
const uint8_t *memb2; /* Pointer to current member */
int nmembs; /* Number of members */
size_t memb_off; /* Member offset */
size_t memb_size; /* Member size */
unsigned memb_idx; /* Member index */
size_t elmt; /* Current element */
/* Get number of members in compound */
if((nmembs = H5Tget_nmembers(tid)) < 0) TEST_ERROR
/* Loop over members */
for(memb_idx=0; memb_idx<(unsigned)nmembs; memb_idx++) {
/* Get member offset. Note that we cannot check for an error here.
*/
memb_off = H5Tget_member_offset(tid, memb_idx);
/* Get member id */
if((memb_id = H5Tget_member_type(tid, memb_idx)) < 0) TEST_ERROR
/* Get member size */
if((memb_size = H5Tget_size(memb_id)) == 0) TEST_ERROR
/* Set up pointers to member in the first element */
memb1 = (const uint8_t *)buf1 + memb_off;
memb2 = (const uint8_t *)buf2 + memb_off;
/* Check if this member contains (or is) a vlen */
if(H5Tget_class(memb_id) == H5T_VLEN) {
hid_t base_id; /* vlen base type id */
/* Get base type of vlen datatype */
if((base_id = H5Tget_super(memb_id)) < 0) TEST_ERROR
/* Iterate over all elements, recursively calling this function
* for each */
for(elmt=0; elmt<nelmts; elmt++) {
/* Check vlen lengths */
if(((const hvl_t *)((const void *)memb1))->len
!= ((const hvl_t *)((const void *)memb2))->len)
TEST_ERROR
/* Check vlen data */
if(!compare_data(parent1, parent2, pid, base_id,
((const hvl_t *)((const void *)memb1))->len,
((const hvl_t *)((const void *)memb1))->p,
((const hvl_t *)((const void *)memb2))->p, obj_owner))
TEST_ERROR
/* Update member pointers */
memb1 += elmt_size;
memb2 += elmt_size;
} /* end for */
} else {
/* vlens cannot currently be nested below the top layer of a
* compound */
HDassert(H5Tdetect_class(memb_id, H5T_VLEN) == FALSE);
/* Iterate over all elements, calling memcmp() for each */
for(elmt=0; elmt<nelmts; elmt++) {
if(HDmemcmp(memb1, memb2, memb_size))
TEST_ERROR
/* Update member pointers */
memb1 += elmt_size;
memb2 += elmt_size;
} /* end for */
} /* end else */
} /* end for */
} else if(H5Tdetect_class(tid, H5T_VLEN) == TRUE) {
const hvl_t *vl_buf1, *vl_buf2; /* Aliases for buffers to compare */
hid_t base_tid; /* Base type of vlen datatype */
size_t u; /* Local index variable */
/* Check for "simple" vlen datatype */
if(H5Tget_class(tid) != H5T_VLEN) TEST_ERROR
/* Get base type of vlen datatype */
if((base_tid = H5Tget_super(tid)) < 0) TEST_ERROR
/* Loop over elements in buffers */
vl_buf1 = (const hvl_t *)buf1;
vl_buf2 = (const hvl_t *)buf2;
for(u = 0; u < nelmts; u++, vl_buf1++, vl_buf2++) {
/* Check vlen lengths */
if(vl_buf1->len != vl_buf2->len) TEST_ERROR
/* Check vlen data */
if(!compare_data(parent1, parent2, pid, base_tid, vl_buf1->len, vl_buf1->p, vl_buf2->p, obj_owner)) TEST_ERROR
} /* end for */
if(H5Tclose(base_tid) < 0) TEST_ERROR
} /* end if */
else if(H5Tdetect_class(tid, H5T_REFERENCE) == TRUE) {
size_t u; /* Local index variable */
/* Check for "simple" reference datatype */
if(H5Tget_class(tid) != H5T_REFERENCE) TEST_ERROR
/* Check for object or region reference */
if(H5Tequal(tid, H5T_STD_REF) > 0) {
const H5R_ref_t *ref_buf1, *ref_buf2; /* Aliases for buffers to compare */
/* Loop over elements in buffers */
ref_buf1 = (const H5R_ref_t *)buf1;
ref_buf2 = (const H5R_ref_t *)buf2;
for(u = 0; u < nelmts; u++, ref_buf1++, ref_buf2++) {
hid_t obj1_id, obj2_id; /* IDs for objects referenced */
H5O_type_t obj1_type, obj2_type; /* Types of objects referenced */
/* Check for types of objects handled */
if(H5Rget_obj_type3(ref_buf1, H5P_DEFAULT, &obj1_type) < 0) TEST_ERROR
if(H5Rget_obj_type3(ref_buf2, H5P_DEFAULT, &obj2_type) < 0) TEST_ERROR
if(obj1_type != obj2_type) TEST_ERROR
/* Open referenced objects */
if((obj1_id = H5Ropen_object(ref_buf1, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if((obj2_id = H5Ropen_object(ref_buf2, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
/* break the infinite loop when the ref_object points to itself */
if(obj_owner > 0) {
H5O_info_t oinfo1, oinfo2;
if(H5Oget_info2(obj_owner, &oinfo1, H5O_INFO_BASIC) < 0) TEST_ERROR
if(H5Oget_info2(obj1_id, &oinfo2, H5O_INFO_BASIC) < 0) TEST_ERROR
if(H5F_addr_eq(oinfo1.addr, oinfo2.addr)) {
if(H5Oclose(obj1_id) < 0) TEST_ERROR
if(H5Oclose(obj2_id) < 0) TEST_ERROR
return TRUE;
}
}
/* Check for types of objects handled */
switch(obj1_type) {
case H5O_TYPE_DATASET:
if(compare_datasets(obj1_id, obj2_id, pid, NULL) != TRUE) TEST_ERROR
break;
case H5O_TYPE_GROUP:
if(compare_groups(obj1_id, obj2_id, pid, -1, 0) != TRUE) TEST_ERROR
break;
case H5O_TYPE_NAMED_DATATYPE:
if(H5Tequal(obj1_id, obj2_id) != TRUE) TEST_ERROR
break;
case H5O_TYPE_MAP:
/* Maps not supported in native VOL connector */
case H5O_TYPE_UNKNOWN:
case H5O_TYPE_NTYPES:
default:
TEST_ERROR
} /* end switch */
/* Close objects */
if(H5Oclose(obj1_id) < 0) TEST_ERROR
if(H5Oclose(obj2_id) < 0) TEST_ERROR
if(H5Rget_type(ref_buf1) == H5R_DATASET_REGION2) {
hid_t obj1_sid, obj2_sid; /* Dataspace IDs for objects referenced */
/* Get regions for referenced datasets */
if((obj1_sid = H5Ropen_region(ref_buf1, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if((obj2_sid = H5Ropen_region(ref_buf2, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
/* Check if dataspaces are the same shape */
if(H5Sselect_shape_same(obj1_sid, obj2_sid) < 0) TEST_ERROR
/* Close dataspaces */
if(H5Sclose(obj1_sid) < 0) TEST_ERROR
if(H5Sclose(obj2_sid) < 0) TEST_ERROR
} /* end if */
} /* end for */
} /* end if */
else
TEST_ERROR
} /* end else */
else
if(HDmemcmp(buf1, buf2, (elmt_size * nelmts))) TEST_ERROR
/* Data should be the same. :-) */
return TRUE;
error:
return FALSE;
} /* end compare_data() */
/*-------------------------------------------------------------------------
* Function: compare_datasets
*
* Purpose: Compare two datasets to check that they are equal
*
* Return: TRUE if datasets are equal/FALSE if they are different
*
* Programmer: Quincey Koziol
* Tuesday, October 25, 2005
*
*-------------------------------------------------------------------------
*/
static int
compare_datasets(hid_t did, hid_t did2, hid_t pid, const void *wbuf)
{
hid_t sid = -1, sid2 = -1; /* Dataspace IDs */
hid_t tid = -1, tid2 = -1; /* Datatype IDs */
hid_t dcpl = -1, dcpl2 = -1; /* Dataset creation property list IDs */
size_t elmt_size; /* Size of datatype */
htri_t is_committed; /* If the datatype is committed */
htri_t is_committed2; /* If the datatype is committed */
int nfilters; /* Number of filters applied to dataset */
hssize_t nelmts; /* # of elements in dataspace */
void *rbuf = NULL; /* Buffer for reading raw data */
void *rbuf2 = NULL; /* Buffer for reading raw data */
H5D_space_status_t space_status; /* Dataset's raw dataspace status */
H5D_space_status_t space_status2; /* Dataset's raw dataspace status */
/* Check the datatypes are equal */
/* Open the datatype for the source dataset */
if((tid = H5Dget_type(did)) < 0) TEST_ERROR
/* Open the datatype for the destination dataset */
if((tid2 = H5Dget_type(did2)) < 0) TEST_ERROR
/* Check that both datatypes are committed/not committed */
if((is_committed = H5Tcommitted(tid)) < 0) TEST_ERROR
if((is_committed2 = H5Tcommitted(tid2)) < 0) TEST_ERROR
if(is_committed != is_committed2) TEST_ERROR
/* Compare the datatypes */
if(H5Tequal(tid, tid2) != TRUE) TEST_ERROR
/* Determine the size of datatype (for later) */
if((elmt_size = H5Tget_size(tid)) == 0) TEST_ERROR
/* Check the dataspaces are equal */
/* Open the dataspace for the source dataset */
if((sid = H5Dget_space(did)) < 0) TEST_ERROR
/* Open the dataspace for the destination dataset */
if((sid2 = H5Dget_space(did2)) < 0) TEST_ERROR
/* Compare the dataspaces */
if(H5Sextent_equal(sid, sid2) != TRUE) TEST_ERROR
/* Determine the number of elements in dataspace (for later) */
if((nelmts = H5Sget_simple_extent_npoints(sid)) < 0) TEST_ERROR
/* Check the dataset creation property lists are equal */
/* Open the dataset creation property list for the source dataset */
if((dcpl = H5Dget_create_plist(did)) < 0) TEST_ERROR
/* Open the dataset creation property list for the destination dataset */
if((dcpl2 = H5Dget_create_plist(did2)) < 0) TEST_ERROR
/* Compare the rest of the dataset creation property lists */
if(H5Pequal(dcpl, dcpl2) != TRUE) TEST_ERROR
/* Get the number of filters on dataset (for later) */
if((nfilters = H5Pget_nfilters(dcpl)) < 0) TEST_ERROR
/* close the source dataset creation property list */
if(H5Pclose(dcpl) < 0) TEST_ERROR
/* close the destination dataset creation property list */
if(H5Pclose(dcpl2) < 0) TEST_ERROR
/* Check the allocated storage is the same */
/* Check that the space allocation status is the same */
if(H5Dget_space_status(did, &space_status) < 0) TEST_ERROR
if(H5Dget_space_status(did2, &space_status2) < 0) TEST_ERROR
if(space_status != space_status2) TEST_ERROR
/* Check that the space used is the same */
/* (Don't check if the dataset is filtered (i.e. compressed, etc.) and
* the datatype is VLEN, since the addresses for the vlen
* data in each dataset will (probably) be different and the storage
* size will thus vary)
*/
if(!(nfilters > 0 && (H5Tdetect_class(tid, H5T_VLEN) ||
(H5Tdetect_class(tid, H5T_REFERENCE) && H5Tequal(tid, H5T_STD_REF))))) {
hsize_t storage_size = H5Dget_storage_size(did); /* Dataset's raw data storage size */
hsize_t storage_size2 = H5Dget_storage_size(did2); /* 2nd Dataset's raw data storage size */
if(storage_size != storage_size2) TEST_ERROR
} /* end if */
/* Check the raw data is equal */
/* Allocate & initialize space for the raw data buffers */
if((rbuf = HDcalloc( elmt_size, (size_t)nelmts)) == NULL) TEST_ERROR
if((rbuf2 = HDcalloc( elmt_size, (size_t)nelmts)) == NULL) TEST_ERROR
/* Read data from datasets */
if(H5Dread(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0) TEST_ERROR
if(H5Dread(did2, tid2, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf2) < 0) TEST_ERROR
/* Check raw data read in against data written out */
if(wbuf) {
if(!compare_data(did, (hid_t)0, pid, tid, (size_t)nelmts, wbuf, rbuf, did)) TEST_ERROR
if(!compare_data(did2, (hid_t)0, pid, tid2, (size_t)nelmts, wbuf, rbuf2, did2)) TEST_ERROR
} /* end if */
/* Don't have written data, just compare data between the two datasets */
else
if(!compare_data(did, did2, pid, tid, (size_t)nelmts, rbuf, rbuf2, did)) TEST_ERROR
/* Reclaim vlen data, if necessary */
if(H5Tdetect_class(tid, H5T_VLEN) == TRUE || H5Tdetect_class(tid, H5T_REFERENCE) == TRUE)
if(H5Treclaim(tid, sid, H5P_DEFAULT, rbuf) < 0) TEST_ERROR
if(H5Tdetect_class(tid2, H5T_VLEN) == TRUE || H5Tdetect_class(tid2, H5T_REFERENCE) == TRUE)
if(H5Treclaim(tid2, sid2, H5P_DEFAULT, rbuf2) < 0) TEST_ERROR
/* Release raw data buffers */
HDfree(rbuf);
rbuf = NULL;
HDfree(rbuf2);
rbuf2 = NULL;
/* close the source dataspace */
if(H5Sclose(sid) < 0) TEST_ERROR
/* close the destination dataspace */
if(H5Sclose(sid2) < 0) TEST_ERROR
/* close the source datatype */
if(H5Tclose(tid) < 0) TEST_ERROR
/* close the destination datatype */
if(H5Tclose(tid2) < 0) TEST_ERROR
/* Check if the attributes are equal */
if(compare_std_attributes(did, did2, pid) != TRUE) TEST_ERROR
/* Datasets should be the same. :-) */
return TRUE;
error:
H5E_BEGIN_TRY {
if(rbuf)
HDfree(rbuf);
if(rbuf2)
HDfree(rbuf2);
H5Pclose(dcpl2);
H5Pclose(dcpl);
H5Sclose(sid2);
H5Sclose(sid);
H5Tclose(tid2);
H5Tclose(tid);
} H5E_END_TRY;
return FALSE;
} /* end compare_datasets() */
/*-------------------------------------------------------------------------
* Function: compare_groups
*
* Purpose: Compare two groups to check that they are "equal"
*
* Return: TRUE if group are equal/FALSE if they are different
*
* Programmer: Quincey Koziol
* Monday, October 31, 2005
*
*-------------------------------------------------------------------------
*/
static int
compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth, unsigned copy_flags)
{
H5G_info_t ginfo; /* Group info struct */
H5G_info_t ginfo2; /* Group info struct */
hsize_t idx; /* Index over the objects in group */
unsigned cpy_flags; /* Object copy flags */
/* Retrieve the object copy flags from the property list, if it's non-DEFAULT */
if(pid != H5P_DEFAULT) {
if(H5Pget_copy_object(pid, &cpy_flags) < 0) TEST_ERROR
} /* end if */
else
cpy_flags = 0;
/* Check if both groups have the same # of objects */
if(H5Gget_info(gid, &ginfo) < 0) TEST_ERROR
if(H5Gget_info(gid2, &ginfo2) < 0) TEST_ERROR
if((cpy_flags & H5O_COPY_SHALLOW_HIERARCHY_FLAG) && depth == 0) {
if(ginfo2.nlinks != 0) TEST_ERROR
} /* end if */
else {
if(ginfo.nlinks != ginfo2.nlinks) TEST_ERROR
} /* end if */
/* Check contents of groups */
if(ginfo2.nlinks > 0) {
char objname[NAME_BUF_SIZE]; /* Name of object in group */
char objname2[NAME_BUF_SIZE]; /* Name of object in group */
H5L_info_t linfo; /* Link information */
H5L_info_t linfo2; /* Link information */
/* Loop over contents of groups */
for(idx = 0; idx < ginfo.nlinks; idx++) {
/* Check name of objects */
if(H5Lget_name_by_idx(gid, ".", H5_INDEX_NAME, H5_ITER_INC, idx, objname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT) < 0) TEST_ERROR
if(H5Lget_name_by_idx(gid2, ".", H5_INDEX_NAME, H5_ITER_INC, idx, objname2, (size_t)NAME_BUF_SIZE, H5P_DEFAULT) < 0) TEST_ERROR
if(HDstrcmp(objname, objname2)) TEST_ERROR
/* Get link info */
if(H5Lget_info(gid, objname, &linfo, H5P_DEFAULT) < 0) TEST_ERROR
if(H5Lget_info(gid2, objname2, &linfo2, H5P_DEFAULT) < 0) TEST_ERROR
if(linfo.type != linfo2.type) TEST_ERROR
/* Extra checks for "real" objects */
if(linfo.type == H5L_TYPE_HARD) {
hid_t oid, oid2; /* IDs of objects within group */
H5O_info_t oinfo, oinfo2; /* Object info */
/* Compare some pieces of the object info */
if(H5Oget_info_by_name2(gid, objname, &oinfo, H5O_INFO_BASIC|H5O_INFO_HDR, H5P_DEFAULT) < 0) TEST_ERROR
if(H5Oget_info_by_name2(gid2, objname2, &oinfo2, H5O_INFO_BASIC|H5O_INFO_HDR, H5P_DEFAULT) < 0) TEST_ERROR
if(oinfo.type != oinfo2.type) TEST_ERROR
if(oinfo.rc != oinfo2.rc) TEST_ERROR
/* If NULL messages are preserved, the number of messages
* should be the same in the destination.
* Otherwise, it should simply be true that the number
* of messages hasn't increased.
*/
if(H5O_COPY_PRESERVE_NULL_FLAG & copy_flags) {
if(oinfo.hdr.nmesgs != oinfo2.hdr.nmesgs)
;
else
if(oinfo.hdr.nmesgs < oinfo2.hdr.nmesgs) TEST_ERROR
}
/* Check for object already having been compared */
if(addr_lookup(&oinfo))
continue;
else
addr_insert(&oinfo);
/* Open objects */
if((oid = H5Oopen(gid, objname, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
if((oid2 = H5Oopen(gid2, objname2, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* Compare objects within group */
switch(oinfo.type) {
case H5O_TYPE_GROUP:
/* Compare groups */
if(compare_groups(oid, oid2, pid, depth - 1, copy_flags) != TRUE) TEST_ERROR
break;
case H5O_TYPE_DATASET:
/* Compare datasets */
if(compare_datasets(oid, oid2, pid, NULL) != TRUE) TEST_ERROR
break;
case H5O_TYPE_NAMED_DATATYPE:
/* Compare datatypes */
if(H5Tequal(oid, oid2) != TRUE) TEST_ERROR
break;
case H5O_TYPE_MAP:
HDassert(0 && "maps not supported in native VOL connector");
case H5O_TYPE_UNKNOWN:
case H5O_TYPE_NTYPES:
default:
HDassert(0 && "Unknown type of object");
break;
} /* end switch */
/* Close objects */
if(H5Oclose(oid) < 0) TEST_ERROR
if(H5Oclose(oid2) < 0) TEST_ERROR
} /* end if */
else {
/* Check that both links are the same size */
if(linfo.u.val_size != linfo2.u.val_size) TEST_ERROR
/* Compare link values */
if(linfo.type == H5L_TYPE_SOFT ||
(linfo.type >= H5L_TYPE_UD_MIN && linfo.type <= H5L_TYPE_MAX)) {
char linkval[NAME_BUF_SIZE]; /* Link value */
char linkval2[NAME_BUF_SIZE]; /* Link value */
/* Get link values */
HDassert(linfo.u.val_size <= NAME_BUF_SIZE);
if(H5Lget_val(gid, objname, linkval, (size_t)NAME_BUF_SIZE, H5P_DEFAULT) < 0) TEST_ERROR
if(H5Lget_val(gid2, objname2, linkval2, (size_t)NAME_BUF_SIZE, H5P_DEFAULT) < 0) TEST_ERROR
/* Compare link data */
if(HDmemcmp(linkval, linkval2, linfo.u.val_size)) TEST_ERROR
} /* end else-if */
else {
HDassert(0 && "Unknown type of link");
} /* end else */
} /* end else */
} /* end for */
} /* end if */
/* Check if the attributes are equal */
if(compare_std_attributes(gid, gid2, pid) != TRUE) TEST_ERROR
/* Groups should be the same. :-) */
return TRUE;
error:
H5E_BEGIN_TRY {
} H5E_END_TRY;
return FALSE;
} /* end compare_groups() */
/*-------------------------------------------------------------------------
* Function: test_copy_option
*
* Purpose: Create a group in SRC file and copy it to DST file
*
* Return: Success: 0
* Failure: number of errors
*
* Programmer: Peter Cao
* March 11, 2006
*
*-------------------------------------------------------------------------
*/
static int
test_copy_option(hid_t fcpl_src, hid_t fcpl_dst, hid_t src_fapl, hid_t dst_fapl,
unsigned flag, hbool_t crt_intermediate_grp, const char* test_desciption)
{
hid_t fid_src = -1, fid_dst = -1, fid_ext = -1; /* File IDs */
hid_t sid = -1; /* Dataspace ID */
hid_t did = -1; /* Dataset ID */
hid_t gid=-1, gid2=-1, gid_ref=-1; /* Group IDs */
hid_t gid_sub=-1, gid_sub_sub=-1; /* Sub-group ID */
hid_t pid=-1, lcpl_id=-1; /* Property IDs */
unsigned cpy_flags; /* Object copy flags */
int depth = -1; /* Copy depth */
hsize_t dim2d[2];
int buf[DIM_SIZE_1][DIM_SIZE_2];
int i, j;
char src_filename[NAME_BUF_SIZE];
char dst_filename[NAME_BUF_SIZE];
TESTING(test_desciption);
/* set initial data values */
for (i=0; i<DIM_SIZE_1; i++)
for (j=0; j<DIM_SIZE_2; j++)
buf[i][j] = 10000 + 100*i+j;
/* Initialize the filenames */
h5_fixname(FILENAME[0], src_fapl, src_filename, sizeof src_filename);
h5_fixname(FILENAME[1], dst_fapl, dst_filename, sizeof dst_filename);
/* Reset file address checking info */
addr_reset();
/* create source file */
if((fid_src = H5Fcreate(src_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR
/* create group at the SRC file */
if((gid = H5Gcreate2(fid_src, NAME_GROUP_TOP, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
/* attach attributes to the group */
if(test_copy_attach_attributes(gid, H5T_NATIVE_INT) < 0) TEST_ERROR
/* Set dataspace dimensions */
dim2d[0]=DIM_SIZE_1;
dim2d[1]=DIM_SIZE_2;
/* create dataspace */
if((sid = H5Screate_simple(2, dim2d, NULL)) < 0) TEST_ERROR
/* add a dataset to the top group */
if((did = H5Dcreate2(gid, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR
if(H5Dclose(did) < 0) TEST_ERROR
/* create a sub-group */
if((gid_sub = H5Gcreate2(fid_src, NAME_GROUP_SUB, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
/* add a dataset to the sub group */
if((did = H5Dcreate2(gid_sub, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR
if(H5Dclose(did) < 0) TEST_ERROR
/* create sub-sub-group */
if((gid_sub_sub = H5Gcreate2(gid_sub, NAME_GROUP_SUB_SUB2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
/* add a dataset to the sub sub group */
if((did = H5Dcreate2(gid_sub_sub, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR
/* close dataset */
if(H5Dclose(did) < 0) TEST_ERROR
/* close dataspace */
if(H5Sclose(sid) < 0) TEST_ERROR
if(H5Gclose(gid_sub_sub) < 0) TEST_ERROR
if(H5Gclose(gid_sub) < 0) TEST_ERROR
/* close the group */
if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) {
/* Create group to copy */
if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
if(H5Lcreate_soft(NAME_DATASET_SUB_SUB, fid_src, NAME_LINK_SOFT, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
if(H5Lcreate_soft("nowhere", fid_src, NAME_LINK_SOFT_DANGLE, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
/* Create group to compare with */
if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
if(H5Lcreate_hard(fid_src, NAME_DATASET_SUB_SUB, H5L_SAME_LOC, NAME_LINK_SOFT2, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
if(H5Lcreate_soft("nowhere", fid_src, NAME_LINK_SOFT_DANGLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
} /* end if */
if((flag & H5O_COPY_EXPAND_EXT_LINK_FLAG) > 0) {
char ext_filename[NAME_BUF_SIZE];
h5_fixname(FILENAME[2], src_fapl, ext_filename, sizeof ext_filename);
/* Create the external file and dataset */
if((fid_ext = H5Fcreate(ext_filename, H5F_ACC_TRUNC, fcpl_src, src_fapl)) < 0) TEST_ERROR
if((sid = H5Screate_simple(2, dim2d, NULL)) < 0) TEST_ERROR
if((did = H5Dcreate2(fid_ext, NAME_DATASET_SIMPLE, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR
if(H5Dclose(did) < 0) TEST_ERROR
if(H5Fclose(fid_ext) < 0) TEST_ERROR
/* Create group to copy */
if(!(flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG)) {
if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
} /* end if */
else
if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Lcreate_external(ext_filename, NAME_DATASET_SIMPLE, fid_src, NAME_LINK_EXTERN, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
if(H5Lcreate_external("no_file", "no_object", fid_src, NAME_LINK_EXTERN_DANGLE, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
if(H5Gclose(gid) < 0) TEST_ERROR
/* Create group to compare with */
if(!(flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG)) {
if((gid = H5Gcreate2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
} /* end if */
else
if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) TEST_ERROR
if((did = H5Dcreate2(fid_src, NAME_LINK_EXTERN2, H5T_NATIVE_INT, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR
if(H5Lcreate_external("no_file", "no_object", fid_src, NAME_LINK_EXTERN_DANGLE2, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
if(H5Dclose(did) < 0) TEST_ERROR
if(H5Gclose(gid) < 0) TEST_ERROR
/* Close dataspace */
if(H5Sclose(sid) < 0) TEST_ERROR
} /* end if */
if((flag & H5O_COPY_EXPAND_REFERENCE_FLAG) > 0) {
if((gid_ref = H5Gcreate2(fid_src, NAME_GROUP_REF, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
/* create an attribute of new object references */
if(attach_ref_attr(fid_src, gid_ref) < 0) TEST_ERROR
/* create an attribute of region references */
if(attach_reg_ref_attr(fid_src, gid_ref) < 0) TEST_ERROR
/* create a dataset of region references */
if(create_reg_ref_dataset(fid_src, gid_ref) < 0) TEST_ERROR
/* Close group holding reference objects */
if(H5Gclose(gid_ref) < 0) TEST_ERROR
} /* end if */
/* close the SRC file */
if(H5Fclose(fid_src) < 0) TEST_ERROR
/* open the source file with read-only */
/* (except when expanding soft links */
if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0) {
if((fid_src = H5Fopen(src_filename, H5F_ACC_RDWR, src_fapl)) < 0) TEST_ERROR
} /* end if */
else
if((fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, src_fapl)) < 0) TEST_ERROR
/* create destination file */
if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, fcpl_dst, dst_fapl)) < 0) TEST_ERROR
/* Create an uncopied object in destination file so that addresses in source and destination
files aren't the same */
if(H5Gclose(H5Gcreate2(fid_dst, NAME_GROUP_UNCOPIED, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
/* create property to pass copy options */
if((pid = H5Pcreate(H5P_OBJECT_COPY)) < 0) TEST_ERROR
/* set options for object copy */
if(H5Pset_copy_object(pid, flag) < 0) TEST_ERROR
/* Verify object copy flags */
if(H5Pget_copy_object(pid, &cpy_flags) < 0) TEST_ERROR
if(cpy_flags != flag) TEST_ERROR
/* copy the group from SRC to DST */
if(crt_intermediate_grp) {
/* Create link creation plist to pass in intermediate group creation */
if((lcpl_id = H5Pcreate(H5P_LINK_CREATE)) < 0) TEST_ERROR
if(H5Pset_create_intermediate_group(lcpl_id, TRUE) < 0) TEST_ERROR
if(H5Ocopy(fid_src, NAME_GROUP_TOP, fid_dst, "/new_g0/new_g00", pid, lcpl_id) < 0) TEST_ERROR
if(H5Pclose(lcpl_id) < 0) TEST_ERROR
/* open the group for copy */
if((gid = H5Gopen2(fid_src, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* open the destination group */
if((gid2 = H5Gopen2(fid_dst, "/new_g0/new_g00", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
} else if(((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0)
|| ((flag & H5O_COPY_EXPAND_EXT_LINK_FLAG) > 0)) {
if(H5Ocopy(fid_src, NAME_GROUP_LINK, fid_dst, NAME_GROUP_LINK, pid, H5P_DEFAULT) < 0) TEST_ERROR
if((flag & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0)
/* Unlink dataset to copy from original location */
/* (So group comparison works properly) */
if(H5Ldelete(fid_src, NAME_DATASET_SUB_SUB, H5P_DEFAULT) < 0) FAIL_STACK_ERROR
/* open the group for copy */
if((gid = H5Gopen2(fid_src, NAME_GROUP_LINK2, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* open the destination group */
if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_LINK, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
} else if(flag & (H5O_COPY_WITHOUT_ATTR_FLAG | H5O_COPY_PRESERVE_NULL_FLAG)) {
if(H5Ocopy(fid_src, NAME_GROUP_TOP, fid_dst, NAME_GROUP_TOP, pid, H5P_DEFAULT) < 0) TEST_ERROR
/* open the group for copy */
if((gid = H5Gopen2(fid_src, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* open the destination group */
if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
} else if(flag & H5O_COPY_SHALLOW_HIERARCHY_FLAG) {
if(H5Ocopy(fid_src, NAME_GROUP_TOP, fid_dst, NAME_GROUP_TOP, pid, H5P_DEFAULT) < 0) TEST_ERROR
/* open the group for copy */
if((gid = H5Gopen2(fid_src, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* open the destination group */
if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_TOP, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* Set the copy depth */
depth = 1;
} else if((flag & H5O_COPY_EXPAND_REFERENCE_FLAG) > 0) {
if(H5Ocopy(fid_src, NAME_GROUP_REF, fid_dst, NAME_GROUP_REF, pid, H5P_DEFAULT) < 0) TEST_ERROR
/* open the group for copy */
if((gid = H5Gopen2(fid_src, NAME_GROUP_REF, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* open the destination group */
if((gid2 = H5Gopen2(fid_dst, NAME_GROUP_REF, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
} else {
/* Unknown flag */
TEST_ERROR
} /* end else */
/* Check if the groups are equal */
if(compare_groups(gid, gid2, pid, depth, flag) != TRUE) TEST_ERROR
if(H5Gclose(gid2) < 0) TEST_ERROR
if(H5Gclose(gid) < 0) TEST_ERROR
/* close the SRC file */
if(H5Fclose(fid_src) < 0) TEST_ERROR
/* close the DST file */
if(H5Fclose(fid_dst) < 0) TEST_ERROR
/* close properties */
if(H5Pclose(pid) < 0) TEST_ERROR
PASSED();
return 0;
error:
H5E_BEGIN_TRY {
H5Pclose(lcpl_id);
H5Pclose(pid);
H5Sclose(sid);
H5Dclose(did);
H5Gclose(gid_ref);
H5Gclose(gid_sub);
H5Gclose(gid2);
H5Gclose(gid);
H5Fclose(fid_dst);
H5Fclose(fid_src);
H5Fclose(fid_ext);
} H5E_END_TRY;
return 1;
} /* end test_copy_option */
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Test H5Ocopy()
*
* Tests a number of cases: messages can be stored in the
* new or old format, messages can be shared in either,
* both, or neither of the source and destination files.
*
* Return: EXIT_SUCCESS/EXIT_FAILURE
*
* Programmer: Peter Cao
* Friday, September 30, 2005
*
*-------------------------------------------------------------------------
*/
int
main(void)
{
int nerrors = 0;
hid_t fapl, fapl2;
hid_t fcpl_shared, ocpl;
unsigned max_compact, min_dense;
int configuration; /* Configuration of tests. */
int ExpressMode;
/* Setup */
h5_reset();
fapl = h5_fileaccess();
ExpressMode = GetTestExpress();
if (ExpressMode > 1)
HDprintf("***Express test mode on. Some tests may be skipped\n");
/* Copy the file access property list */
if((fapl2 = H5Pcopy(fapl)) < 0) TEST_ERROR
/* Set the "use the latest version of the format" bounds for creating objects in the file */
if(H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) TEST_ERROR
/* Create an FCPL with sharing enabled */
if((fcpl_shared = H5Pcreate(H5P_FILE_CREATE)) < 0) TEST_ERROR
if(H5Pset_shared_mesg_nindexes(fcpl_shared, 1) < 0) TEST_ERROR
if(H5Pset_shared_mesg_index(fcpl_shared, 0, H5O_SHMESG_ALL_FLAG, 10) < 0) TEST_ERROR
/* Obtain the default attribute storage phase change values */
if((ocpl = H5Pcreate(H5P_OBJECT_CREATE)) < 0) TEST_ERROR
if(H5Pget_attr_phase_change(ocpl, &max_compact, &min_dense) < 0) TEST_ERROR
if(H5Pclose(ocpl) < 0) TEST_ERROR
/* Test in all configurations */
for(configuration = 0; configuration <= MAX_CONFIGURATION; configuration++) {
hid_t src_fapl;
hid_t dst_fapl;
hid_t fcpl_src;
hid_t fcpl_dst;
/* No need to test dense attributes with old format */
if(!(configuration & CONFIG_SRC_NEW_FORMAT) && (configuration & CONFIG_DENSE))
continue;
/* TODO Region references currently do not support copy from new format to old format
* (this may be fixed once H5Sencode/decode and H5CXis fixed) */
if((configuration & CONFIG_SRC_NEW_FORMAT) && !(configuration & CONFIG_DST_NEW_FORMAT))
continue;
/* Test with and without shared messages */
if(configuration & CONFIG_SHARE_SRC) {
HDputs("\nTesting with shared src messages:");
fcpl_src = fcpl_shared;
}
else {
HDputs("\nTesting without shared src messages:");
fcpl_src = H5P_DEFAULT;
}
if(configuration & CONFIG_SHARE_DST) {
HDputs("Testing with shared dst messages:");
fcpl_dst = fcpl_shared;
}
else {
HDputs("Testing without shared dst messages:");
fcpl_dst = H5P_DEFAULT;
}
/* Set the FAPL for the source file's type of format */
if(configuration & CONFIG_SRC_NEW_FORMAT) {
HDputs("Testing with latest format for source file:");
src_fapl = fapl2;
/* Test with and without dense attributes */
if(configuration & CONFIG_DENSE) {
HDputs("Testing with dense attributes:");
num_attributes_g = max_compact + 1;
}
else {
HDputs("Testing without dense attributes:");
num_attributes_g = MAX(min_dense, 2) - 2;
}
} /* end if */
else {
HDputs("Testing with oldest file format for source file:");
src_fapl = fapl;
num_attributes_g = 4;
} /* end else */
/* Set the FAPL for the destination file's type of format */
if(configuration & CONFIG_DST_NEW_FORMAT) {
HDputs("Testing with latest format for destination file:");
dst_fapl = fapl2;
} /* end if */
else {
HDputs("Testing with oldest file format for destination file:");
dst_fapl = fapl;
} /* end else */
/* The tests... */
nerrors += test_copy_option(fcpl_src, fcpl_dst, src_fapl, dst_fapl,
H5O_COPY_EXPAND_REFERENCE_FLAG,
FALSE, "H5Ocopy(): expand object reference");
} /* end for */
/* Reset file address checking info */
addr_reset();
/* Verify symbol table messages are cached */
nerrors += (h5_verify_cached_stabs(FILENAME, fapl) < 0 ? 1 : 0);
/* Results */
if(nerrors) {
HDprintf("***** %d OBJECT COPY TEST%s FAILED! *****\n",
nerrors, (1 == nerrors ? "" : "S"));
HDexit(EXIT_FAILURE);
} /* end if */
HDputs ("All object copying tests passed.");
/* close property list.
* NOTE: if this property list is not closed and the test is
* run with the split or multi driver, an interesting
* problem is exposed in the property list shutdown code.
*
* Namely, since the split/multi driver copies property
* lists for internal use, there's a (high) chance that
* leaving the FAPL open and having the library's shutdown
* code close it will cause the underlying property lists
* to be cleaned up first, causing the actual property list
* close operation to fail (since it won't be able to close
* the already closed underlying property list).
*
* The could be addressed by converting the split/multi to
* use non-public API routines, or putting some way into the
* public H5I routines to indicate ordering at shutdown.
*
* For now, we just make certain to close the property list.
* (QAK - 2016/04/06)
*
*/
H5Pclose(fapl2);
h5_cleanup(FILENAME, fapl);
HDexit(EXIT_SUCCESS);
error:
HDexit(EXIT_FAILURE);
} /* main */