/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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 files COPYING and Copyright.html.  COPYING can be found at the root   *
 * of the source code distribution tree; Copyright.html can be found at the  *
 * root level of an installed copy of the electronic HDF5 document set and   *
 * is linked from the top-level documents page.  It can also be found at     *
 * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
 * access to either file, you may request a copy from help@hdfgroup.org.     *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/***********************************************************
*
* Test program:	 tattr
*
* Test the attribute functionality
*
*************************************************************/

#include "testhdf5.h"
#include "h5test.h"
#include "hdf5.h"

/*
 * This file needs to access private information from the H5O package.
 * This file also needs to access the object header testing code.
 */
#define H5O_PACKAGE
#define H5O_TESTING
#include "H5Opkg.h"		/* Object headers 			*/

/*
 * This file needs to access private information from the H5A package.
 * This file also needs to access the attribute testing code.
 */
#define H5A_PACKAGE
#define H5A_TESTING
#include "H5Apkg.h"		/* Attributes	 			*/

/*
 * This file needs to access private information from the H5F package.
 * This file also needs to access the file testing code.
 */
#define H5F_PACKAGE
#define H5F_TESTING
#include "H5Fpkg.h"		/* File access	 			*/

#define FILENAME   "tattr.h5"
#define NAME_BUF_SIZE   1024
#define ATTR_NAME_LEN   16
#define ATTR_MAX_DIMS   7
#define ATTR_TMP_NAME   "a really long temp_name"
#define CORDER_ITER_STOP            3

/* 3-D dataset with fixed dimensions */
#define SPACE1_NAME  "Space1"
#define SPACE1_RANK	3
#define SPACE1_DIM1	3
#define SPACE1_DIM2	15
#define SPACE1_DIM3	13

/* Dataset Information */
#define DSET1_NAME "Dataset1"
#define DSET2_NAME "Dataset2"
#define DSET3_NAME "Dataset3"
#define NUM_DSETS       3

/* Group Information */
#define GROUP1_NAME "/Group1"

/* Named Datatype Information */
#define TYPE1_NAME "/Type"

/* Attribute Rank & Dimensions */
#define ATTR1_NAME  "Attr1"
#define ATTR1_RANK	1
#define ATTR1_DIM1	3
int attr_data1[ATTR1_DIM1]={512,-234,98123}; /* Test data for 1st attribute */

/* rank & dimensions for another attribute */
#define ATTR1A_NAME  "Attr1_a"
int attr_data1a[ATTR1_DIM1]={256,11945,-22107};

#define ATTR2_NAME  "Attr2"
#define ATTR2_RANK	2
#define ATTR2_DIM1	2
#define ATTR2_DIM2	2
int attr_data2[ATTR2_DIM1][ATTR2_DIM2]={{7614,-416},{197814,-3}}; /* Test data for 2nd attribute */

#define ATTR3_NAME  "Attr3"
#define ATTR3_RANK	3
#define ATTR3_DIM1	2
#define ATTR3_DIM2	2
#define ATTR3_DIM3	2
double attr_data3[ATTR3_DIM1][ATTR3_DIM2][ATTR3_DIM3]={{{2.3,-26.1},{0.123,-10.0}},{{973.23,-0.91827},{2.0,23.0}}}; /* Test data for 3rd attribute */

#define ATTR4_NAME  "Attr4"
#define ATTR4_RANK	2
#define ATTR4_DIM1	2
#define ATTR4_DIM2	2
#define ATTR4_FIELDNAME1	"i"
#define ATTR4_FIELDNAME2	"d"
#define ATTR4_FIELDNAME3	"c"
size_t attr4_field1_off=0;
size_t attr4_field2_off=0;
size_t attr4_field3_off=0;
struct attr4_struct {
    int i;
    double d;
    char c;
 } attr_data4[ATTR4_DIM1][ATTR4_DIM2]={{{3,-26.1,'d'},{-100000, 0.123,'3'}},
    {{-23,981724.2,'Q'},{0,2.0,'\n'}}}; /* Test data for 4th attribute */

#define ATTR5_NAME  "Attr5"
#define ATTR5_RANK	0
float attr_data5=(float)-5.123;        /* Test data for 5th attribute */

#define ATTR6_RANK	3
#define ATTR6_DIM1	100
#define ATTR6_DIM2	100
#define ATTR6_DIM3	100

/* Attribute iteration struct */
typedef struct {
    H5_iter_order_t order;      /* Direction of iteration */
    unsigned ncalled;           /* # of times callback is entered */
    unsigned nskipped;          /* # of attributes skipped */
    int stop;                   /* # of iterations to stop after */
    int64_t curr;               /* Current creation order value */
    size_t max_visit;           /* Size of "visited attribute" flag array */
    hbool_t *visited;           /* Pointer to array of "visited attribute" flags */
} attr_iter_info_t;

static herr_t attr_op1(hid_t loc_id, const char *name, void *op_data);



/****************************************************************
**
**  test_attr_basic_write(): Test basic H5A (attribute) code.
**      Tests integer attributes on both datasets and groups
**
****************************************************************/
static void
test_attr_basic_write(hid_t fapl)
{
    hid_t		fid1;		/* HDF5 File IDs		*/
    hid_t		dataset;	/* Dataset ID			*/
    hid_t		group;	    /* Group ID			    */
    hid_t		sid1,sid2;	/* Dataspace ID			*/
    hid_t		attr, attr2;	    /* Attribute ID		*/
    hsize_t             attr_size;  /* storage size for attribute       */
    ssize_t             attr_name_size; /* size of attribute name       */
    char                *attr_name=NULL;    /* name of attribute        */
    hsize_t		dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3};
    hsize_t		dims2[] = {ATTR1_DIM1};
    hsize_t		dims3[] = {ATTR2_DIM1,ATTR2_DIM2};
    int       read_data1[ATTR1_DIM1]={0}; /* Buffer for reading 1st attribute */
    int         i;
    herr_t		ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Basic Scalar Attribute Writing Functions\n"));

    /* Create file */
    fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
    CHECK(fid1, FAIL, "H5Fcreate");

    /* Create dataspace for dataset */
    sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL);
    CHECK(sid1, FAIL, "H5Screate_simple");

    /* Create a dataset */
    dataset=H5Dcreate(fid1,DSET1_NAME,H5T_NATIVE_UCHAR,sid1,H5P_DEFAULT);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Create dataspace for attribute */
    sid2 = H5Screate_simple(ATTR1_RANK, dims2, NULL);
    CHECK(sid2, FAIL, "H5Screate_simple");


    /* Try to create an attribute on the file (should create an attribute on root group) */
    attr = H5Acreate(fid1, ATTR1_NAME, H5T_NATIVE_INT, sid2, H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Close attribute */
    ret = H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Open the root group */
    group = H5Gopen(fid1, "/");
    CHECK(group, FAIL, "H5Gopen");

    /* Open attribute again */
    attr = H5Aopen_name(group, ATTR1_NAME);
    CHECK(attr, FAIL, "H5Aopen_name");

    /* Close attribute */
    ret = H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close root group */
    ret = H5Gclose(group);
    CHECK(ret, FAIL, "H5Gclose");


    /* Create an attribute for the dataset */
    attr=H5Acreate(dataset,ATTR1_NAME,H5T_NATIVE_INT,sid2,H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Try to create the same attribute again (should fail) */
    ret=H5Acreate(dataset,ATTR1_NAME,H5T_NATIVE_INT,sid2,H5P_DEFAULT);
    VERIFY(ret, FAIL, "H5Acreate");

    /* Write attribute information */
    ret=H5Awrite(attr,H5T_NATIVE_INT,attr_data1);
    CHECK(ret, FAIL, "H5Awrite");

    /* Create an another attribute for the dataset */
    attr2=H5Acreate(dataset,ATTR1A_NAME,H5T_NATIVE_INT,sid2,H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Write attribute information */
    ret=H5Awrite(attr2,H5T_NATIVE_INT,attr_data1a);
    CHECK(ret, FAIL, "H5Awrite");

    /* Check storage size for attribute */
    attr_size=H5Aget_storage_size(attr);
    VERIFY(attr_size, (ATTR1_DIM1*sizeof(int)), "H5A_get_storage_size");

    /* Read attribute information immediately, without closing attribute */
    ret=H5Aread(attr,H5T_NATIVE_INT,read_data1);
    CHECK(ret, FAIL, "H5Aread");

    /* Verify values read in */
    for(i=0; i<ATTR1_DIM1; i++)
        if(attr_data1[i]!=read_data1[i])
            TestErrPrintf("%d: attribute data different: attr_data1[%d]=%d, read_data1[%d]=%d\n",__LINE__,i,attr_data1[i],i,read_data1[i]);

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close attribute */
    ret=H5Aclose(attr2);
    CHECK(ret, FAIL, "H5Aclose");

    /* change attribute name */
    ret=H5Arename(dataset, ATTR1_NAME, ATTR_TMP_NAME);
    CHECK(ret, FAIL, "H5Arename");

    /* Open attribute again */
    attr=H5Aopen_name(dataset, ATTR_TMP_NAME);
    CHECK(attr, FAIL, "H5Aopen_name");

    /* Verify new attribute name */
    attr_name_size = H5Aget_name(attr, (size_t)0, NULL);
    CHECK(attr_name_size, FAIL, "H5Aget_name");

    if(attr_name_size>0)
        attr_name = (char*)HDcalloc((size_t)(attr_name_size+1), sizeof(char));

    ret=(herr_t)H5Aget_name(attr, (size_t)(attr_name_size+1), attr_name);
    CHECK(ret, FAIL, "H5Aget_name");
    ret=HDstrcmp(attr_name, ATTR_TMP_NAME);
    VERIFY(ret, 0, "HDstrcmp");

    if(attr_name)
        HDfree(attr_name);

    /* Read attribute information immediately, without closing attribute */
    ret=H5Aread(attr,H5T_NATIVE_INT,read_data1);
    CHECK(ret, FAIL, "H5Aread");

    /* Verify values read in */
    for(i=0; i<ATTR1_DIM1; i++)
        if(attr_data1[i]!=read_data1[i])
            TestErrPrintf("%d: attribute data different: attr_data1[%d]=%d, read_data1[%d]=%d\n",__LINE__,i,attr_data1[i],i,read_data1[i]);

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Open the second attribute again */
    attr2=H5Aopen_name(dataset, ATTR1A_NAME);
    CHECK(attr, FAIL, "H5Aopen_name");

    /* Verify new attribute name */
    attr_name_size = H5Aget_name(attr2, (size_t)0, NULL);
    CHECK(attr_name_size, FAIL, "H5Aget_name");

    if(attr_name_size>0)
        attr_name = (char*)HDcalloc((size_t)(attr_name_size+1), sizeof(char));

    ret=(herr_t)H5Aget_name(attr2, (size_t)(attr_name_size+1), attr_name);
    CHECK(ret, FAIL, "H5Aget_name");
    ret=HDstrcmp(attr_name, ATTR1A_NAME);
    VERIFY(ret, 0, "HDstrcmp");

    if(attr_name)
        HDfree(attr_name);

    /* Read attribute information immediately, without closing attribute */
    ret=H5Aread(attr2,H5T_NATIVE_INT,read_data1);
    CHECK(ret, FAIL, "H5Aread");

    /* Verify values read in */
    for(i=0; i<ATTR1_DIM1; i++)
        if(attr_data1a[i]!=read_data1[i])
            TestErrPrintf("%d: attribute data different: attr_data1a[%d]=%d, read_data1[%d]=%d\n",__LINE__,i,attr_data1a[i],i,read_data1[i]);

    /* Close attribute */
    ret=H5Aclose(attr2);
    CHECK(ret, FAIL, "H5Aclose");

    ret = H5Sclose(sid1);
    CHECK(ret, FAIL, "H5Sclose");
    ret = H5Sclose(sid2);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Create group */
    group = H5Gcreate(fid1, GROUP1_NAME, (size_t)0);
    CHECK(group, FAIL, "H5Gcreate");

    /* Create dataspace for attribute */
    sid2 = H5Screate_simple(ATTR2_RANK, dims3, NULL);
    CHECK(sid2, FAIL, "H5Screate_simple");

    /* Create an attribute for the group */
    attr=H5Acreate(group,ATTR2_NAME,H5T_NATIVE_INT,sid2,H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Check storage size for attribute */
    attr_size=H5Aget_storage_size(attr);
    VERIFY(attr_size, (ATTR2_DIM1*ATTR2_DIM2*sizeof(int)), "H5Aget_storage_size");

    /* Try to create the same attribute again (should fail) */
    ret=H5Acreate(group,ATTR2_NAME,H5T_NATIVE_INT,sid2,H5P_DEFAULT);
    VERIFY(ret, FAIL, "H5Acreate");

    /* Write attribute information */
    ret=H5Awrite(attr,H5T_NATIVE_INT,attr_data2);
    CHECK(ret, FAIL, "H5Awrite");

    /* Check storage size for attribute */
    attr_size=H5Aget_storage_size(attr);
    VERIFY(attr_size, (ATTR2_DIM1*ATTR2_DIM2*sizeof(int)), "H5A_get_storage_size");

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close Attribute dataspace */
    ret = H5Sclose(sid2);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close Group */
    ret = H5Gclose(group);
    CHECK(ret, FAIL, "H5Gclose");

    /* Close file */
    ret = H5Fclose(fid1);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_basic_write() */


/****************************************************************
**
**  test_attr_basic_read(): Test basic H5A (attribute) code.
**
****************************************************************/
static void
test_attr_basic_read(hid_t fapl)
{
    hid_t		fid1;		/* HDF5 File IDs		*/
    hid_t		dataset;	/* Dataset ID			*/
    hid_t		group;	    /* Group ID			    */
    hid_t		attr;	    /* Attribute ID			*/
    int       read_data1[ATTR1_DIM1]={0}; /* Buffer for reading 1st attribute */
    int       read_data2[ATTR2_DIM1][ATTR2_DIM2]={{0}}; /* Buffer for reading 2nd attribute */
    int         i,j;
    herr_t		ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Basic Attribute Functions\n"));

    /* Create file */
    fid1 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid1, FAIL, "H5Fopen");

    /* Open the dataset */
    dataset=H5Dopen(fid1,DSET1_NAME);
    CHECK(dataset, FAIL, "H5Dopen");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(dataset);
    VERIFY(ret, 2, "H5Aget_num_attrs");

    /* Open first attribute for the dataset */
    attr=H5Aopen_name(dataset, ATTR_TMP_NAME);
    CHECK(attr, FAIL, "H5Aopen_name");

    /* Read attribute information */
    ret=H5Aread(attr,H5T_NATIVE_INT,read_data1);
    CHECK(ret, FAIL, "H5Aread");

    /* Verify values read in */
    for(i=0; i<ATTR1_DIM1; i++)
        if(attr_data1[i]!=read_data1[i])
            TestErrPrintf("%d: attribute data different: attr_data1[%d]=%d, read_data1[%d]=%d\n",__LINE__,i,attr_data1[i],i,read_data1[i]);

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Open the group */
    group = H5Gopen(fid1,GROUP1_NAME);
    CHECK(group, FAIL, "H5Gopen");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(group);
    VERIFY(ret, 1, "H5Aget_num_attrs");

    /* Open the attribute for the group */
    attr=H5Aopen_name(group,ATTR2_NAME);
    CHECK(attr, FAIL, "H5Aopen_name");

    /* Read attribute information */
    ret=H5Aread(attr,H5T_NATIVE_INT,read_data2);
    CHECK(ret, FAIL, "H5Aread");

    /* Verify values read in */
    for(i=0; i<ATTR2_DIM1; i++)
        for(j=0; j<ATTR2_DIM2; j++)
            if(attr_data2[i][j]!=read_data2[i][j])
                TestErrPrintf("%d: attribute data different: attr_data2[%d][%d]=%d, read_data2[%d][%d]=%d\n",__LINE__, i,j,attr_data2[i][j],i,j,read_data1[i]);

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close group */
    ret = H5Gclose(group);
    CHECK(ret, FAIL, "H5Gclose");

    /* Close file */
    ret = H5Fclose(fid1);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_basic_read() */


/****************************************************************
**
**  test_attr_flush(): Test H5A (attribute) code for performing
**                      I/O when H5Fflush is used.
**
****************************************************************/
static void
test_attr_flush(hid_t fapl)
{
    hid_t fil,          /* File ID */
        att,            /* Attribute ID */
        spc,            /* Dataspace ID */
        set;            /* Dataset ID */
    double wdata=3.14159;       /* Data to write */
    double rdata;       /* Data read in */
    herr_t ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Attribute Flushing\n"));

    fil = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
    CHECK(fil, FAIL, "H5Fcreate");

    spc = H5Screate(H5S_SCALAR);
    CHECK(spc, FAIL, "H5Screate");

    set = H5Dcreate(fil, DSET1_NAME, H5T_NATIVE_DOUBLE, spc, H5P_DEFAULT);
    CHECK(set, FAIL, "H5Dcreate");

    att = H5Acreate(set, ATTR1_NAME, H5T_NATIVE_DOUBLE, spc, H5P_DEFAULT);
    CHECK(att, FAIL, "H5Acreate");

    ret=H5Aread(att, H5T_NATIVE_DOUBLE, &rdata);
    CHECK(ret, FAIL, "H5Awrite");

    if(!DBL_ABS_EQUAL(rdata,0.0))
        TestErrPrintf("attribute value wrong: rdata=%f, should be %f\n",rdata,0.0);

    ret=H5Fflush(fil, H5F_SCOPE_GLOBAL);
    CHECK(ret, FAIL, "H5Fflush");

    ret=H5Aread(att, H5T_NATIVE_DOUBLE, &rdata);
    CHECK(ret, FAIL, "H5Awrite");

    if(!DBL_ABS_EQUAL(rdata,0.0))
        TestErrPrintf("attribute value wrong: rdata=%f, should be %f\n",rdata,0.0);

    ret=H5Awrite(att, H5T_NATIVE_DOUBLE, &wdata);
    CHECK(ret, FAIL, "H5Awrite");

    ret=H5Aread(att, H5T_NATIVE_DOUBLE, &rdata);
    CHECK(ret, FAIL, "H5Awrite");

    if(!DBL_ABS_EQUAL(rdata,wdata))
        TestErrPrintf("attribute value wrong: rdata=%f, should be %f\n",rdata,wdata);

    ret=H5Sclose(spc);
    CHECK(ret, FAIL, "H5Sclose");
    ret=H5Aclose(att);
    CHECK(ret, FAIL, "H5Aclose");
    ret=H5Dclose(set);
    CHECK(ret, FAIL, "H5Dclose");
    ret=H5Fclose(fil);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_flush() */


/****************************************************************
**
**  test_attr_plist(): Test Attribute Creation Property Lists
**
****************************************************************/
static void
test_attr_plist(hid_t fapl)
{
    hid_t		fid1;           /* HDF5 File IDs		*/
    hid_t		dataset;        /* Dataset ID			*/
    hid_t		sid1,sid2;      /* Dataspace ID			*/
    hid_t		attr;	        /* Attribute ID		*/
    hid_t               plist;          /* Property list ID             */
    hsize_t		dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3};
    hsize_t		dims2[] = {ATTR1_DIM1};
    H5T_cset_t          cset;           /* Character set for attributes */
    herr_t		ret;            /* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Attribute Property Lists\n"));

    /* Create file */
    fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
    CHECK(fid1, FAIL, "H5Fcreate");

    /* Create dataspace for dataset */
    sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL);
    CHECK(sid1, FAIL, "H5Screate_simple");

    /* Create a dataset */
    dataset=H5Dcreate(fid1,DSET1_NAME,H5T_NATIVE_UCHAR,sid1,H5P_DEFAULT);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Create dataspace for attribute */
    sid2 = H5Screate_simple(ATTR1_RANK, dims2, NULL);
    CHECK(sid2, FAIL, "H5Screate_simple");

    /* Create default property list for attribute */
    plist = H5Pcreate(H5P_ATTRIBUTE_CREATE);
    CHECK(plist, FAIL, "H5Pcreate");

    /* Get the character encoding and ensure that it is the default (ASCII) */
    ret = H5Pget_char_encoding(plist, &cset);
    CHECK(ret, FAIL, "H5Pget_char_encoding");
    VERIFY(cset, H5T_CSET_ASCII, "H5Pget_char_encoding");

    /* Create an attribute for the dataset using the property list */
    attr=H5Acreate(dataset,ATTR1_NAME,H5T_NATIVE_INT,sid2,plist);
    CHECK(attr, FAIL, "H5Acreate");

    /* Close the property list, and get the attribute's property list */
    ret = H5Pclose(plist);
    CHECK(ret, FAIL, "H5Pclose");
    plist = H5Aget_create_plist(attr);
    CHECK(plist, FAIL, "H5Aget_create_plist");

    /* Get the character encoding and ensure that it is the default (ASCII) */
    ret = H5Pget_char_encoding(plist, &cset);
    CHECK(ret, FAIL, "H5Pget_char_encoding");
    VERIFY(cset, H5T_CSET_ASCII, "H5Pget_char_encoding");

    /* Close the property list and attribute */
    ret = H5Pclose(plist);
    CHECK(ret, FAIL, "H5Pclose");
    ret = H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Create a new property list and modify it to use a different encoding */
    plist = H5Pcreate(H5P_ATTRIBUTE_CREATE);
    CHECK(plist, FAIL, "H5Pcreate");
    ret=H5Pset_char_encoding(plist, H5T_CSET_UTF8);
    CHECK(ret, FAIL, "H5Pset_char_encoding");

    /* Get the character encoding and ensure that it has been changed */
    ret = H5Pget_char_encoding(plist, &cset);
    CHECK(ret, FAIL, "H5Pget_char_encoding");
    VERIFY(cset, H5T_CSET_UTF8, "H5Pget_char_encoding");

    /* Create an attribute for the dataset using the modified property list */
    attr=H5Acreate(dataset,ATTR2_NAME,H5T_NATIVE_INT,sid2,plist);
    CHECK(attr, FAIL, "H5Acreate");

    /* Close the property list and attribute */
    ret = H5Pclose(plist);
    CHECK(ret, FAIL, "H5Pclose");
    ret = H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Re-open the second attribute and ensure that its character encoding is correct */
    attr = H5Aopen_name(dataset, ATTR2_NAME);
    CHECK(attr, FAIL, "H5Aopen_name");
    plist = H5Aget_create_plist(attr);
    CHECK(plist, FAIL, "H5Aget_create_plist");
    ret = H5Pget_char_encoding(plist, &cset);
    CHECK(ret, FAIL, "H5Pget_char_encoding");
    VERIFY(cset, H5T_CSET_UTF8, "H5Pget_char_encoding");

    /* Close everything */
    ret=H5Sclose(sid1);
    CHECK(ret, FAIL, "H5Sclose");
    ret=H5Sclose(sid2);
    CHECK(ret, FAIL, "H5Sclose");
    ret = H5Pclose(plist);
    CHECK(ret, FAIL, "H5Pclose");
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");
    ret=H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");
    ret=H5Fclose(fid1);
    CHECK(ret, FAIL, "H5Fclose");
}  /* test_attr_plist() */


/****************************************************************
**
**  test_attr_compound_write(): Test H5A (attribute) code.
**      Tests compound datatype attributes
**
****************************************************************/
static void
test_attr_compound_write(hid_t fapl)
{
    hid_t		fid1;		/* HDF5 File IDs		*/
    hid_t		dataset;	/* Dataset ID			*/
    hid_t       tid1;       /* Attribute datatype ID */
    hid_t		sid1,sid2;	/* Dataspace ID			*/
    hid_t		attr;	    /* Attribute ID			*/
    hsize_t		dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3};
    hsize_t		dims2[] = {ATTR4_DIM1,ATTR4_DIM2};
    herr_t		ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Multiple Attribute Functions\n"));

    /* Create file */
    fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
    CHECK(fid1, FAIL, "H5Fcreate");

    /* Create dataspace for dataset */
    sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL);
    CHECK(sid1, FAIL, "H5Screate_simple");

    /* Create a dataset */
    dataset=H5Dcreate(fid1,DSET1_NAME,H5T_NATIVE_UCHAR,sid1,H5P_DEFAULT);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Close dataset's dataspace */
    ret = H5Sclose(sid1);
    CHECK(ret, FAIL, "H5Sclose");

    /* Create the attribute datatype.  */
    tid1 = H5Tcreate (H5T_COMPOUND, sizeof(struct attr4_struct));
    CHECK(tid1, FAIL, "H5Tcreate");
    attr4_field1_off=HOFFSET(struct attr4_struct, i);
    ret = H5Tinsert(tid1, ATTR4_FIELDNAME1, attr4_field1_off, H5T_NATIVE_INT);
    CHECK(ret, FAIL, "H5Tinsert");
    attr4_field2_off=HOFFSET(struct attr4_struct, d);
    ret = H5Tinsert(tid1, ATTR4_FIELDNAME2, attr4_field2_off, H5T_NATIVE_DOUBLE);
    CHECK(ret, FAIL, "H5Tinsert");
    attr4_field3_off=HOFFSET(struct attr4_struct, c);
    ret = H5Tinsert(tid1, ATTR4_FIELDNAME3, attr4_field3_off,
		    H5T_NATIVE_SCHAR);
    CHECK(ret, FAIL, "H5Tinsert");

    /* Create dataspace for 1st attribute */
    sid2 = H5Screate_simple(ATTR4_RANK, dims2, NULL);
    CHECK(sid2, FAIL, "H5Screate_simple");

    /* Create complex attribute for the dataset */
    attr=H5Acreate(dataset,ATTR4_NAME,tid1,sid2,H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Try to create the same attribute again (should fail) */
    ret=H5Acreate(dataset,ATTR4_NAME,tid1,sid2,H5P_DEFAULT);
    VERIFY(ret, FAIL, "H5Acreate");

    /* Write complex attribute data */
    ret=H5Awrite(attr,tid1,attr_data4);
    CHECK(ret, FAIL, "H5Awrite");

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close attribute's dataspace */
    ret = H5Sclose(sid2);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close attribute's datatype */
    ret = H5Tclose(tid1);
    CHECK(ret, FAIL, "H5Tclose");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid1);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_compound_write() */


/****************************************************************
**
**  test_attr_compound_read(): Test basic H5A (attribute) code.
**
****************************************************************/
static void
test_attr_compound_read(hid_t fapl)
{
    hid_t   fid1;		/* HDF5 File IDs		*/
    hid_t   dataset;	/* Dataset ID			*/
    hid_t   space;      /* Attribute dataspace  */
    hid_t   type;       /* Attribute datatype   */
    hid_t   attr;	    /* Attribute ID			*/
    char    attr_name[ATTR_NAME_LEN]; /* Buffer for attribute names */
    int     rank;       /* Attribute rank */
    hsize_t dims[ATTR_MAX_DIMS];    /* Attribute dimensions */
    H5T_class_t t_class;  /* Attribute datatype class */
    H5T_order_t order;  /* Attribute datatype order */
    size_t      size;   /* Attribute datatype size as stored in file */
    int     fields;     /* # of Attribute datatype fields */
    char *fieldname;    /* Name of a field */
    size_t      offset; /* Attribute datatype field offset */
    hid_t   field;      /* Attribute field datatype */
    struct attr4_struct read_data4[ATTR4_DIM1][ATTR4_DIM2]; /* Buffer for reading 4th attribute */
    int     i,j;
    size_t  name_len;   /* Length of attribute name */
    herr_t  ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Basic Attribute Functions\n"));

    /* Open file */
    fid1 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid1, FAIL, "H5Fopen");

    /* Open the dataset */
    dataset=H5Dopen(fid1,DSET1_NAME);
    CHECK(dataset, FAIL, "H5Dopen");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(dataset);
    VERIFY(ret, 1, "H5Aget_num_attrs");

    /* Open 1st attribute for the dataset */
    attr=H5Aopen_idx(dataset,0);
    CHECK(attr, FAIL, "H5Aopen_idx");

    /* Verify Dataspace */
    space=H5Aget_space(attr);
    CHECK(space, FAIL, "H5Aget_space");
    rank=H5Sget_simple_extent_ndims(space);
    VERIFY(rank, ATTR4_RANK, "H5Sget_simple_extent_ndims");
    ret=H5Sget_simple_extent_dims(space,dims, NULL);
    CHECK(ret, FAIL, "H5Sget_simple_extent_dims");
    if(dims[0]!=ATTR4_DIM1)
        TestErrPrintf("attribute dimensions different: dims[0]=%d, should be %d\n",(int)dims[0],ATTR4_DIM1);
    if(dims[1]!=ATTR4_DIM2)
        TestErrPrintf("attribute dimensions different: dims[1]=%d, should be %d\n",(int)dims[1],ATTR4_DIM2);
    H5Sclose(space);

    /* Verify Datatype */
    type=H5Aget_type(attr);
    CHECK(type, FAIL, "H5Aget_type");
    t_class=H5Tget_class(type);
    VERIFY(t_class, H5T_COMPOUND, "H5Tget_class");
    fields=H5Tget_nmembers(type);
    VERIFY(fields, 3, "H5Tget_nmembers");
    for(i=0; i<fields; i++) {
        fieldname=H5Tget_member_name(type,(unsigned)i);
        if(!(HDstrcmp(fieldname,ATTR4_FIELDNAME1) ||
                HDstrcmp(fieldname,ATTR4_FIELDNAME2) ||
                HDstrcmp(fieldname,ATTR4_FIELDNAME3)))
            TestErrPrintf("invalid field name for field #%d: %s\n",i,fieldname);
        free(fieldname);
      } /* end for */
    offset=H5Tget_member_offset(type,0);
    VERIFY(offset, attr4_field1_off, "H5Tget_member_offset");
    offset=H5Tget_member_offset(type,1);
    VERIFY(offset, attr4_field2_off, "H5Tget_member_offset");
    offset=H5Tget_member_offset(type,2);
    VERIFY(offset, attr4_field3_off, "H5Tget_member_offset");

    /* Verify each field's type, class & size */
    field=H5Tget_member_type(type,0);
    CHECK(field, FAIL, "H5Tget_member_type");
    t_class=H5Tget_class(field);
    VERIFY(t_class, H5T_INTEGER, "H5Tget_class");
    order=H5Tget_order(field);
    VERIFY(order, H5Tget_order(H5T_NATIVE_INT), "H5Tget_order");
    size=H5Tget_size(field);
    VERIFY(size, H5Tget_size(H5T_NATIVE_INT), "H5Tget_size");
    H5Tclose(field);
    field=H5Tget_member_type(type,1);
    CHECK(field, FAIL, "H5Tget_member_type");
    t_class=H5Tget_class(field);
    VERIFY(t_class, H5T_FLOAT, "H5Tget_class");
    order=H5Tget_order(field);
    VERIFY(order, H5Tget_order(H5T_NATIVE_DOUBLE), "H5Tget_order");
    size=H5Tget_size(field);
    VERIFY(size, H5Tget_size(H5T_NATIVE_DOUBLE), "H5Tget_size");
    H5Tclose(field);
    field=H5Tget_member_type(type,2);
    CHECK(field, FAIL, "H5Tget_member_type");
    t_class=H5Tget_class(field);
    VERIFY(t_class, H5T_INTEGER, "H5Tget_class");
    order=H5Tget_order(field);
    VERIFY(order, H5Tget_order(H5T_NATIVE_SCHAR), "H5Tget_order");
    size=H5Tget_size(field);
    VERIFY(size, H5Tget_size(H5T_NATIVE_SCHAR), "H5Tget_size");
    H5Tclose(field);

    /* Read attribute information */
    ret=H5Aread(attr,type,read_data4);
    CHECK(ret, FAIL, "H5Aread");

    /* Verify values read in */
    for(i=0; i<ATTR4_DIM1; i++)
        for(j=0; j<ATTR4_DIM2; j++)
            if(HDmemcmp(&attr_data4[i][j],&read_data4[i][j],sizeof(struct attr4_struct))) {
                printf("%d: attribute data different: attr_data4[%d][%d].i=%d, read_data4[%d][%d].i=%d\n",__LINE__,i,j,attr_data4[i][j].i,i,j,read_data4[i][j].i);
                printf("%d: attribute data different: attr_data4[%d][%d].d=%f, read_data4[%d][%d].d=%f\n",__LINE__,i,j,attr_data4[i][j].d,i,j,read_data4[i][j].d);
                TestErrPrintf("%d: attribute data different: attr_data4[%d][%d].c=%c, read_data4[%d][%d].c=%c\n",__LINE__,i,j,attr_data4[i][j].c,i,j,read_data4[i][j].c);
             } /* end if */

    /* Verify Name */
    name_len=H5Aget_name(attr, (size_t)ATTR_NAME_LEN, attr_name);
    VERIFY(name_len, HDstrlen(ATTR4_NAME), "H5Aget_name");
    if(HDstrcmp(attr_name,ATTR4_NAME))
        TestErrPrintf("attribute name different: attr_name=%s, should be %s\n",attr_name,ATTR4_NAME);

    /* Close attribute datatype */
    ret=H5Tclose(type);
    CHECK(ret, FAIL, "H5Tclose");

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid1);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_compound_read() */


/****************************************************************
**
**  test_attr_scalar_write(): Test scalar H5A (attribute) writing code.
**
****************************************************************/
static void
test_attr_scalar_write(hid_t fapl)
{
    hid_t		fid1;		/* HDF5 File IDs		*/
    hid_t		dataset;	/* Dataset ID			*/
    hid_t		sid1,sid2;	/* Dataspace ID			*/
    hid_t		attr;	    /* Attribute ID			*/
    hsize_t		dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3};
    herr_t		ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Basic Attribute Functions\n"));

    /* Create file */
    fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
    CHECK(fid1, FAIL, "H5Fcreate");

    /* Create dataspace for dataset */
    sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL);
    CHECK(sid1, FAIL, "H5Screate_simple");

    /* Create a dataset */
    dataset=H5Dcreate(fid1,DSET1_NAME,H5T_NATIVE_UCHAR,sid1,H5P_DEFAULT);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Create dataspace for attribute */
    sid2 = H5Screate_simple(ATTR5_RANK, NULL, NULL);
    CHECK(sid2, FAIL, "H5Screate_simple");

    /* Create an attribute for the dataset */
    attr=H5Acreate(dataset,ATTR5_NAME,H5T_NATIVE_FLOAT,sid2,H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Try to create the same attribute again (should fail) */
    ret=H5Acreate(dataset,ATTR5_NAME,H5T_NATIVE_FLOAT,sid2,H5P_DEFAULT);
    VERIFY(ret, FAIL, "H5Acreate");

    /* Write attribute information */
    ret=H5Awrite(attr,H5T_NATIVE_FLOAT,&attr_data5);
    CHECK(ret, FAIL, "H5Awrite");

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    ret = H5Sclose(sid1);
    CHECK(ret, FAIL, "H5Sclose");
    ret = H5Sclose(sid2);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid1);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_scalar_write() */


/****************************************************************
**
**  test_attr_scalar_read(): Test scalar H5A (attribute) reading code.
**
****************************************************************/
static void
test_attr_scalar_read(hid_t fapl)
{
    hid_t		fid1;		/* HDF5 File IDs		*/
    hid_t		dataset;	/* Dataset ID			*/
    hid_t		sid;	        /* Dataspace ID			*/
    hid_t		attr;	        /* Attribute ID			*/
    H5S_class_t         stype;          /* Dataspace class              */
    float       rdata=0.0;  /* Buffer for reading 1st attribute */
    herr_t		ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Basic Scalar Attribute Reading Functions\n"));

    /* Create file */
    fid1 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid1, FAIL, "H5Fopen");

    /* Open the dataset */
    dataset=H5Dopen(fid1,DSET1_NAME);
    CHECK(dataset, FAIL, "H5Dopen");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(dataset);
    VERIFY(ret, 1, "H5Aget_num_attrs");

    /* Open an attribute for the dataset */
    attr=H5Aopen_name(dataset,ATTR5_NAME);
    CHECK(attr, FAIL, "H5Aopen_name");

    /* Read attribute information */
    ret=H5Aread(attr,H5T_NATIVE_FLOAT,&rdata);
    CHECK(ret, FAIL, "H5Aread");
    /* Verify the floating-poing value in this way to avoid compiler warning. */
    if(!FLT_ABS_EQUAL(rdata,attr_data5))
	printf("*** UNEXPECTED VALUE from %s should be %f, but is %f at line %4d in %s\n",
	    "H5Aread", attr_data5, rdata, (int)__LINE__, __FILE__);
 
    /* Get the attribute's dataspace */
    sid = H5Aget_space(attr);
    CHECK(sid, FAIL, "H5Aget_space");

    /* Make certain the dataspace is scalar */
    stype = H5Sget_simple_extent_type (sid);
    VERIFY(stype, H5S_SCALAR, "H5Sget_simple_extent_type");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid1);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_scalar_read() */


/****************************************************************
**
**  test_attr_mult_write(): Test basic H5A (attribute) code.
**      Tests integer attributes on both datasets and groups
**
****************************************************************/
static void
test_attr_mult_write(hid_t fapl)
{
    hid_t		fid1;		/* HDF5 File IDs		*/
    hid_t		dataset;	/* Dataset ID			*/
    hid_t		sid1,sid2;	/* Dataspace ID			*/
    hid_t		attr;	    /* Attribute ID			*/
    hsize_t		dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3};
    hsize_t		dims2[] = {ATTR1_DIM1};
    hsize_t		dims3[] = {ATTR2_DIM1,ATTR2_DIM2};
    hsize_t		dims4[] = {ATTR3_DIM1,ATTR3_DIM2,ATTR3_DIM3};
    herr_t		ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Multiple Attribute Functions\n"));

    /* Create file */
    fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
    CHECK(fid1, FAIL, "H5Fcreate");

    /* Create dataspace for dataset */
    sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL);
    CHECK(sid1, FAIL, "H5Screate_simple");

    /* Create a dataset */
    dataset=H5Dcreate(fid1,DSET1_NAME,H5T_NATIVE_UCHAR,sid1,H5P_DEFAULT);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Close dataset's dataspace */
    ret = H5Sclose(sid1);
    CHECK(ret, FAIL, "H5Sclose");

    /* Create dataspace for 1st attribute */
    sid2 = H5Screate_simple(ATTR1_RANK, dims2, NULL);
    CHECK(sid2, FAIL, "H5Screate_simple");

    /* Create 1st attribute for the dataset */
    attr=H5Acreate(dataset,ATTR1_NAME,H5T_NATIVE_INT,sid2,H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Try to create the same attribute again (should fail) */
    ret=H5Acreate(dataset,ATTR1_NAME,H5T_NATIVE_INT,sid2,H5P_DEFAULT);
    VERIFY(ret, FAIL, "H5Acreate");

    /* Write 1st attribute data */
    ret=H5Awrite(attr,H5T_NATIVE_INT,attr_data1);
    CHECK(ret, FAIL, "H5Awrite");

    /* Close 1st attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close attribute's dataspace */
    ret = H5Sclose(sid2);
    CHECK(ret, FAIL, "H5Sclose");

    /* Create dataspace for 2nd attribute */
    sid2 = H5Screate_simple(ATTR2_RANK, dims3, NULL);
    CHECK(sid2, FAIL, "H5Screate_simple");

    /* Create 2nd attribute for the dataset */
    attr=H5Acreate(dataset,ATTR2_NAME,H5T_NATIVE_INT,sid2,H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Try to create the same attribute again (should fail) */
    ret=H5Acreate(dataset,ATTR2_NAME,H5T_NATIVE_INT,sid2,H5P_DEFAULT);
    VERIFY(ret, FAIL, "H5Acreate");

    /* Write 2nd attribute information */
    ret=H5Awrite(attr,H5T_NATIVE_INT,attr_data2);
    CHECK(ret, FAIL, "H5Awrite");

    /* Close 2nd attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close 2nd attribute's dataspace */
    ret = H5Sclose(sid2);
    CHECK(ret, FAIL, "H5Sclose");

    /* Create dataspace for 3rd attribute */
    sid2 = H5Screate_simple(ATTR3_RANK, dims4, NULL);
    CHECK(sid2, FAIL, "H5Screate_simple");

    /* Create 3rd attribute for the dataset */
    attr=H5Acreate(dataset,ATTR3_NAME,H5T_NATIVE_DOUBLE,sid2,H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Try to create the same attribute again (should fail) */
    ret=H5Acreate(dataset,ATTR3_NAME,H5T_NATIVE_DOUBLE,sid2,H5P_DEFAULT);
    VERIFY(ret, FAIL, "H5Acreate");

    /* Write 3rd attribute information */
    ret=H5Awrite(attr,H5T_NATIVE_DOUBLE,attr_data3);
    CHECK(ret, FAIL, "H5Awrite");

    /* Close 3rd attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close 3rd attribute's dataspace */
    ret = H5Sclose(sid2);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid1);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_mult_write() */


/****************************************************************
**
**  test_attr_mult_read(): Test basic H5A (attribute) code.
**
****************************************************************/
static void
test_attr_mult_read(hid_t fapl)
{
    hid_t   fid1;		/* HDF5 File IDs		*/
    hid_t   dataset;	/* Dataset ID			*/
    hid_t   space;      /* Attribute dataspace  */
    hid_t   type;       /* Attribute datatype   */
    hid_t   attr;	    /* Attribute ID			*/
    char    attr_name[ATTR_NAME_LEN]; /* Buffer for attribute names */
    char    temp_name[ATTR_NAME_LEN]; /* Buffer for mangling attribute names */
    int     rank;       /* Attribute rank */
    hsize_t dims[ATTR_MAX_DIMS];    /* Attribute dimensions */
    H5T_class_t t_class;              /* Attribute datatype class */
    H5T_order_t order;              /* Attribute datatype order */
    size_t      size;               /* Attribute datatype size as stored in file */
    int   read_data1[ATTR1_DIM1]={0}; /* Buffer for reading 1st attribute */
    int   read_data2[ATTR2_DIM1][ATTR2_DIM2]={{0}}; /* Buffer for reading 2nd attribute */
    double  read_data3[ATTR3_DIM1][ATTR3_DIM2][ATTR3_DIM3]={{{0}}}; /* Buffer for reading 3rd attribute */
    int     i,j,k;
    size_t  name_len;   /* Length of attribute name */
    herr_t  ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Basic Attribute Functions\n"));

    /* Open file */
    fid1 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid1, FAIL, "H5Fopen");

    /* Open the dataset */
    dataset=H5Dopen(fid1,DSET1_NAME);
    CHECK(dataset, FAIL, "H5Dopen");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(dataset);
    VERIFY(ret, 3, "H5Aget_num_attrs");

    /* Open 1st attribute for the dataset */
    attr=H5Aopen_idx(dataset,0);
    CHECK(attr, FAIL, "H5Aopen_idx");

    /* Verify Dataspace */
    space=H5Aget_space(attr);
    CHECK(space, FAIL, "H5Aget_space");
    rank=H5Sget_simple_extent_ndims(space);
    VERIFY(rank, ATTR1_RANK, "H5Sget_simple_extent_ndims");
    ret=H5Sget_simple_extent_dims(space,dims, NULL);
    CHECK(ret, FAIL, "H5Sget_simple_extent_dims");
    if(dims[0]!=ATTR1_DIM1)
        TestErrPrintf("attribute dimensions different: dims[0]=%d, should be %d\n",(int)dims[0],ATTR1_DIM1);
    H5Sclose(space);

    /* Verify Datatype */
    type=H5Aget_type(attr);
    CHECK(type, FAIL, "H5Aget_type");
    t_class=H5Tget_class(type);
    VERIFY(t_class, H5T_INTEGER, "H5Tget_class");
    order=H5Tget_order(type);
    VERIFY(order, H5Tget_order(H5T_NATIVE_INT), "H5Tget_order");
    size=H5Tget_size(type);
    VERIFY(size, H5Tget_size(H5T_NATIVE_INT), "H5Tget_size");
    H5Tclose(type);

    /* Read attribute information */
    ret=H5Aread(attr,H5T_NATIVE_INT,read_data1);
    CHECK(ret, FAIL, "H5Aread");

    /* Verify values read in */
    for(i=0; i<ATTR1_DIM1; i++)
        if(attr_data1[i]!=read_data1[i])
            TestErrPrintf("%d: attribute data different: attr_data1[%d]=%d, read_data1[%d]=%d\n",__LINE__,i,attr_data1[i],i,read_data1[i]);

    /* Verify Name */
    name_len=H5Aget_name(attr, (size_t)ATTR_NAME_LEN, attr_name);
    VERIFY(name_len, HDstrlen(ATTR1_NAME), "H5Aget_name");
    if(HDstrcmp(attr_name,ATTR1_NAME))
        TestErrPrintf("attribute name different: attr_name=%s, should be %s\n",attr_name,ATTR1_NAME);

    /* Verify Name with too small of a buffer */
    name_len=H5Aget_name(attr,HDstrlen(ATTR1_NAME), attr_name);
    VERIFY(name_len, HDstrlen(ATTR1_NAME), "H5Aget_name");
    HDstrcpy(temp_name,ATTR1_NAME);     /* make a copy of the name */
    temp_name[HDstrlen(ATTR1_NAME)-1]='\0';   /* truncate it to match the one retrieved */
    if(HDstrcmp(attr_name,temp_name))
        TestErrPrintf("attribute name different: attr_name=%s, should be %s\n",attr_name,temp_name);

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Open 2nd attribute for the dataset */
    attr=H5Aopen_idx(dataset,1);
    CHECK(attr, FAIL, "H5Aopen_idx");

    /* Verify Dataspace */
    space=H5Aget_space(attr);
    CHECK(space, FAIL, "H5Aget_space");
    rank=H5Sget_simple_extent_ndims(space);
    VERIFY(rank, ATTR2_RANK, "H5Sget_simple_extent_ndims");
    ret=H5Sget_simple_extent_dims(space,dims, NULL);
    CHECK(ret, FAIL, "H5Sget_simple_extent_dims");
    if(dims[0]!=ATTR2_DIM1)
        TestErrPrintf("attribute dimensions different: dims[0]=%d, should be %d\n",(int)dims[0],ATTR2_DIM1);
    if(dims[1]!=ATTR2_DIM2)
        TestErrPrintf("attribute dimensions different: dims[1]=%d, should be %d\n",(int)dims[1],ATTR2_DIM2);
    H5Sclose(space);

    /* Verify Datatype */
    type=H5Aget_type(attr);
    CHECK(type, FAIL, "H5Aget_type");
    t_class=H5Tget_class(type);
    VERIFY(t_class, H5T_INTEGER, "H5Tget_class");
    order=H5Tget_order(type);
    VERIFY(order, H5Tget_order(H5T_NATIVE_INT), "H5Tget_order");
    size=H5Tget_size(type);
    VERIFY(size, H5Tget_size(H5T_NATIVE_INT), "H5Tget_size");
    H5Tclose(type);

    /* Read attribute information */
    ret=H5Aread(attr,H5T_NATIVE_INT,read_data2);
    CHECK(ret, FAIL, "H5Aread");

    /* Verify values read in */
    for(i=0; i<ATTR2_DIM1; i++)
        for(j=0; j<ATTR2_DIM2; j++)
            if(attr_data2[i][j]!=read_data2[i][j])
                TestErrPrintf("%d: attribute data different: attr_data2[%d][%d]=%d, read_data2[%d][%d]=%d\n",__LINE__,i,j,attr_data2[i][j],i,j,read_data2[i][j]);

    /* Verify Name */
    name_len=H5Aget_name(attr, (size_t)ATTR_NAME_LEN, attr_name);
    VERIFY(name_len, HDstrlen(ATTR2_NAME), "H5Aget_name");
    if(HDstrcmp(attr_name,ATTR2_NAME))
        TestErrPrintf("attribute name different: attr_name=%s, should be %s\n",attr_name,ATTR2_NAME);

    /* Verify Name with too small of a buffer */
    name_len=H5Aget_name(attr, HDstrlen(ATTR2_NAME), attr_name);
    VERIFY(name_len, HDstrlen(ATTR2_NAME), "H5Aget_name");
    HDstrcpy(temp_name,ATTR2_NAME);     /* make a copy of the name */
    temp_name[HDstrlen(ATTR2_NAME)-1]='\0';   /* truncate it to match the one retrieved */
    if(HDstrcmp(attr_name,temp_name))
        TestErrPrintf("attribute name different: attr_name=%s, should be %s\n",attr_name,temp_name);

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Open 2nd attribute for the dataset */
    attr=H5Aopen_idx(dataset,2);
    CHECK(attr, FAIL, "H5Aopen_idx");

    /* Verify Dataspace */
    space=H5Aget_space(attr);
    CHECK(space, FAIL, "H5Aget_space");
    rank=H5Sget_simple_extent_ndims(space);
    VERIFY(rank, ATTR3_RANK, "H5Sget_simple_extent_ndims");
    ret=H5Sget_simple_extent_dims(space,dims, NULL);
    CHECK(ret, FAIL, "H5Sget_simple_extent_dims");
    if(dims[0]!=ATTR3_DIM1)
        TestErrPrintf("attribute dimensions different: dims[0]=%d, should be %d\n",(int)dims[0],ATTR3_DIM1);
    if(dims[1]!=ATTR3_DIM2)
        TestErrPrintf("attribute dimensions different: dims[1]=%d, should be %d\n",(int)dims[1],ATTR3_DIM2);
    if(dims[2]!=ATTR3_DIM3)
        TestErrPrintf("attribute dimensions different: dims[2]=%d, should be %d\n",(int)dims[2],ATTR3_DIM3);
    H5Sclose(space);

    /* Verify Datatype */
    type=H5Aget_type(attr);
    CHECK(type, FAIL, "H5Aget_type");
    t_class=H5Tget_class(type);
    VERIFY(t_class, H5T_FLOAT, "H5Tget_class");
    order=H5Tget_order(type);
    VERIFY(order, H5Tget_order(H5T_NATIVE_DOUBLE), "H5Tget_order");
    size=H5Tget_size(type);
    VERIFY(size, H5Tget_size(H5T_NATIVE_DOUBLE), "H5Tget_size");
    H5Tclose(type);

    /* Read attribute information */
    ret=H5Aread(attr,H5T_NATIVE_DOUBLE,read_data3);
    CHECK(ret, FAIL, "H5Aread");

    /* Verify values read in */
    for(i=0; i<ATTR3_DIM1; i++)
        for(j=0; j<ATTR3_DIM2; j++)
            for(k=0; k<ATTR3_DIM3; k++)
                if(!DBL_ABS_EQUAL(attr_data3[i][j][k],read_data3[i][j][k]))
                    TestErrPrintf("%d: attribute data different: attr_data3[%d][%d][%d]=%f, read_data3[%d][%d][%d]=%f\n",__LINE__,i,j,k,attr_data3[i][j][k],i,j,k,read_data3[i][j][k]);

    /* Verify Name */
    name_len=H5Aget_name(attr, (size_t)ATTR_NAME_LEN, attr_name);
    VERIFY(name_len, HDstrlen(ATTR3_NAME), "H5Aget_name");
    if(HDstrcmp(attr_name,ATTR3_NAME))
        TestErrPrintf("attribute name different: attr_name=%s, should be %s\n",attr_name,ATTR3_NAME);

    /* Verify Name with too small of a buffer */
    name_len=H5Aget_name(attr, HDstrlen(ATTR3_NAME), attr_name);
    VERIFY(name_len, HDstrlen(ATTR3_NAME), "H5Aget_name");
    HDstrcpy(temp_name,ATTR3_NAME);     /* make a copy of the name */
    temp_name[HDstrlen(ATTR3_NAME)-1]='\0';   /* truncate it to match the one retrieved */
    if(HDstrcmp(attr_name,temp_name))
        TestErrPrintf("attribute name different: attr_name=%s, should be %s\n",attr_name,temp_name);

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid1);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_mult_read() */


/****************************************************************
**
**  attr_op1(): Attribute operator
**
****************************************************************/
herr_t attr_op1(hid_t UNUSED loc_id, const char *name, void *op_data)
{
    int *count=(int *)op_data;
    herr_t ret=0;

    switch(*count) {
        case 0:
            if(HDstrcmp(name,ATTR1_NAME))
                TestErrPrintf("attribute name different: name=%s, should be %s\n",name,ATTR1_NAME);
             (*count)++;
             break;

        case 1:
            if(HDstrcmp(name,ATTR2_NAME))
                TestErrPrintf("attribute name different: name=%s, should be %s\n",name,ATTR2_NAME);
             (*count)++;
             break;

        case 2:
            if(HDstrcmp(name,ATTR3_NAME))
                TestErrPrintf("attribute name different: name=%s, should be %s\n",name,ATTR3_NAME);
             (*count)++;
             break;

        default:
            ret=-1;
            break;
    }  /* end switch() */

    return(ret);
} /* end attr_op1() */


/****************************************************************
**
**  test_attr_iterate(): Test H5A (attribute) iterator code.
**
****************************************************************/
static void
test_attr_iterate(hid_t fapl)
{
    hid_t   file;		/* HDF5 File ID 		*/
    hid_t   dataset;	/* Dataset ID			*/
    hid_t   sid;	/* Dataspace ID			*/
    unsigned start;     /* Starting attribute to look up */
    int     count;      /* operator data for the iterator */
    herr_t  ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Basic Attribute Functions\n"));

    /* Open file */
    file = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(file, FAIL, "H5Fopen");

    /* Create a dataspace */
    sid=H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create a new dataset */
    dataset=H5Dcreate(file,DSET2_NAME,H5T_NATIVE_INT,sid,H5P_DEFAULT);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(dataset);
    VERIFY(ret, 0, "H5Aget_num_attrs");

    /* Iterate over attributes on dataset */
    start = 0;
    count = 0;
    ret = H5Aiterate(dataset, &start, attr_op1, &count);
    VERIFY(ret, 0, "H5Aiterate");

    /* Close dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Open existing dataset w/attributes */
    dataset=H5Dopen(file,DSET1_NAME);
    CHECK(dataset, FAIL, "H5Dopen");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(dataset);
    VERIFY(ret, 3, "H5Aget_num_attrs");

    /* Iterate over attributes on dataset */
    start=0;
    count=0;
    ret = H5Aiterate(dataset,&start,attr_op1,&count);
    VERIFY(ret, 0, "H5Aiterate");

    /* Close dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(file);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_iterate() */


/****************************************************************
**
**  test_attr_delete(): Test H5A (attribute) code for deleting objects.
**
****************************************************************/
static void
test_attr_delete(hid_t fapl)
{
    hid_t   fid1;		/* HDF5 File ID 		*/
    hid_t   dataset;	/* Dataset ID			*/
    hid_t   attr;	    /* Attribute ID			*/
    char    attr_name[ATTR_NAME_LEN]; /* Buffer for attribute names */
    size_t  name_len;   /* Length of attribute name */
    herr_t  ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Basic Attribute Functions\n"));

    /* Open file */
    fid1 = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid1, FAIL, "H5Fopen");

    /* Open the dataset */
    dataset=H5Dopen(fid1,DSET1_NAME);
    CHECK(dataset, FAIL, "H5Dopen");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(dataset);
    VERIFY(ret, 3, "H5Aget_num_attrs");

    /* Try to delete bogus attribute */
    ret=H5Adelete(dataset,"Bogus");
    VERIFY(ret, FAIL, "H5Adelete");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(dataset);
    VERIFY(ret, 3, "H5Aget_num_attrs");

    /* Delete middle (2nd) attribute */
    ret=H5Adelete(dataset,ATTR2_NAME);
    CHECK(ret, FAIL, "H5Adelete");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(dataset);
    VERIFY(ret, 2, "H5Aget_num_attrs");

    /* Open 1st attribute for the dataset */
    attr=H5Aopen_idx(dataset,0);
    CHECK(attr, FAIL, "H5Aopen_idx");

    /* Verify Name */
    name_len=H5Aget_name(attr, (size_t)ATTR_NAME_LEN,attr_name);
    VERIFY(name_len, HDstrlen(ATTR1_NAME), "H5Aget_name");
    if(HDstrcmp(attr_name,ATTR1_NAME))
        TestErrPrintf("attribute name different: attr_name=%s, should be %s\n",attr_name,ATTR1_NAME);

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Open last (formally 3rd) attribute for the dataset */
    attr=H5Aopen_idx(dataset,1);
    CHECK(attr, FAIL, "H5Aopen_idx");

    /* Verify Name */
    name_len=H5Aget_name(attr, (size_t)ATTR_NAME_LEN, attr_name);
    VERIFY(name_len, HDstrlen(ATTR3_NAME), "H5Aget_name");
    if(HDstrcmp(attr_name,ATTR3_NAME))
        TestErrPrintf("attribute name different: attr_name=%s, should be %s\n",attr_name,ATTR3_NAME);

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Delete first attribute */
    ret=H5Adelete(dataset,ATTR1_NAME);
    CHECK(ret, FAIL, "H5Adelete");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(dataset);
    VERIFY(ret, 1, "H5Aget_num_attrs");

    /* Open last (formally 3rd) attribute for the dataset */
    attr=H5Aopen_idx(dataset,0);
    CHECK(attr, FAIL, "H5Aopen_idx");

    /* Verify Name */
    name_len=H5Aget_name(attr, (size_t)ATTR_NAME_LEN, attr_name);
    VERIFY(name_len, HDstrlen(ATTR3_NAME), "H5Aget_name");
    if(HDstrcmp(attr_name,ATTR3_NAME))
        TestErrPrintf("attribute name different: attr_name=%s, should be %s\n",attr_name,ATTR3_NAME);

    /* Close attribute */
    ret=H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Delete first attribute */
    ret=H5Adelete(dataset,ATTR3_NAME);
    CHECK(ret, FAIL, "H5Adelete");

    /* Verify the correct number of attributes */
    ret=H5Aget_num_attrs(dataset);
    VERIFY(ret, 0, "H5Aget_num_attrs");

    /* Close dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid1);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_delete() */


/****************************************************************
**
**  test_attr_dtype_shared(): Test H5A (attribute) code for using
**                              shared datatypes in attributes.
**
****************************************************************/
static void
test_attr_dtype_shared(hid_t fapl)
{
    hid_t file_id;              /* File ID */
    hid_t dset_id;              /* Dataset ID */
    hid_t space_id;             /* Dataspace ID for dataset & attribute */
    hid_t type_id;              /* Datatype ID for named datatype */
    hid_t attr_id;              /* Attribute ID */
    int data=8;                 /* Data to write */
    int rdata=0;                /* Read read in */
    H5G_stat_t statbuf;         /* Object's information */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    herr_t  ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Shared Datatypes with Attributes\n"));

    /* Create a file */
    file_id=H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
    CHECK(file_id, FAIL, "H5Fopen");

    /* Close file */
    ret=H5Fclose(file_id);
    CHECK(ret, FAIL, "H5Fclose");

    /* Get size of file */
    empty_filesize=h5_get_file_size(FILENAME);
    if(empty_filesize<0)
        TestErrPrintf("Line %d: file size wrong!\n",__LINE__);


    /* Re-open file */
    file_id=H5Fopen(FILENAME,H5F_ACC_RDWR,fapl);
    CHECK(file_id, FAIL, "H5Fopen");

    /* Create a datatype to commit and use */
    type_id=H5Tcopy(H5T_NATIVE_INT);
    CHECK(type_id, FAIL, "H5Tcopy");

    /* Commit datatype to file */
    ret=H5Tcommit(file_id,TYPE1_NAME,type_id);
    CHECK(ret, FAIL, "H5Tcommit");

    /* Check reference count on named datatype */
    ret=H5Gget_objinfo(file_id,TYPE1_NAME,0,&statbuf);
    CHECK(ret, FAIL, "H5Gget_objinfo");
    VERIFY(statbuf.nlink, 1, "H5Tcommit");

    /* Create dataspace for dataset */
    space_id=H5Screate(H5S_SCALAR);
    CHECK(space_id, FAIL, "H5Screate");

    /* Create dataset */
    dset_id=H5Dcreate(file_id,DSET1_NAME,type_id,space_id,H5P_DEFAULT);
    CHECK(dset_id, FAIL, "H5Dcreate");

    /* Check reference count on named datatype */
    ret=H5Gget_objinfo(file_id,TYPE1_NAME,0,&statbuf);
    CHECK(ret, FAIL, "H5Gget_objinfo");
    VERIFY(statbuf.nlink, 2, "H5Dcreate");

    /* Create attribute on dataset */
    attr_id=H5Acreate(dset_id,ATTR1_NAME,type_id,space_id,H5P_DEFAULT);
    CHECK(attr_id, FAIL, "H5Acreate");

    /* Check reference count on named datatype */
    ret=H5Gget_objinfo(file_id,TYPE1_NAME,0,&statbuf);
    CHECK(ret, FAIL, "H5Gget_objinfo");
    VERIFY(statbuf.nlink, 3, "H5Acreate");

    /* Close attribute */
    ret=H5Aclose(attr_id);
    CHECK(ret, FAIL, "H5Aclose");

    /* Delete attribute */
    ret=H5Adelete(dset_id,ATTR1_NAME);
    CHECK(ret, FAIL, "H5Adelete");

    /* Check reference count on named datatype */
    ret=H5Gget_objinfo(file_id,TYPE1_NAME,0,&statbuf);
    CHECK(ret, FAIL, "H5Gget_objinfo");
    VERIFY(statbuf.nlink, 2, "H5Adelete");

    /* Create attribute on dataset */
    attr_id=H5Acreate(dset_id,ATTR1_NAME,type_id,space_id,H5P_DEFAULT);
    CHECK(attr_id, FAIL, "H5Acreate");

    /* Check reference count on named datatype */
    ret=H5Gget_objinfo(file_id,TYPE1_NAME,0,&statbuf);
    CHECK(ret, FAIL, "H5Gget_objinfo");
    VERIFY(statbuf.nlink, 3, "H5Acreate");

    /* Write data into the attribute */
    ret=H5Awrite(attr_id,H5T_NATIVE_INT,&data);
    CHECK(ret, FAIL, "H5Awrite");

    /* Close attribute */
    ret=H5Aclose(attr_id);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close dataset */
    ret=H5Dclose(dset_id);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close dataspace */
    ret=H5Sclose(space_id);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close datatype */
    ret=H5Tclose(type_id);
    CHECK(ret, FAIL, "H5Tclose");

    /* Close file */
    ret=H5Fclose(file_id);
    CHECK(ret, FAIL, "H5Fclose");

    /* Re-open file */
    file_id=H5Fopen(FILENAME,H5F_ACC_RDWR,fapl);
    CHECK(file_id, FAIL, "H5Fopen");

    /* Open dataset */
    dset_id=H5Dopen(file_id,DSET1_NAME);
    CHECK(dset_id, FAIL, "H5Dopen");

    /* Open attribute */
    attr_id=H5Aopen_name(dset_id,ATTR1_NAME);
    CHECK(attr_id, FAIL, "H5Aopen_name");

    /* Read data from the attribute */
    ret=H5Aread(attr_id,H5T_NATIVE_INT,&rdata);
    CHECK(ret, FAIL, "H5Aread");
    VERIFY(data, rdata, "H5Aread");

    /* Close attribute */
    ret=H5Aclose(attr_id);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close dataset */
    ret=H5Dclose(dset_id);
    CHECK(ret, FAIL, "H5Dclose");

    /* Check reference count on named datatype */
    ret=H5Gget_objinfo(file_id,TYPE1_NAME,0,&statbuf);
    CHECK(ret, FAIL, "H5Gget_objinfo");
    VERIFY(statbuf.nlink, 3, "H5Gget_objinfo");

    /* Unlink the dataset */
    ret=H5Gunlink(file_id,DSET1_NAME);
    CHECK(ret, FAIL, "H5Gunlink");

    /* Check reference count on named datatype */
    ret=H5Gget_objinfo(file_id,TYPE1_NAME,0,&statbuf);
    CHECK(ret, FAIL, "H5Gget_objinfo");
    VERIFY(statbuf.nlink, 1, "H5Gget_objinfo");

    /* Unlink the named datatype */
    ret=H5Gunlink(file_id,TYPE1_NAME);
    CHECK(ret, FAIL, "H5Gunlink");

    /* Close file */
    ret=H5Fclose(file_id);
    CHECK(ret, FAIL, "H5Fclose");

    /* Check size of file */
    filesize=h5_get_file_size(FILENAME);
    VERIFY(filesize, empty_filesize, "h5_get_file_size");
}   /* test_attr_dtype_shared() */


/****************************************************************
**
**  test_attr_dense_verify(): Test basic H5A (attribute) code.
**      Verify attributes on object
**
****************************************************************/
static int
test_attr_dense_verify(hid_t loc_id, unsigned max_attr)
{
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    hid_t	attr;	        /* Attribute ID	*/
    unsigned    value;          /* Attribute value */
    unsigned    u;              /* Local index variable */
    int         old_nerrs;      /* Number of errors when entering this check */
    herr_t	ret;		/* Generic return value	*/

    /* Retrieve the current # of reported errors */
    old_nerrs = GetTestNumErrs();

    /* Re-open all the attributes by name and verify the data */
    for(u = 0; u < max_attr; u++) {
        /* Open attribute */
        sprintf(attrname, "attr %02u", u);
        attr = H5Aopen_name(loc_id, attrname);
        CHECK(attr, FAIL, "H5Aopen_name");

        /* Read data from the attribute */
        ret = H5Aread(attr, H5T_NATIVE_UINT, &value);
        CHECK(ret, FAIL, "H5Aread");
        VERIFY(value, u, "H5Aread");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");
    } /* end for */

    /* Re-open all the attributes by index and verify the data */
    for(u = 0; u < max_attr; u++) {
        size_t name_len;                /* Length of attribute name */
        char check_name[ATTR_NAME_LEN]; /* Buffer for checking attribute names */

        /* Open attribute */
        attr = H5Aopen_idx(loc_id, u);
        CHECK(attr, FAIL, "H5Aopen_idx");

        /* Verify Name */
        sprintf(attrname, "attr %02u", u);
        name_len = H5Aget_name(attr, (size_t)ATTR_NAME_LEN, check_name);
        VERIFY(name_len, HDstrlen(attrname), "H5Aget_name");
        if(HDstrcmp(check_name, attrname))
            TestErrPrintf("attribute name different: attr_name = '%s', should be '%s'\n", check_name, attrname);

        /* Read data from the attribute */
        ret = H5Aread(attr, H5T_NATIVE_UINT, &value);
        CHECK(ret, FAIL, "H5Aread");
        VERIFY(value, u, "H5Aread");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");
    } /* end for */

    /* Retrieve current # of errors */
    if(old_nerrs == GetTestNumErrs())
        return(0);
    else
        return(-1);
}   /* test_attr_dense_verify() */


/****************************************************************
**
**  test_attr_dense_create(): Test basic H5A (attribute) code.
**      Tests "dense" attribute storage creation
**
****************************************************************/
static void
test_attr_dense_create(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dataset;	/* Dataset ID			*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    unsigned    max_compact;    /* Maximum # of attributes to store compactly */
    unsigned    min_dense;      /* Minimum # of attributes to store "densely" */
    htri_t	is_dense;	/* Are attributes stored densely? */
    unsigned    u;              /* Local index variable */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Dense Attribute Storage Creation\n"));

    /* Create file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Get size of file */
    empty_filesize = h5_get_file_size(FILENAME);
    if(empty_filesize < 0)
        TestErrPrintf("Line %d: file size wrong!\n", __LINE__);

    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Create dataspace for dataset */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Query the group creation properties */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Create a dataset */
    dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Retrieve limits for compact/dense attribute storage */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

    /* Add attributes, until just before converting to dense storage */
    for(u = 0; u < max_compact; u++) {
        /* Create attribute */
        sprintf(attrname, "attr %02u", u);
        attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
        CHECK(attr, FAIL, "H5Acreate");

        /* Write data into the attribute */
        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
        CHECK(ret, FAIL, "H5Awrite");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");
    } /* end for */

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

    /* Add one more attribute, to push into "dense" storage */
    /* Create attribute */
    sprintf(attrname, "attr %02u", u);
    attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

    /* Write data into the attribute */
    ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
    CHECK(ret, FAIL, "H5Awrite");

    /* Close attribute */
    ret = H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Attempt to add attribute again, which should fail */
    attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
    VERIFY(attr, FAIL, "H5Acreate");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Unlink dataset with attributes */
    ret = H5Gunlink(fid, DSET1_NAME);
    CHECK(ret, FAIL, "H5Gunlink");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Check size of file */
    filesize = h5_get_file_size(FILENAME);
    VERIFY(filesize, empty_filesize, "h5_get_file_size");
}   /* test_attr_dense_create() */


/****************************************************************
**
**  test_attr_dense_open(): Test basic H5A (attribute) code.
**      Tests opening attributes in "dense" storage
**
****************************************************************/
static void
test_attr_dense_open(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dataset;	/* Dataset ID			*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    unsigned    max_compact;    /* Maximum # of attributes to store compactly */
    unsigned    min_dense;      /* Minimum # of attributes to store "densely" */
    htri_t	is_dense;	/* Are attributes stored densely? */
    unsigned    u;              /* Local index variable */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Opening Attributes in Dense Storage\n"));

    /* Create file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Get size of file */
    empty_filesize = h5_get_file_size(FILENAME);
    if(empty_filesize < 0)
        TestErrPrintf("Line %d: file size wrong!\n", __LINE__);

    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Create dataspace for dataset */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Query the group creation properties */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Enable creation order tracking on attributes, so creation order tests work */
    ret = H5Pset_attr_creation_order(dcpl, H5P_CRT_ORDER_TRACKED);
    CHECK(ret, FAIL, "H5Pset_attr_creation_order");

    /* Create a dataset */
    dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Retrieve limits for compact/dense attribute storage */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

    /* Add attributes, until just before converting to dense storage */
    for(u = 0; u < max_compact; u++) {
        /* Create attribute */
        sprintf(attrname, "attr %02u", u);
        attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
        CHECK(attr, FAIL, "H5Acreate");

        /* Write data into the attribute */
        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
        CHECK(ret, FAIL, "H5Awrite");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");

        /* Verify attributes written so far */
        ret = test_attr_dense_verify(dataset, u);
        CHECK(ret, FAIL, "test_attr_dense_verify");
    } /* end for */

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

    /* Add one more attribute, to push into "dense" storage */
    /* Create attribute */
    sprintf(attrname, "attr %02u", u);
    attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

    /* Write data into the attribute */
    ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
    CHECK(ret, FAIL, "H5Awrite");

    /* Close attribute */
    ret = H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Verify all the attributes written */
    ret = test_attr_dense_verify(dataset, (u + 1));
    CHECK(ret, FAIL, "test_attr_dense_verify");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Unlink dataset with attributes */
    ret = H5Gunlink(fid, DSET1_NAME);
    CHECK(ret, FAIL, "H5Gunlink");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Check size of file */
    filesize = h5_get_file_size(FILENAME);
    VERIFY(filesize, empty_filesize, "h5_get_file_size");
}   /* test_attr_dense_open() */


/****************************************************************
**
**  test_attr_dense_delete(): Test basic H5A (attribute) code.
**      Tests deleting attributes in "dense" storage
**
****************************************************************/
static void
test_attr_dense_delete(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dataset;	/* Dataset ID			*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    unsigned    max_compact;    /* Maximum # of attributes to store compactly */
    unsigned    min_dense;      /* Minimum # of attributes to store "densely" */
    htri_t	is_dense;	/* Are attributes stored densely? */
    unsigned    u;              /* Local index variable */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    int         attr_count;     /* # of attributes */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Deleting Attributes in Dense Storage\n"));

    /* Create file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Get size of file */
    empty_filesize = h5_get_file_size(FILENAME);
    if(empty_filesize < 0)
        TestErrPrintf("Line %d: file size wrong!\n", __LINE__);

    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Create dataspace for dataset */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Query the group creation properties */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Enable creation order tracking on attributes, so creation order tests work */
    ret = H5Pset_attr_creation_order(dcpl, H5P_CRT_ORDER_TRACKED);
    CHECK(ret, FAIL, "H5Pset_attr_creation_order");

    /* Create a dataset */
    dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Retrieve limits for compact/dense attribute storage */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

    /* Add attributes, until well into dense storage */
    for(u = 0; u < (max_compact * 2); u++) {
        /* Create attribute */
        sprintf(attrname, "attr %02u", u);
        attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
        CHECK(attr, FAIL, "H5Acreate");

        /* Write data into the attribute */
        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
        CHECK(ret, FAIL, "H5Awrite");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");

        /* Check # of attributes */
        attr_count = H5Aget_num_attrs(dataset);
        CHECK(attr_count, FAIL, "H5Aget_num_attrs");
        VERIFY(attr_count, (int)(u + 1), "H5Aget_num_attrs");
    } /* end for */

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");


    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Open dataset */
    dataset = H5Dopen(fid, DSET1_NAME);
    CHECK(dataset, FAIL, "H5Dopen");

    /* Delete attributes until the attributes revert to compact storage again */
    for(u--; u >= min_dense; u--) {
        /* Delete attribute */
        sprintf(attrname, "attr %02u", u);
        ret = H5Adelete(dataset, attrname);
        CHECK(ret, FAIL, "H5Adelete");

        /* Verify attributes still left */
        ret = test_attr_dense_verify(dataset, u);
        CHECK(ret, FAIL, "test_attr_dense_verify");
    } /* end for */

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

    /* Delete one more attribute, which should cause reversion to compact storage */
    sprintf(attrname, "attr %02u", u);
    ret = H5Adelete(dataset, attrname);
    CHECK(ret, FAIL, "H5Adelete");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

    /* Verify attributes still left */
    ret = test_attr_dense_verify(dataset, (u - 1));
    CHECK(ret, FAIL, "test_attr_dense_verify");

    /* Delete another attribute, to verify deletion in compact storage */
    sprintf(attrname, "attr %02u", (u - 1));
    ret = H5Adelete(dataset, attrname);
    CHECK(ret, FAIL, "H5Adelete");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

    /* Verify attributes still left */
    ret = test_attr_dense_verify(dataset, (u - 2));
    CHECK(ret, FAIL, "test_attr_dense_verify");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Unlink dataset with attributes */
    ret = H5Gunlink(fid, DSET1_NAME);
    CHECK(ret, FAIL, "H5Gunlink");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Check size of file */
    filesize = h5_get_file_size(FILENAME);
    VERIFY(filesize, empty_filesize, "h5_get_file_size");
}   /* test_attr_dense_delete() */


/****************************************************************
**
**  test_attr_dense_rename(): Test basic H5A (attribute) code.
**      Tests renaming attributes in "dense" storage
**
****************************************************************/
static void
test_attr_dense_rename(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dataset;	/* Dataset ID			*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    char	new_attrname[NAME_BUF_SIZE];    /* New name of attribute */
    unsigned    max_compact;    /* Maximum # of attributes to store compactly */
    unsigned    min_dense;      /* Minimum # of attributes to store "densely" */
    htri_t	is_dense;	/* Are attributes stored densely? */
    int         attr_count;     /* # of attributes */
    unsigned    u;              /* Local index variable */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Renaming Attributes in Dense Storage\n"));

    /* Create file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Get size of file */
    empty_filesize = h5_get_file_size(FILENAME);
    if(empty_filesize < 0)
        TestErrPrintf("Line %d: file size wrong!\n", __LINE__);

    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Create dataspace for dataset */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Query the group creation properties */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Create a dataset */
    dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Retrieve limits for compact/dense attribute storage */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

    /* Add attributes, until well into dense storage */
    for(u = 0; u < (max_compact * 2); u++) {
        /* Create attribute */
        sprintf(attrname, "attr %02u", u);
        attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
        CHECK(attr, FAIL, "H5Acreate");

        /* Write data into the attribute */
        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
        CHECK(ret, FAIL, "H5Awrite");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");

        /* Rename attribute */
        sprintf(new_attrname, "new attr %02u", u);

        /* Rename attribute */
        ret = H5Arename2(fid, DSET1_NAME, attrname, new_attrname, H5P_DEFAULT);
        CHECK(ret, FAIL, "H5Arename2");

        /* Check # of attributes */
        attr_count = H5Aget_num_attrs(dataset);
        CHECK(attr_count, FAIL, "H5Aget_num_attrs");
        VERIFY(attr_count, (int)(u + 1), "H5Aget_num_attrs");
    } /* end for */

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");


    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Open dataset */
    dataset = H5Dopen(fid, DSET1_NAME);
    CHECK(dataset, FAIL, "H5Dopen");

    /* Verify renamed attributes */
    for(u = 0; u < (max_compact * 2); u++) {
        unsigned    value;          /* Attribute value */

        /* Create attribute */
        sprintf(attrname, "new attr %02u", u);
        attr = H5Aopen_name(dataset, attrname);
        CHECK(attr, FAIL, "H5Aopen_name");

        /* Read data from the attribute */
        ret = H5Aread(attr, H5T_NATIVE_UINT, &value);
        CHECK(ret, FAIL, "H5Aread");
        VERIFY(value, u, "H5Aread");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");
    } /* end for */

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Unlink dataset with attributes */
    ret = H5Gunlink(fid, DSET1_NAME);
    CHECK(ret, FAIL, "H5Gunlink");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Check size of file */
    filesize = h5_get_file_size(FILENAME);
    VERIFY(filesize, empty_filesize, "h5_get_file_size");
}   /* test_attr_dense_rename() */


/****************************************************************
**
**  test_attr_dense_unlink(): Test basic H5A (attribute) code.
**      Tests unlinking object with attributes in "dense" storage
**
****************************************************************/
static void
test_attr_dense_unlink(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dataset;	/* Dataset ID			*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    unsigned    max_compact;    /* Maximum # of attributes to store compactly */
    unsigned    min_dense;      /* Minimum # of attributes to store "densely" */
    htri_t	is_dense;	/* Are attributes stored densely? */
    int         attr_count;     /* # of attributes */
    size_t      mesg_count;     /* # of shared messages */
    unsigned    u;              /* Local index variable */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Unlinking Object with Attributes in Dense Storage\n"));

    /* Create file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Get size of file */
    empty_filesize = h5_get_file_size(FILENAME);
    if(empty_filesize < 0)
        TestErrPrintf("Line %d: file size wrong!\n", __LINE__);

    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Create dataspace for dataset */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Query the group creation properties */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Create a dataset */
    dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Retrieve limits for compact/dense attribute storage */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

    /* Add attributes, until well into dense storage */
    for(u = 0; u < (max_compact * 2); u++) {
        /* Create attribute */
        sprintf(attrname, "attr %02u", u);
        attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
        CHECK(attr, FAIL, "H5Acreate");

        /* Write data into the attribute */
        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
        CHECK(ret, FAIL, "H5Awrite");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");

        /* Check # of attributes */
        attr_count = H5Aget_num_attrs(dataset);
        CHECK(attr_count, FAIL, "H5Aget_num_attrs");
        VERIFY(attr_count, (int)(u + 1), "H5Aget_num_attrs");
    } /* end for */

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");


    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Unlink dataset */
    ret = H5Gunlink(fid, DSET1_NAME);
    CHECK(ret, FAIL, "H5Gunlink");

    /* Check on dataset's attribute storage status */
    ret = H5F_get_sohm_mesg_count_test(fid, H5O_ATTR_ID, &mesg_count);
    CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
    VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Check size of file */
    filesize = h5_get_file_size(FILENAME);
    VERIFY(filesize, empty_filesize, "h5_get_file_size");
}   /* test_attr_dense_unlink() */


/****************************************************************
**
**  test_attr_dense_limits(): Test basic H5A (attribute) code.
**      Tests attribute in "dense" storage limits
**
****************************************************************/
static void
test_attr_dense_limits(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dataset;	/* Dataset ID			*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    unsigned    max_compact, rmax_compact;      /* Maximum # of attributes to store compactly */
    unsigned    min_dense, rmin_dense;          /* Minimum # of attributes to store "densely" */
    htri_t	is_dense;	/* Are attributes stored densely? */
    unsigned    u;              /* Local index variable */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Phase Change Limits For Attributes in Dense Storage\n"));

    /* Create file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Get size of file */
    empty_filesize = h5_get_file_size(FILENAME);
    if(empty_filesize < 0)
        TestErrPrintf("Line %d: file size wrong!\n", __LINE__);

    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Create dataspace for dataset */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Query the group creation properties */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Change limits on compact/dense attribute storage */
    max_compact = 0;
    min_dense = 0;
    ret = H5Pset_attr_phase_change(dcpl, max_compact, min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Create a dataset */
    dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Retrieve limits for compact/dense attribute storage */
    ret = H5Pget_attr_phase_change(dcpl, &rmax_compact, &rmin_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");
    VERIFY(rmax_compact, max_compact, "H5Pget_attr_phase_change");
    VERIFY(rmin_dense, min_dense, "H5Pget_attr_phase_change");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");


    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");


    /* Add first attribute, which should be immediately in dense storage */

    /* Create attribute */
    u = 0;
    sprintf(attrname, "attr %02u", u);
    attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Write data into the attribute */
    ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
    CHECK(ret, FAIL, "H5Awrite");

    /* Close attribute */
    ret = H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");


    /* Add second attribute, to allow deletions to be checked easily */

    /* Create attribute */
    u = 1;
    sprintf(attrname, "attr %02u", u);
    attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Write data into the attribute */
    ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
    CHECK(ret, FAIL, "H5Awrite");

    /* Close attribute */
    ret = H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");


    /* Delete second attribute, attributes should still be stored densely */

    /* Delete attribute */
    ret = H5Adelete(dataset, attrname);
    CHECK(ret, FAIL, "H5Adelete");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");


    /* Delete first attribute, attributes should not be stored densely */

    /* Delete attribute */
    u = 0;
    sprintf(attrname, "attr %02u", u);
    ret = H5Adelete(dataset, attrname);
    CHECK(ret, FAIL, "H5Adelete");

    /* Check on dataset's attribute storage status */
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");


    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Unlink dataset */
    ret = H5Gunlink(fid, DSET1_NAME);
    CHECK(ret, FAIL, "H5Gunlink");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Check size of file */
    filesize = h5_get_file_size(FILENAME);
    VERIFY(filesize, empty_filesize, "h5_get_file_size");
}   /* test_attr_dense_limits() */


/****************************************************************
**
**  test_attr_big(): Test basic H5A (attribute) code.
**      Tests storing "big" attribute in dense storage immediately, if available
**
****************************************************************/
static void
test_attr_big(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dataset;	/* Dataset ID			*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	big_sid;	/* "Big" dataspace ID		*/
    hsize_t     dims[ATTR6_RANK] = {ATTR6_DIM1, ATTR6_DIM2, ATTR6_DIM3};           /* Attribute dimensions */
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    unsigned    max_compact;    /* Maximum # of attributes to store compactly */
    unsigned    min_dense;      /* Minimum # of attributes to store "densely" */
    unsigned    nshared_indices;        /* # of shared message indices */
    hbool_t     latest_format;  /* Whether we're using the latest version of the format or not */
    htri_t	is_empty;	/* Are there any attributes? */
    htri_t	is_dense;	/* Are attributes stored densely? */
    unsigned    u;              /* Local index variable */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Storing 'Big' Attributes in Dense Storage\n"));

    /* Create file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Get size of file */
    empty_filesize = h5_get_file_size(FILENAME);
    if(empty_filesize < 0)
        TestErrPrintf("Line %d: file size wrong!\n", __LINE__);

    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Create dataspace for dataset & "small" attributes */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create "big" dataspace for "big" attributes */
    big_sid = H5Screate_simple(ATTR6_RANK, dims, NULL);
    CHECK(big_sid, FAIL, "H5Screate_simple");

    /* Query the group creation properties */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Retrieve limits for compact/dense attribute storage */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Retrieve # of shared message indices (ie. whether attributes are shared or not) */
    ret = H5Pget_shared_mesg_nindexes(fcpl, &nshared_indices);
    CHECK(ret, FAIL, "H5Pget_shared_mesg_nindexes");

    /* Retrieve the "use the latest version of the format" flag for creating objects in the file */
    ret = H5Pget_latest_format(fapl, &latest_format);
    CHECK(ret, FAIL, "H5Pget_latest_format");

    /* Create a dataset */
    dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");


    /* Check on dataset's attribute storage status */
    is_empty = H5O_is_attr_empty_test(dataset);
    VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");


    /* Add first "small" attribute, which should be in compact storage */

    /* Create attribute */
    u = 0;
    sprintf(attrname, "attr %02u", u);
    attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Close attribute */
    ret = H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Check on dataset's attribute storage status */
    is_empty = H5O_is_attr_empty_test(dataset);
    VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");


    /* Add second "small" attribute, which should stay in compact storage */

    /* Create attribute */
    u = 1;
    sprintf(attrname, "attr %02u", u);
    attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
    CHECK(attr, FAIL, "H5Acreate");

    /* Close attribute */
    ret = H5Aclose(attr);
    CHECK(ret, FAIL, "H5Aclose");

    /* Check on dataset's attribute storage status */
    is_empty = H5O_is_attr_empty_test(dataset);
    VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");


    /* Add first "big" attribute, which should push storage into dense form */

    /* Create attribute */
    u = 2;
    sprintf(attrname, "attr %02u", u);
    attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, big_sid, H5P_DEFAULT);
    if(latest_format) {
        CHECK(attr, FAIL, "H5Acreate");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");

        /* Check on dataset's attribute storage status */
        /* (when attributes are shared, the "big" attribute goes into the shared
         *  message heap instead of forcing the attribute storage into the dense
         *  form - QAK)
         */
        is_empty = H5O_is_attr_empty_test(dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(dataset);
        VERIFY(is_dense, (nshared_indices ? FALSE : TRUE), "H5O_is_attr_dense_test");


        /* Add second "big" attribute, which should leave storage in dense form */

        /* Create attribute */
        u = 3;
        sprintf(attrname, "attr %02u", u);
        attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, big_sid, H5P_DEFAULT);
        CHECK(attr, FAIL, "H5Acreate");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");

        /* Check on dataset's attribute storage status */
        /* (when attributes are shared, the "big" attribute goes into the shared
         *  message heap instead of forcing the attribute storage into the dense
         *  form - QAK)
         */
        is_empty = H5O_is_attr_empty_test(dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(dataset);
        VERIFY(is_dense, (nshared_indices ? FALSE : TRUE), "H5O_is_attr_dense_test");


        /* Delete second "small" attribute, attributes should still be stored densely */

        /* Delete attribute */
        u = 1;
        sprintf(attrname, "attr %02u", u);
        ret = H5Adelete(dataset, attrname);
        CHECK(ret, FAIL, "H5Adelete");

        /* Check on dataset's attribute storage status */
        is_empty = H5O_is_attr_empty_test(dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(dataset);
        VERIFY(is_dense, (nshared_indices ? FALSE : TRUE), "H5O_is_attr_dense_test");


        /* Delete second "big" attribute, attributes should still be stored densely */

        /* Delete attribute */
        u = 3;
        sprintf(attrname, "attr %02u", u);
        ret = H5Adelete(dataset, attrname);
        CHECK(ret, FAIL, "H5Adelete");

        /* Check on dataset's attribute storage status */
        is_empty = H5O_is_attr_empty_test(dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(dataset);
        VERIFY(is_dense, (nshared_indices ? FALSE : TRUE), "H5O_is_attr_dense_test");


        /* Delete first "big" attribute, attributes should _not_ be stored densely */

        /* Delete attribute */
        u = 2;
        sprintf(attrname, "attr %02u", u);
        ret = H5Adelete(dataset, attrname);
        CHECK(ret, FAIL, "H5Adelete");

        /* Check on dataset's attribute storage status */
        is_empty = H5O_is_attr_empty_test(dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");


        /* Delete first "small" attribute, should be no attributes now */

        /* Delete attribute */
        u = 0;
        sprintf(attrname, "attr %02u", u);
        ret = H5Adelete(dataset, attrname);
        CHECK(ret, FAIL, "H5Adelete");

        /* Check on dataset's attribute storage status */
        is_empty = H5O_is_attr_empty_test(dataset);
        VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
    } /* end if */
    else {
        /* Shouldn't be able to create "big" attributes with older version of format */
        VERIFY(attr, FAIL, "H5Acreate");

        /* Check on dataset's attribute storage status */
        /* (when attributes are shared, the "big" attribute goes into the shared
         *  message heap instead of forcing the attribute storage into the dense
         *  form - QAK)
         */
        is_empty = H5O_is_attr_empty_test(dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
    } /* end else */


    /* Close dataspaces */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");
    ret = H5Sclose(big_sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Unlink dataset */
    ret = H5Gunlink(fid, DSET1_NAME);
    CHECK(ret, FAIL, "H5Gunlink");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Check size of file */
    filesize = h5_get_file_size(FILENAME);
    VERIFY(filesize, empty_filesize, "h5_get_file_size");
}   /* test_attr_dense_limits() */


/****************************************************************
**
**  test_attr_corder_create_empty(): Test basic H5A (attribute) code.
**      Tests basic code to create objects with attribute creation order info
**
****************************************************************/
static void
test_attr_corder_create_basic(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dataset;	/* Dataset ID			*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    unsigned    crt_order_flags;/* Creation order flags */
    htri_t	is_empty;	/* Are there any attributes? */
    htri_t	is_dense;	/* Are attributes stored densely? */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Basic Code for Attributes with Creation Order Info\n"));

    /* Create file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Create dataset creation property list */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Get creation order indexing on object */
    ret = H5Pget_attr_creation_order(dcpl, &crt_order_flags);
    CHECK(ret, FAIL, "H5Pget_attr_creation_order");
    VERIFY(crt_order_flags, 0, "H5Pget_attr_creation_order");

    /* Setting invalid combination of a attribute order creation order indexing on should fail */
    ret = H5Pset_attr_creation_order(dcpl, H5P_CRT_ORDER_INDEXED);
    VERIFY(ret, FAIL, "H5Pset_attr_creation_order");
    ret = H5Pget_attr_creation_order(dcpl, &crt_order_flags);
    CHECK(ret, FAIL, "H5Pget_attr_creation_order");
    VERIFY(crt_order_flags, 0, "H5Pget_attr_creation_order");

    /* Set attribute creation order tracking & indexing for object */
    ret = H5Pset_attr_creation_order(dcpl, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED));
    CHECK(ret, FAIL, "H5Pset_attr_creation_order");
    ret = H5Pget_attr_creation_order(dcpl, &crt_order_flags);
    CHECK(ret, FAIL, "H5Pget_attr_creation_order");
    VERIFY(crt_order_flags, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED) , "H5Pget_attr_creation_order");

    /* Create dataspace for dataset */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create a dataset */
    dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dataset, FAIL, "H5Dcreate");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Check on dataset's attribute storage status */
    is_empty = H5O_is_attr_empty_test(dataset);
    VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");


    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Open dataset created */
    dataset = H5Dopen(fid, DSET1_NAME);
    CHECK(dataset, FAIL, "H5Dopen");

    /* Check on dataset's attribute storage status */
    is_empty = H5O_is_attr_empty_test(dataset);
    VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
    is_dense = H5O_is_attr_dense_test(dataset);
    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

    /* Retrieve dataset creation property list for group */
    dcpl = H5Dget_create_plist(dataset);
    CHECK(dcpl, FAIL, "H5Dget_create_plist");

    /* Query the attribute creation properties */
    ret = H5Pget_attr_creation_order(dcpl, &crt_order_flags);
    CHECK(ret, FAIL, "H5Pget_link_creation_order");
    VERIFY(crt_order_flags, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED) , "H5Pget_attr_creation_order");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close Dataset */
    ret = H5Dclose(dataset);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_corder_create_basic() */


/****************************************************************
**
**  test_attr_corder_create_compact(): Test basic H5A (attribute) code.
**      Tests compact attribute storage on objects with attribute creation order info
**
****************************************************************/
static void
test_attr_corder_create_compact(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dset1, dset2, dset3;	/* Dataset IDs			*/
    hid_t	my_dataset;	/* Current dataset ID		*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    unsigned    max_compact;    /* Maximum # of links to store in group compactly */
    unsigned    min_dense;      /* Minimum # of links to store in group "densely" */
    htri_t	is_empty;	/* Are there any attributes? */
    htri_t	is_dense;	/* Are attributes stored densely? */
    hsize_t     nattrs;         /* Number of attributes on object */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    unsigned    curr_dset;      /* Current dataset to work on */
    unsigned    u;              /* Local index variable */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Compact Storage of Attributes with Creation Order Info\n"));

    /* Create file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Create dataset creation property list */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Set attribute creation order tracking & indexing for object */
    ret = H5Pset_attr_creation_order(dcpl, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED));
    CHECK(ret, FAIL, "H5Pset_attr_creation_order");

    /* Query the attribute creation properties */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Create dataspace for dataset & attributes */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create datasets */
    dset1 = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dset1, FAIL, "H5Dcreate");
    dset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dset2, FAIL, "H5Dcreate");
    dset3 = H5Dcreate(fid, DSET3_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dset3, FAIL, "H5Dcreate");

    /* Work on all the datasets */
    for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
        switch(curr_dset) {
            case 0:
                my_dataset = dset1;
                break;

            case 1:
                my_dataset = dset2;
                break;

            case 2:
                my_dataset = dset3;
                break;

            default:
                HDassert(0 && "Too many datasets!");
        } /* end switch */

        /* Check on dataset's attribute storage status */
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

        /* Create several attributes, but keep storage in compact form */
        for(u = 0; u < max_compact; u++) {
            /* Create attribute */
            sprintf(attrname, "attr %02u", u);
            attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
            CHECK(attr, FAIL, "H5Acreate");

            /* Write data into the attribute */
            ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
            CHECK(ret, FAIL, "H5Awrite");

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Verify state of object */
            ret = H5O_num_attrs_test(my_dataset, &nattrs);
            CHECK(ret, FAIL, "H5O_num_attrs_test");
            VERIFY(nattrs, (u + 1), "H5O_num_attrs_test");
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
        } /* end for */
    } /* end for */

    /* Close Datasets */
    ret = H5Dclose(dset1);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset2);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset3);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");


    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Open datasets created */
    dset1 = H5Dopen(fid, DSET1_NAME);
    CHECK(dset1, FAIL, "H5Dopen");
    dset2 = H5Dopen(fid, DSET2_NAME);
    CHECK(dset2, FAIL, "H5Dopen");
    dset3 = H5Dopen(fid, DSET3_NAME);
    CHECK(dset3, FAIL, "H5Dopen");

    /* Work on all the datasets */
    for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
        switch(curr_dset) {
            case 0:
                my_dataset = dset1;
                break;

            case 1:
                my_dataset = dset2;
                break;

            case 2:
                my_dataset = dset3;
                break;

            default:
                HDassert(0 && "Too many datasets!");
        } /* end switch */

        /* Check on dataset's attribute storage status */
        ret = H5O_num_attrs_test(my_dataset, &nattrs);
        CHECK(ret, FAIL, "H5O_num_attrs_test");
        VERIFY(nattrs, max_compact, "H5O_num_attrs_test");
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

        /* Loop through attributes, checking their creation order values */
        /* (the name index is used, but the creation order value is in the same order) */
        for(u = 0; u < max_compact; u++) {
            H5A_info_t ainfo;           /* Attribute information */

            /* Retrieve information for attribute */
            sprintf(attrname, "attr %02u", u);
            ret = H5Aget_info_by_name(my_dataset, ".", attrname, &ainfo, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Aget_info_by_name");

            /* Verify creation order of attribute */
            VERIFY(ainfo.corder_valid, TRUE, "H5Aget_info_by_name");
            VERIFY(ainfo.corder, u, "H5Aget_info_by_name");
        } /* end for */
    } /* end for */

    /* Close Datasets */
    ret = H5Dclose(dset1);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset2);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset3);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_corder_create_compact() */


/****************************************************************
**
**  test_attr_corder_create_dense(): Test basic H5A (attribute) code.
**      Tests dense attribute storage on objects with attribute creation order info
**
****************************************************************/
static void
test_attr_corder_create_dense(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dset1, dset2, dset3;	/* Dataset IDs			*/
    hid_t	my_dataset;	/* Current dataset ID		*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    unsigned    max_compact;    /* Maximum # of links to store in group compactly */
    unsigned    min_dense;      /* Minimum # of links to store in group "densely" */
    htri_t	is_empty;	/* Are there any attributes? */
    htri_t	is_dense;	/* Are attributes stored densely? */
    hsize_t     nattrs;         /* Number of attributes on object */
    hsize_t     name_count;     /* # of records in name index */
    hsize_t     corder_count;   /* # of records in creation order index */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    unsigned    curr_dset;      /* Current dataset to work on */
    unsigned    u;              /* Local index variable */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Dense Storage of Attributes with Creation Order Info\n"));

    /* Create file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Create dataset creation property list */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Set attribute creation order tracking & indexing for object */
    ret = H5Pset_attr_creation_order(dcpl, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED));
    CHECK(ret, FAIL, "H5Pset_attr_creation_order");

    /* Query the attribute creation properties */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Create dataspace for dataset & attributes */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create datasets */
    dset1 = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dset1, FAIL, "H5Dcreate");
    dset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dset2, FAIL, "H5Dcreate");
    dset3 = H5Dcreate(fid, DSET3_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dset3, FAIL, "H5Dcreate");

    /* Work on all the datasets */
    for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
        switch(curr_dset) {
            case 0:
                my_dataset = dset1;
                break;

            case 1:
                my_dataset = dset2;
                break;

            case 2:
                my_dataset = dset3;
                break;

            default:
                HDassert(0 && "Too many datasets!");
        } /* end switch */

        /* Check on dataset's attribute storage status */
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

        /* Create several attributes, but keep storage in compact form */
        for(u = 0; u < max_compact; u++) {
            /* Create attribute */
            sprintf(attrname, "attr %02u", u);
            attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
            CHECK(attr, FAIL, "H5Acreate");

            /* Write data into the attribute */
            ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
            CHECK(ret, FAIL, "H5Awrite");

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Verify state of object */
            ret = H5O_num_attrs_test(my_dataset, &nattrs);
            CHECK(ret, FAIL, "H5O_num_attrs_test");
            VERIFY(nattrs, (u + 1), "H5O_num_attrs_test");
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
        } /* end for */

        /* Create another attribute, to push into dense storage */
        sprintf(attrname, "attr %02u", max_compact);
        attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
        CHECK(attr, FAIL, "H5Acreate");

        /* Write data into the attribute */
        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
        CHECK(ret, FAIL, "H5Awrite");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");

        /* Verify state of object */
        ret = H5O_num_attrs_test(my_dataset, &nattrs);
        CHECK(ret, FAIL, "H5O_num_attrs_test");
        VERIFY(nattrs, (max_compact + 1), "H5O_num_attrs_test");
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

        /* Retrieve & verify # of records in the name & creation order indices */
        ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
        CHECK(ret, FAIL, "H5O_attr_dense_info_test");
        VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");
    } /* end for */

    /* Close Datasets */
    ret = H5Dclose(dset1);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset2);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset3);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");


    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Open datasets created */
    dset1 = H5Dopen(fid, DSET1_NAME);
    CHECK(dset1, FAIL, "H5Dopen");
    dset2 = H5Dopen(fid, DSET2_NAME);
    CHECK(dset2, FAIL, "H5Dopen");
    dset3 = H5Dopen(fid, DSET3_NAME);
    CHECK(dset3, FAIL, "H5Dopen");

    /* Work on all the datasets */
    for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
        switch(curr_dset) {
            case 0:
                my_dataset = dset1;
                break;

            case 1:
                my_dataset = dset2;
                break;

            case 2:
                my_dataset = dset3;
                break;

            default:
                HDassert(0 && "Too many datasets!");
        } /* end switch */

        /* Check on dataset's attribute storage status */
        ret = H5O_num_attrs_test(my_dataset, &nattrs);
        CHECK(ret, FAIL, "H5O_num_attrs_test");
        VERIFY(nattrs, (max_compact + 1), "H5O_num_attrs_test");
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

        /* Loop through attributes, checking their creation order values */
        /* (the name index is used, but the creation order value is in the same order) */
        for(u = 0; u < (max_compact + 1); u++) {
            H5A_info_t ainfo;           /* Attribute information */

            /* Retrieve information for attribute */
            sprintf(attrname, "attr %02u", u);
            ret = H5Aget_info_by_name(my_dataset, ".", attrname, &ainfo, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Aget_info_by_name");

            /* Verify creation order of attribute */
            VERIFY(ainfo.corder_valid, TRUE, "H5Aget_info_by_name");
            VERIFY(ainfo.corder, u, "H5Aget_info_by_name");
        } /* end for */
    } /* end for */

    /* Close Datasets */
    ret = H5Dclose(dset1);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset2);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset3);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_corder_create_dense() */


/****************************************************************
**
**  test_attr_corder_transition(): Test basic H5A (attribute) code.
**      Tests attribute storage transitions on objects with attribute creation order info
**
****************************************************************/
static void
test_attr_corder_transition(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dset1, dset2, dset3;	/* Dataset IDs			*/
    hid_t	my_dataset;	/* Current dataset ID		*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    unsigned    max_compact;    /* Maximum # of links to store in group compactly */
    unsigned    min_dense;      /* Minimum # of links to store in group "densely" */
    htri_t	is_empty;	/* Are there any attributes? */
    htri_t	is_dense;	/* Are attributes stored densely? */
    hsize_t     nattrs;         /* Number of attributes on object */
    hsize_t     name_count;     /* # of records in name index */
    hsize_t     corder_count;   /* # of records in creation order index */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    unsigned    curr_dset;      /* Current dataset to work on */
    unsigned    u;              /* Local index variable */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Storage Transitions of Attributes with Creation Order Info\n"));

    /* Create file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Create dataset creation property list */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Set attribute creation order tracking & indexing for object */
    ret = H5Pset_attr_creation_order(dcpl, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED));
    CHECK(ret, FAIL, "H5Pset_attr_creation_order");

    /* Query the attribute creation properties */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Create dataspace for dataset & attributes */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

/* XXX: Try to find a way to resize dataset's object header so that the object
 *      header can have one chunk, then retrieve "empty" file size and check
 *      that size after everything is deleted -QAK
 */
    /* Create datasets */
    dset1 = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dset1, FAIL, "H5Dcreate");
    dset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dset2, FAIL, "H5Dcreate");
    dset3 = H5Dcreate(fid, DSET3_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
    CHECK(dset3, FAIL, "H5Dcreate");

    /* Work on all the datasets */
    for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
        switch(curr_dset) {
            case 0:
                my_dataset = dset1;
                break;

            case 1:
                my_dataset = dset2;
                break;

            case 2:
                my_dataset = dset3;
                break;

            default:
                HDassert(0 && "Too many datasets!");
        } /* end switch */

        /* Check on dataset's attribute storage status */
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
    } /* end for */

    /* Close Datasets */
    ret = H5Dclose(dset1);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset2);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset3);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");


    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Open datasets created */
    dset1 = H5Dopen(fid, DSET1_NAME);
    CHECK(dset1, FAIL, "H5Dopen");
    dset2 = H5Dopen(fid, DSET2_NAME);
    CHECK(dset2, FAIL, "H5Dopen");
    dset3 = H5Dopen(fid, DSET3_NAME);
    CHECK(dset3, FAIL, "H5Dopen");

    /* Work on all the datasets */
    for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
        switch(curr_dset) {
            case 0:
                my_dataset = dset1;
                break;

            case 1:
                my_dataset = dset2;
                break;

            case 2:
                my_dataset = dset3;
                break;

            default:
                HDassert(0 && "Too many datasets!");
        } /* end switch */

        /* Create several attributes, but keep storage in compact form */
        for(u = 0; u < max_compact; u++) {
            /* Create attribute */
            sprintf(attrname, "attr %02u", u);
            attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
            CHECK(attr, FAIL, "H5Acreate");

            /* Write data into the attribute */
            ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
            CHECK(ret, FAIL, "H5Awrite");

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Verify state of object */
            ret = H5O_num_attrs_test(my_dataset, &nattrs);
            CHECK(ret, FAIL, "H5O_num_attrs_test");
            VERIFY(nattrs, (u + 1), "H5O_num_attrs_test");
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
        } /* end for */

        /* Create another attribute, to push into dense storage */
        sprintf(attrname, "attr %02u", max_compact);
        attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
        CHECK(attr, FAIL, "H5Acreate");

        /* Write data into the attribute */
        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
        CHECK(ret, FAIL, "H5Awrite");

        /* Close attribute */
        ret = H5Aclose(attr);
        CHECK(ret, FAIL, "H5Aclose");

        /* Verify state of object */
        ret = H5O_num_attrs_test(my_dataset, &nattrs);
        CHECK(ret, FAIL, "H5O_num_attrs_test");
        VERIFY(nattrs, (max_compact + 1), "H5O_num_attrs_test");
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

        /* Retrieve & verify # of records in the name & creation order indices */
        ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
        CHECK(ret, FAIL, "H5O_attr_dense_info_test");
        VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");

        /* Delete several attributes from object, until attribute storage resumes compact form */
        for(u = max_compact; u >= min_dense; u--) {
            sprintf(attrname, "attr %02u", u);
            ret = H5Adelete2(my_dataset, ".", attrname, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Adelete2");

            /* Verify state of object */
            ret = H5O_num_attrs_test(my_dataset, &nattrs);
            CHECK(ret, FAIL, "H5O_num_attrs_test");
            VERIFY(nattrs, u, "H5O_num_attrs_test");
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

            /* Retrieve & verify # of records in the name & creation order indices */
            ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
            CHECK(ret, FAIL, "H5O_attr_dense_info_test");
            VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");
        } /* end for */

        /* Delete another attribute, to push attribute storage into compact form */
        sprintf(attrname, "attr %02u", (min_dense - 1));
        ret = H5Adelete2(my_dataset, ".", attrname, H5P_DEFAULT);
        CHECK(ret, FAIL, "H5Adelete2");

        /* Verify state of object */
        ret = H5O_num_attrs_test(my_dataset, &nattrs);
        CHECK(ret, FAIL, "H5O_num_attrs_test");
        VERIFY(nattrs, (min_dense - 1), "H5O_num_attrs_test");
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

        /* Re-add attributes to get back into dense form */
        for(u = (min_dense - 1); u < (max_compact + 1); u++) {
            /* Create attribute */
            sprintf(attrname, "attr %02u", u);
            attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
            CHECK(attr, FAIL, "H5Acreate");

            /* Write data into the attribute */
            ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
            CHECK(ret, FAIL, "H5Awrite");

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");
        } /* end for */

        /* Verify state of object */
        ret = H5O_num_attrs_test(my_dataset, &nattrs);
        CHECK(ret, FAIL, "H5O_num_attrs_test");
        VERIFY(nattrs, (max_compact + 1), "H5O_num_attrs_test");
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

        /* Retrieve & verify # of records in the name & creation order indices */
        ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
        CHECK(ret, FAIL, "H5O_attr_dense_info_test");
        VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");
    } /* end for */

    /* Close Datasets */
    ret = H5Dclose(dset1);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset2);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset3);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");


    /* Re-open file */
    fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
    CHECK(fid, FAIL, "H5Fopen");

    /* Open datasets created */
    dset1 = H5Dopen(fid, DSET1_NAME);
    CHECK(dset1, FAIL, "H5Dopen");
    dset2 = H5Dopen(fid, DSET2_NAME);
    CHECK(dset2, FAIL, "H5Dopen");
    dset3 = H5Dopen(fid, DSET3_NAME);
    CHECK(dset3, FAIL, "H5Dopen");

    /* Work on all the datasets */
    for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
        switch(curr_dset) {
            case 0:
                my_dataset = dset1;
                break;

            case 1:
                my_dataset = dset2;
                break;

            case 2:
                my_dataset = dset3;
                break;

            default:
                HDassert(0 && "Too many datasets!");
        } /* end switch */

        /* Check on dataset's attribute storage status */
        ret = H5O_num_attrs_test(my_dataset, &nattrs);
        CHECK(ret, FAIL, "H5O_num_attrs_test");
        VERIFY(nattrs, (max_compact + 1), "H5O_num_attrs_test");
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

        /* Retrieve & verify # of records in the name & creation order indices */
        ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
        CHECK(ret, FAIL, "H5O_attr_dense_info_test");
        VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");

        /* Delete several attributes from object, until attribute storage resumes compact form */
        for(u = max_compact; u >= min_dense; u--) {
            sprintf(attrname, "attr %02u", u);
            ret = H5Adelete2(my_dataset, ".", attrname, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Adelete2");

            /* Verify state of object */
            ret = H5O_num_attrs_test(my_dataset, &nattrs);
            CHECK(ret, FAIL, "H5O_num_attrs_test");
            VERIFY(nattrs, u, "H5O_num_attrs_test");
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

            /* Retrieve & verify # of records in the name & creation order indices */
            ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
            CHECK(ret, FAIL, "H5O_attr_dense_info_test");
            VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");
        } /* end for */

        /* Delete another attribute, to push attribute storage into compact form */
        sprintf(attrname, "attr %02u", (min_dense - 1));
        ret = H5Adelete2(my_dataset, ".", attrname, H5P_DEFAULT);
        CHECK(ret, FAIL, "H5Adelete2");

        /* Verify state of object */
        ret = H5O_num_attrs_test(my_dataset, &nattrs);
        CHECK(ret, FAIL, "H5O_num_attrs_test");
        VERIFY(nattrs, (min_dense - 1), "H5O_num_attrs_test");
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

        /* Re-add attributes to get back into dense form */
        for(u = (min_dense - 1); u < (max_compact + 1); u++) {
            /* Create attribute */
            sprintf(attrname, "attr %02u", u);
            attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
            CHECK(attr, FAIL, "H5Acreate");

            /* Write data into the attribute */
            ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
            CHECK(ret, FAIL, "H5Awrite");

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");
        } /* end for */

        /* Verify state of object */
        ret = H5O_num_attrs_test(my_dataset, &nattrs);
        CHECK(ret, FAIL, "H5O_num_attrs_test");
        VERIFY(nattrs, (max_compact + 1), "H5O_num_attrs_test");
        is_empty = H5O_is_attr_empty_test(my_dataset);
        VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
        is_dense = H5O_is_attr_dense_test(my_dataset);
        VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

        /* Retrieve & verify # of records in the name & creation order indices */
        ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
        CHECK(ret, FAIL, "H5O_attr_dense_info_test");
        VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");

        /* Delete all attributes */
        for(u = max_compact; u > 0; u--) {
            sprintf(attrname, "attr %02u", u);
            ret = H5Adelete2(my_dataset, ".", attrname, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Adelete2");
        } /* end for */
        sprintf(attrname, "attr %02u", 0);
        ret = H5Adelete2(my_dataset, ".", attrname, H5P_DEFAULT);
        CHECK(ret, FAIL, "H5Adelete2");
    } /* end for */

    /* Close Datasets */
    ret = H5Dclose(dset1);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset2);
    CHECK(ret, FAIL, "H5Dclose");
    ret = H5Dclose(dset3);
    CHECK(ret, FAIL, "H5Dclose");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");
}   /* test_attr_corder_transition() */


/****************************************************************
**
**  test_attr_corder_delete(): Test basic H5A (attribute) code.
**      Tests deleting object w/dense attribute storage on objects with attribute creation order info
**
****************************************************************/
static void
test_attr_corder_delete(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dset1, dset2, dset3;	/* Dataset IDs			*/
    hid_t	my_dataset;	/* Current dataset ID		*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    unsigned    max_compact;    /* Maximum # of links to store in group compactly */
    unsigned    min_dense;      /* Minimum # of links to store in group "densely" */
    htri_t	is_empty;	/* Are there any attributes? */
    htri_t	is_dense;	/* Are attributes stored densely? */
    hsize_t     nattrs;         /* Number of attributes on object */
    hsize_t     name_count;     /* # of records in name index */
    hsize_t     corder_count;   /* # of records in creation order index */
    hbool_t     reopen_file;            /* Whether to re-open the file before deleting group */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
#ifdef LATER
    h5_stat_size_t empty_size;  /* Size of empty file */
    h5_stat_size_t file_size;   /* Size of file after operating on it */
#endif /* LATER */
    unsigned    curr_dset;      /* Current dataset to work on */
    unsigned    u;              /* Local index variable */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Deleting Object w/Dense Attribute Storage and Creation Order Info\n"));

    /* Create dataspace for dataset & attributes */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create dataset creation property list */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Set attribute creation order tracking & indexing for object */
    ret = H5Pset_attr_creation_order(dcpl, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED));
    CHECK(ret, FAIL, "H5Pset_attr_creation_order");

    /* Query the attribute creation properties */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");


/* XXX: Try to find a way to resize dataset's object header so that the object
 *      header can have one chunk, then retrieve "empty" file size and check
 *      that size after everything is deleted -QAK
 */
#ifdef LATER
    /* Create empty file */
    fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
    CHECK(fid, FAIL, "H5Fcreate");

    /* Close file */
    ret = H5Fclose(fid);
    CHECK(ret, FAIL, "H5Fclose");

    /* Get the size of an empty file */
    empty_size = h5_get_file_size(FILENAME);
    CHECK(empty_size, FAIL, "h5_get_file_size");
#endif /* LATER */


    /* Loop to leave file open when deleting dataset, or to close & re-open file
     *  before deleting dataset */
    for(reopen_file = FALSE; reopen_file <= TRUE; reopen_file++) {
        /* Create test file */
        fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
        CHECK(fid, FAIL, "H5Fopen");

        /* Create datasets */
        dset1 = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dset1, FAIL, "H5Dcreate");
        dset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dset2, FAIL, "H5Dcreate");
        dset3 = H5Dcreate(fid, DSET3_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dset3, FAIL, "H5Dcreate");

        /* Work on all the datasets */
        for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
            switch(curr_dset) {
                case 0:
                    my_dataset = dset1;
                    break;

                case 1:
                    my_dataset = dset2;
                    break;

                case 2:
                    my_dataset = dset3;
                    break;

                default:
                    HDassert(0 && "Too many datasets!");
            } /* end switch */

            /* Check on dataset's attribute storage status */
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

            /* Create attributes, until attribute storage is in dense form */
            for(u = 0; u < max_compact * 2; u++) {
                /* Create attribute */
                sprintf(attrname, "attr %02u", u);
                attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Write data into the attribute */
                ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                CHECK(ret, FAIL, "H5Awrite");

                /* Close attribute */
                ret = H5Aclose(attr);
                CHECK(ret, FAIL, "H5Aclose");
            } /* end for */

            /* Verify state of object */
            ret = H5O_num_attrs_test(my_dataset, &nattrs);
            CHECK(ret, FAIL, "H5O_num_attrs_test");
            VERIFY(nattrs, (max_compact * 2), "H5O_num_attrs_test");
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

            /* Retrieve & verify # of records in the name & creation order indices */
            ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
            CHECK(ret, FAIL, "H5O_attr_dense_info_test");
            VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");
        } /* end for */

        /* Close Datasets */
        ret = H5Dclose(dset1);
        CHECK(ret, FAIL, "H5Dclose");
        ret = H5Dclose(dset2);
        CHECK(ret, FAIL, "H5Dclose");
        ret = H5Dclose(dset3);
        CHECK(ret, FAIL, "H5Dclose");

        /* Check for deleting datasets without re-opening file */
        if(!reopen_file) {
            ret = H5Ldelete(fid, DSET1_NAME, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Ldelete");
            ret = H5Ldelete(fid, DSET2_NAME, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Ldelete");
            ret = H5Ldelete(fid, DSET3_NAME, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Ldelete");
        } /* end if */

        /* Close file */
        ret = H5Fclose(fid);
        CHECK(ret, FAIL, "H5Fclose");

        /* Check for deleting dataset after re-opening file */
        if(reopen_file) {
            /* Re-open file */
            fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
            CHECK(fid, FAIL, "H5Fopen");

            /* Delete the datasets */
            ret = H5Ldelete(fid, DSET1_NAME, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Ldelete");
            ret = H5Ldelete(fid, DSET2_NAME, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Ldelete");
            ret = H5Ldelete(fid, DSET3_NAME, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Ldelete");

            /* Close file */
            ret = H5Fclose(fid);
            CHECK(ret, FAIL, "H5Fclose");
        } /* end if */

#ifdef LATER
        /* Get the size of the file now */
        file_size = h5_get_file_size(FILENAME);
        CHECK(file_size, FAIL, "h5_get_file_size");
        VERIFY(file_size, empty_size, "h5_get_file_size");
#endif /* LATER */
    } /* end for */

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");
}   /* test_attr_corder_delete() */


/*-------------------------------------------------------------------------
 * Function:    attr_info_by_idx_check
 *
 * Purpose:     Support routine for attr_info_by_idx, to verify the attribute
 *              info is correct for a attribute
 *
 * Note:	This routine assumes that the attributes have been added to the
 *              object in alphabetical order.
 *
 * Return:      Success:        0
 *              Failure:        -1
 *
 * Programmer:  Quincey Koziol
 *              Tuesday, Februrary 13, 2007
 *
 *-------------------------------------------------------------------------
 */
static int
attr_info_by_idx_check(hid_t obj_id, const char *attrname, hsize_t n,
    hbool_t use_index)
{
    char tmpname[NAME_BUF_SIZE];        /* Temporary attribute name */
    H5A_info_t  ainfo;                  /* Attribute info struct */
    int         old_nerrs;              /* Number of errors when entering this check */
    herr_t	ret;		        /* Generic return value */

    /* Retrieve the current # of reported errors */
    old_nerrs = GetTestNumErrs();

    /* Verify the information for first attribute, in increasing creation order */
    HDmemset(&ainfo, 0, sizeof(ainfo));
    ret = H5Aget_info_by_idx(obj_id, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, &ainfo, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_info_by_idx");
    VERIFY(ainfo.corder, 0, "H5Aget_info_by_idx");

    /* Verify the information for new attribute, in increasing creation order */
    HDmemset(&ainfo, 0, sizeof(ainfo));
    ret = H5Aget_info_by_idx(obj_id, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, n, &ainfo, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_info_by_idx");
    VERIFY(ainfo.corder, n, "H5Aget_info_by_idx");

    /* Verify the name for new link, in increasing creation order */
    HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE);
    ret = H5Aget_name_by_idx(obj_id, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, n, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_name_by_idx");
    if(HDstrcmp(attrname, tmpname))
        TestErrPrintf("Line %d: attribute name size wrong!\n", __LINE__);


    /* Don't test "native" order if there is no creation order index, since
     *  there's not a good way to easily predict the attribute's order in the name
     *  index.
     */
    if(use_index) {
        /* Verify the information for first attribute, in native creation order */
        HDmemset(&ainfo, 0, sizeof(ainfo));
        ret = H5Aget_info_by_idx(obj_id, ".", H5_INDEX_CRT_ORDER, H5_ITER_NATIVE, (hsize_t)0, &ainfo, H5P_DEFAULT);
        CHECK(ret, FAIL, "H5Aget_info_by_idx");
        VERIFY(ainfo.corder, 0, "H5Aget_info_by_idx");

        /* Verify the information for new attribute, in native creation order */
        HDmemset(&ainfo, 0, sizeof(ainfo));
        ret = H5Aget_info_by_idx(obj_id, ".", H5_INDEX_CRT_ORDER, H5_ITER_NATIVE, n, &ainfo, H5P_DEFAULT);
        CHECK(ret, FAIL, "H5Aget_info_by_idx");
        VERIFY(ainfo.corder, n, "H5Aget_info_by_idx");

        /* Verify the name for new link, in increasing native order */
        HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE);
        ret = H5Aget_name_by_idx(obj_id, ".", H5_INDEX_CRT_ORDER, H5_ITER_NATIVE, n, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
        CHECK(ret, FAIL, "H5Aget_name_by_idx");
        if(HDstrcmp(attrname, tmpname))
            TestErrPrintf("Line %d: attribute name size wrong!\n", __LINE__);
    } /* end if */


    /* Verify the information for first attribute, in decreasing creation order */
    HDmemset(&ainfo, 0, sizeof(ainfo));
    ret = H5Aget_info_by_idx(obj_id, ".", H5_INDEX_CRT_ORDER, H5_ITER_DEC, n, &ainfo, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_info_by_idx");
    VERIFY(ainfo.corder, 0, "H5Aget_info_by_idx");

    /* Verify the information for new attribute, in increasing creation order */
    HDmemset(&ainfo, 0, sizeof(ainfo));
    ret = H5Aget_info_by_idx(obj_id, ".", H5_INDEX_CRT_ORDER, H5_ITER_DEC, (hsize_t)0, &ainfo, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_info_by_idx");
    VERIFY(ainfo.corder, n, "H5Aget_info_by_idx");

    /* Verify the name for new link, in increasing creation order */
    HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE);
    ret = H5Aget_name_by_idx(obj_id, ".", H5_INDEX_CRT_ORDER, H5_ITER_DEC, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_name_by_idx");
    if(HDstrcmp(attrname, tmpname))
        TestErrPrintf("Line %d: attribute name size wrong!\n", __LINE__);


    /* Verify the information for first attribute, in increasing name order */
    HDmemset(&ainfo, 0, sizeof(ainfo));
    ret = H5Aget_info_by_idx(obj_id, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)0, &ainfo, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_info_by_idx");
    VERIFY(ainfo.corder, 0, "H5Aget_info_by_idx");

    /* Verify the information for new attribute, in increasing name order */
    HDmemset(&ainfo, 0, sizeof(ainfo));
    ret = H5Aget_info_by_idx(obj_id, ".", H5_INDEX_NAME, H5_ITER_INC, n, &ainfo, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_info_by_idx");
    VERIFY(ainfo.corder, n, "H5Aget_info_by_idx");

    /* Verify the name for new link, in increasing name order */
    HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE);
    ret = H5Aget_name_by_idx(obj_id, ".", H5_INDEX_NAME, H5_ITER_INC, n, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_name_by_idx");
    if(HDstrcmp(attrname, tmpname))
        TestErrPrintf("Line %d: attribute name size wrong!\n", __LINE__);


    /* Don't test "native" order queries on link name order, since there's not
     *  a good way to easily predict the order of the links in the name index.
     */


    /* Verify the information for first attribute, in decreasing name order */
    HDmemset(&ainfo, 0, sizeof(ainfo));
    ret = H5Aget_info_by_idx(obj_id, ".", H5_INDEX_NAME, H5_ITER_DEC, n, &ainfo, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_info_by_idx");
    VERIFY(ainfo.corder, 0, "H5Aget_info_by_idx");

    /* Verify the information for new attribute, in increasing name order */
    HDmemset(&ainfo, 0, sizeof(ainfo));
    ret = H5Aget_info_by_idx(obj_id, ".", H5_INDEX_NAME, H5_ITER_DEC, (hsize_t)0, &ainfo, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_info_by_idx");
    VERIFY(ainfo.corder, n, "H5Aget_info_by_idx");

    /* Verify the name for new link, in increasing name order */
    HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE);
    ret = H5Aget_name_by_idx(obj_id, ".", H5_INDEX_NAME, H5_ITER_DEC, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aget_name_by_idx");
    if(HDstrcmp(attrname, tmpname))
        TestErrPrintf("Line %d: attribute name size wrong!\n", __LINE__);

    /* Retrieve current # of errors */
    if(old_nerrs == GetTestNumErrs())
        return(0);
    else
        return(-1);
} /* end attr_info_by_idx_check() */


/****************************************************************
**
**  test_attr_info_by_idx(): Test basic H5A (attribute) code.
**      Tests querying attribute info by index
**
****************************************************************/
static void
test_attr_info_by_idx(hbool_t new_format, hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dset1, dset2, dset3;	/* Dataset IDs			*/
    hid_t	my_dataset;	/* Current dataset ID		*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    H5A_info_t  ainfo;          /* Attribute information */
    unsigned    max_compact;    /* Maximum # of links to store in group compactly */
    unsigned    min_dense;      /* Minimum # of links to store in group "densely" */
    htri_t	is_empty;	/* Are there any attributes? */
    htri_t	is_dense;	/* Are attributes stored densely? */
    hsize_t     nattrs;         /* Number of attributes on object */
    hsize_t     name_count;     /* # of records in name index */
    hsize_t     corder_count;   /* # of records in creation order index */
    hbool_t     use_index;      /* Use index on creation order values */
    char	attrname[NAME_BUF_SIZE];    /* Name of attribute */
    char        tmpname[NAME_BUF_SIZE];     /* Temporary attribute name */
    unsigned    curr_dset;      /* Current dataset to work on */
    unsigned    u;              /* Local index variable */
    herr_t	ret;		/* Generic return value		*/

    /* Create dataspace for dataset & attributes */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create dataset creation property list */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Query the attribute creation properties */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Loop over using index for creation order value */
    for(use_index = FALSE; use_index <= TRUE; use_index++) {
        /* Output message about test being performed */
        if(use_index)
            MESSAGE(5, ("Testing Querying Attribute Info By Index w/Creation Order Index\n"))
        else
            MESSAGE(5, ("Testing Querying Attribute Info By Index w/o Creation Order Index\n"))

        /* Create file */
        fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
        CHECK(fid, FAIL, "H5Fcreate");

        /* Set attribute creation order tracking & indexing for object */
        if(new_format == TRUE) {
            ret = H5Pset_attr_creation_order(dcpl, (H5P_CRT_ORDER_TRACKED | (use_index ? H5P_CRT_ORDER_INDEXED : (unsigned)0)));
            CHECK(ret, FAIL, "H5Pset_attr_creation_order");
        } /* end if */

        /* Create datasets */
        dset1 = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dset1, FAIL, "H5Dcreate");
        dset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dset2, FAIL, "H5Dcreate");
        dset3 = H5Dcreate(fid, DSET3_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dset3, FAIL, "H5Dcreate");

        /* Work on all the datasets */
        for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
            switch(curr_dset) {
                case 0:
                    my_dataset = dset1;
                    break;

                case 1:
                    my_dataset = dset2;
                    break;

                case 2:
                    my_dataset = dset3;
                    break;

                default:
                    HDassert(0 && "Too many datasets!");
            } /* end switch */

            /* Check on dataset's attribute storage status */
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

            /* Check for query on non-existant attribute */
            ret = H5Aget_info_by_idx(my_dataset, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, &ainfo, H5P_DEFAULT);
            VERIFY(ret, FAIL, "H5Aget_info_by_idx");
            ret = H5Aget_name_by_idx(my_dataset, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
            VERIFY(ret, FAIL, "H5Aget_name_by_idx");

            /* Create attributes, up to limit of compact form */
            for(u = 0; u < max_compact; u++) {
                /* Create attribute */
                sprintf(attrname, "attr %02u", u);
                attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Write data into the attribute */
                ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                CHECK(ret, FAIL, "H5Awrite");

                /* Close attribute */
                ret = H5Aclose(attr);
                CHECK(ret, FAIL, "H5Aclose");

                /* Verify information for new attribute */
                ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index);
                CHECK(ret, FAIL, "attr_info_by_idx_check");
            } /* end for */

            /* Verify state of object */
            ret = H5O_num_attrs_test(my_dataset, &nattrs);
            CHECK(ret, FAIL, "H5O_num_attrs_test");
            VERIFY(nattrs, max_compact, "H5O_num_attrs_test");
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

            /* Check for out of bound offset queries */
            ret = H5Aget_info_by_idx(my_dataset, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, &ainfo, H5P_DEFAULT);
            VERIFY(ret, FAIL, "H5Aget_info_by_idx");
            ret = H5Aget_info_by_idx(my_dataset, ".", H5_INDEX_CRT_ORDER, H5_ITER_DEC, (hsize_t)u, &ainfo, H5P_DEFAULT);
            VERIFY(ret, FAIL, "H5Aget_info_by_idx");
            ret = H5Aget_name_by_idx(my_dataset, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
            VERIFY(ret, FAIL, "H5Aget_name_by_idx");

            /* Create more attributes, to push into dense form */
            for(; u < (max_compact * 2); u++) {
                /* Create attribute */
                sprintf(attrname, "attr %02u", u);
                attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Write data into the attribute */
                ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                CHECK(ret, FAIL, "H5Awrite");

                /* Close attribute */
                ret = H5Aclose(attr);
                CHECK(ret, FAIL, "H5Aclose");

                /* Verify state of object */
                is_dense = H5O_is_attr_dense_test(my_dataset);
                VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test");

                /* Verify information for new attribute */
                ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index);
                CHECK(ret, FAIL, "attr_info_by_idx_check");
            } /* end for */

            /* Verify state of object */
            ret = H5O_num_attrs_test(my_dataset, &nattrs);
            CHECK(ret, FAIL, "H5O_num_attrs_test");
            VERIFY(nattrs, (max_compact * 2), "H5O_num_attrs_test");
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test");

            if(new_format) {
                /* Retrieve & verify # of records in the name & creation order indices */
                ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
                CHECK(ret, FAIL, "H5O_attr_dense_info_test");
                if(use_index)
                    VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");
                VERIFY(name_count, (max_compact * 2), "H5O_attr_dense_info_test");
            } /* end if */

            /* Check for out of bound offset queries */
            ret = H5Aget_info_by_idx(my_dataset, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, &ainfo, H5P_DEFAULT);
            VERIFY(ret, FAIL, "H5Aget_info_by_idx");
            ret = H5Aget_info_by_idx(my_dataset, ".", H5_INDEX_CRT_ORDER, H5_ITER_DEC, (hsize_t)u, &ainfo, H5P_DEFAULT);
            VERIFY(ret, FAIL, "H5Aget_info_by_idx");
            ret = H5Aget_name_by_idx(my_dataset, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
            VERIFY(ret, FAIL, "H5Aget_name_by_idx");
        } /* end for */

        /* Close Datasets */
        ret = H5Dclose(dset1);
        CHECK(ret, FAIL, "H5Dclose");
        ret = H5Dclose(dset2);
        CHECK(ret, FAIL, "H5Dclose");
        ret = H5Dclose(dset3);
        CHECK(ret, FAIL, "H5Dclose");

        /* Close file */
        ret = H5Fclose(fid);
        CHECK(ret, FAIL, "H5Fclose");
    } /* end for */

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");
}   /* test_attr_info_by_idx() */


/****************************************************************
**
**  test_attr_delete_by_idx(): Test basic H5A (attribute) code.
**      Tests deleting attribute by index
**
****************************************************************/
static void
test_attr_delete_by_idx(hbool_t new_format, hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dset1, dset2, dset3;	/* Dataset IDs			*/
    hid_t	my_dataset;	/* Current dataset ID		*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    H5A_info_t  ainfo;          /* Attribute information */
    unsigned    max_compact;    /* Maximum # of links to store in group compactly */
    unsigned    min_dense;      /* Minimum # of links to store in group "densely" */
    htri_t	is_empty;	/* Are there any attributes? */
    htri_t	is_dense;	/* Are attributes stored densely? */
    hsize_t     nattrs;         /* Number of attributes on object */
    hsize_t     name_count;     /* # of records in name index */
    hsize_t     corder_count;   /* # of records in creation order index */
    H5_index_t idx_type;        /* Type of index to operate on */
    H5_iter_order_t order;      /* Order within in the index */
    hbool_t     use_index;      /* Use index on creation order values */
    char	attrname[NAME_BUF_SIZE];    /* Name of attribute */
    char        tmpname[NAME_BUF_SIZE];     /* Temporary attribute name */
    unsigned    curr_dset;      /* Current dataset to work on */
    unsigned    u;              /* Local index variable */
    herr_t	ret;		/* Generic return value		*/

    /* Create dataspace for dataset & attributes */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create dataset creation property list */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Query the attribute creation properties */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Loop over operating on different indices on link fields */
    for(idx_type = H5_INDEX_NAME; idx_type <=H5_INDEX_CRT_ORDER; idx_type++) {
        /* Loop over operating in different orders */
        for(order = H5_ITER_INC; order <=H5_ITER_DEC; order++) {
            /* Loop over using index for creation order value */
            for(use_index = FALSE; use_index <= TRUE; use_index++) {
                /* Print appropriate test message */
                if(idx_type == H5_INDEX_CRT_ORDER) {
                    if(order == H5_ITER_INC) {
                        if(use_index)
                            MESSAGE(5, ("Testing Deleting Attribute By Creation Order Index in Increasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Deleting Attribute By Creation Order Index in Increasing Order w/o Creation Order Index\n"))
                    } /* end if */
                    else {
                        if(use_index)
                            MESSAGE(5, ("Testing Deleting Attribute By Creation Order Index in Decreasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Deleting Attribute By Creation Order Index in Decreasing Order w/o Creation Order Index\n"))
                    } /* end else */
                } /* end if */
                else {
                    if(order == H5_ITER_INC) {
                        if(use_index)
                            MESSAGE(5, ("Testing Deleting Attribute By Name Index in Increasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Deleting Attribute By Name Index in Increasing Order w/o Creation Order Index\n"))
                    } /* end if */
                    else {
                        if(use_index)
                            MESSAGE(5, ("Testing Deleting Attribute By Name Index in Decreasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Deleting Attribute By Name Index in Decreasing Order w/o Creation Order Index\n"))
                    } /* end else */
                } /* end else */

                /* Create file */
                fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
                CHECK(fid, FAIL, "H5Fcreate");

                /* Set attribute creation order tracking & indexing for object */
                if(new_format == TRUE) {
                    ret = H5Pset_attr_creation_order(dcpl, (H5P_CRT_ORDER_TRACKED | (use_index ? H5P_CRT_ORDER_INDEXED : (unsigned)0)));
                    CHECK(ret, FAIL, "H5Pset_attr_creation_order");
                } /* end if */

                /* Create datasets */
                dset1 = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
                CHECK(dset1, FAIL, "H5Dcreate");
                dset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
                CHECK(dset2, FAIL, "H5Dcreate");
                dset3 = H5Dcreate(fid, DSET3_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
                CHECK(dset3, FAIL, "H5Dcreate");

                /* Work on all the datasets */
                for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
                    switch(curr_dset) {
                        case 0:
                            my_dataset = dset1;
                            break;

                        case 1:
                            my_dataset = dset2;
                            break;

                        case 2:
                            my_dataset = dset3;
                            break;

                        default:
                            HDassert(0 && "Too many datasets!");
                    } /* end switch */

                    /* Check on dataset's attribute storage status */
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
                    is_dense = H5O_is_attr_dense_test(my_dataset);
                    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

                    /* Check for deleting non-existant attribute */
                    ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
                    VERIFY(ret, FAIL, "H5Adelete_by_idx");

                    /* Create attributes, up to limit of compact form */
                    for(u = 0; u < max_compact; u++) {
                        /* Create attribute */
                        sprintf(attrname, "attr %02u", u);
                        attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                        CHECK(attr, FAIL, "H5Acreate");

                        /* Write data into the attribute */
                        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                        CHECK(ret, FAIL, "H5Awrite");

                        /* Close attribute */
                        ret = H5Aclose(attr);
                        CHECK(ret, FAIL, "H5Aclose");

                        /* Verify information for new attribute */
                        ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index);
                        CHECK(ret, FAIL, "attr_info_by_idx_check");
                    } /* end for */

                    /* Verify state of object */
                    ret = H5O_num_attrs_test(my_dataset, &nattrs);
                    CHECK(ret, FAIL, "H5O_num_attrs_test");
                    VERIFY(nattrs, max_compact, "H5O_num_attrs_test");
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
                    is_dense = H5O_is_attr_dense_test(my_dataset);
                    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

                    /* Check for out of bound deletions */
                    ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)u, H5P_DEFAULT);
                    VERIFY(ret, FAIL, "H5Adelete_by_idx");
                } /* end for */

                /* Work on all the datasets */
                for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
                    switch(curr_dset) {
                        case 0:
                            my_dataset = dset1;
                            break;

                        case 1:
                            my_dataset = dset2;
                            break;

                        case 2:
                            my_dataset = dset3;
                            break;

                        default:
                            HDassert(0 && "Too many datasets!");
                    } /* end switch */

                    /* Delete attributes from compact storage */
                    for(u = 0; u < (max_compact - 1); u++) {
                        /* Delete first attribute in appropriate order */
                        ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
                        CHECK(ret, FAIL, "H5Adelete_by_idx");

                        /* Verify the attribute information for first attribute in appropriate order */
                        HDmemset(&ainfo, 0, sizeof(ainfo));
                        ret = H5Aget_info_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, &ainfo, H5P_DEFAULT);
                        if(new_format) {
                            if(order == H5_ITER_INC) {
                                VERIFY(ainfo.corder, (u + 1), "H5Aget_info_by_idx");
                            } /* end if */
                            else {
                                VERIFY(ainfo.corder, (max_compact - (u + 2)), "H5Aget_info_by_idx");
                            } /* end else */
                        } /* end if */

                        /* Verify the name for first attribute in appropriate order */
                        HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE);
                        ret = H5Aget_name_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
                        if(order == H5_ITER_INC)
                            sprintf(attrname, "attr %02u", (u + 1));
                        else
                            sprintf(attrname, "attr %02u", (max_compact - (u + 2)));
                        ret = HDstrcmp(attrname, tmpname);
                        VERIFY(ret, 0, "H5Aget_name_by_idx");
                    } /* end for */

                    /* Delete last attribute */
                    ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
                    CHECK(ret, FAIL, "H5Adelete_by_idx");

                    /* Verify state of attribute storage (empty) */
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
                } /* end for */

                /* Work on all the datasets */
                for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
                    switch(curr_dset) {
                        case 0:
                            my_dataset = dset1;
                            break;

                        case 1:
                            my_dataset = dset2;
                            break;

                        case 2:
                            my_dataset = dset3;
                            break;

                        default:
                            HDassert(0 && "Too many datasets!");
                    } /* end switch */

                    /* Create more attributes, to push into dense form */
                    for(u = 0; u < (max_compact * 2); u++) {
                        /* Create attribute */
                        sprintf(attrname, "attr %02u", u);
                        attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                        CHECK(attr, FAIL, "H5Acreate");

                        /* Write data into the attribute */
                        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                        CHECK(ret, FAIL, "H5Awrite");

                        /* Close attribute */
                        ret = H5Aclose(attr);
                        CHECK(ret, FAIL, "H5Aclose");

                        /* Verify state of object */
                        if(u >= max_compact) {
                            is_dense = H5O_is_attr_dense_test(my_dataset);
                            VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test");
                        } /* end if */

                        /* Verify information for new attribute */
                        ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index);
                        CHECK(ret, FAIL, "attr_info_by_idx_check");
                    } /* end for */

                    /* Verify state of object */
                    ret = H5O_num_attrs_test(my_dataset, &nattrs);
                    CHECK(ret, FAIL, "H5O_num_attrs_test");
                    VERIFY(nattrs, (max_compact * 2), "H5O_num_attrs_test");
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
                    is_dense = H5O_is_attr_dense_test(my_dataset);
                    VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test");

                    if(new_format) {
                        /* Retrieve & verify # of records in the name & creation order indices */
                        ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
                        CHECK(ret, FAIL, "H5O_attr_dense_info_test");
                        if(use_index)
                            VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");
                        VERIFY(name_count, (max_compact * 2), "H5O_attr_dense_info_test");
                    } /* end if */

                    /* Check for out of bound deletion */
                    ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)u, H5P_DEFAULT);
                    VERIFY(ret, FAIL, "H5Adelete_by_idx");
                } /* end for */

                /* Work on all the datasets */
                for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
                    switch(curr_dset) {
                        case 0:
                            my_dataset = dset1;
                            break;

                        case 1:
                            my_dataset = dset2;
                            break;

                        case 2:
                            my_dataset = dset3;
                            break;

                        default:
                            HDassert(0 && "Too many datasets!");
                    } /* end switch */

                    /* Delete attributes from dense storage */
                    for(u = 0; u < ((max_compact * 2) - 1); u++) {
                        /* Delete first attribute in appropriate order */
                        ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
                        CHECK(ret, FAIL, "H5Adelete_by_idx");

                        /* Verify the attribute information for first attribute in appropriate order */
                        HDmemset(&ainfo, 0, sizeof(ainfo));
                        ret = H5Aget_info_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, &ainfo, H5P_DEFAULT);
                        if(new_format) {
                            if(order == H5_ITER_INC) {
                                VERIFY(ainfo.corder, (u + 1), "H5Aget_info_by_idx");
                            } /* end if */
                            else {
                                VERIFY(ainfo.corder, ((max_compact * 2) - (u + 2)), "H5Aget_info_by_idx");
                            } /* end else */
                        } /* end if */

                        /* Verify the name for first attribute in appropriate order */
                        HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE);
                        ret = H5Aget_name_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
                        if(order == H5_ITER_INC)
                            sprintf(attrname, "attr %02u", (u + 1));
                        else
                            sprintf(attrname, "attr %02u", ((max_compact * 2) - (u + 2)));
                        ret = HDstrcmp(attrname, tmpname);
                        VERIFY(ret, 0, "H5Aget_name_by_idx");
                    } /* end for */

                    /* Delete last attribute */
                    ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
                    CHECK(ret, FAIL, "H5Adelete_by_idx");

                    /* Verify state of attribute storage (empty) */
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");

                    /* Check for deletion on empty attribute storage again */
                    ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
                    VERIFY(ret, FAIL, "H5Adelete_by_idx");
                } /* end for */


                    /* Delete attributes in middle */


                /* Work on all the datasets */
                for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
                    switch(curr_dset) {
                        case 0:
                            my_dataset = dset1;
                            break;

                        case 1:
                            my_dataset = dset2;
                            break;

                        case 2:
                            my_dataset = dset3;
                            break;

                        default:
                            HDassert(0 && "Too many datasets!");
                    } /* end switch */

                    /* Create attributes, to push into dense form */
                    for(u = 0; u < (max_compact * 2); u++) {
                        /* Create attribute */
                        sprintf(attrname, "attr %02u", u);
                        attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                        CHECK(attr, FAIL, "H5Acreate");

                        /* Write data into the attribute */
                        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                        CHECK(ret, FAIL, "H5Awrite");

                        /* Close attribute */
                        ret = H5Aclose(attr);
                        CHECK(ret, FAIL, "H5Aclose");

                        /* Verify state of object */
                        if(u >= max_compact) {
                            is_dense = H5O_is_attr_dense_test(my_dataset);
                            VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test");
                        } /* end if */

                        /* Verify information for new attribute */
                        ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index);
                        CHECK(ret, FAIL, "attr_info_by_idx_check");
                    } /* end for */
                } /* end for */

                /* Work on all the datasets */
                for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
                    switch(curr_dset) {
                        case 0:
                            my_dataset = dset1;
                            break;

                        case 1:
                            my_dataset = dset2;
                            break;

                        case 2:
                            my_dataset = dset3;
                            break;

                        default:
                            HDassert(0 && "Too many datasets!");
                    } /* end switch */

                    /* Delete every other attribute from dense storage, in appropriate order */
                    for(u = 0; u < max_compact; u++) {
                        /* Delete attribute */
                        ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)u, H5P_DEFAULT);
                        CHECK(ret, FAIL, "H5Adelete_by_idx");

                        /* Verify the attribute information for first attribute in appropriate order */
                        HDmemset(&ainfo, 0, sizeof(ainfo));
                        ret = H5Aget_info_by_idx(my_dataset, ".", idx_type, order, (hsize_t)u, &ainfo, H5P_DEFAULT);
                        if(new_format) {
                            if(order == H5_ITER_INC) {
                                VERIFY(ainfo.corder, ((u * 2) + 1), "H5Aget_info_by_idx");
                            } /* end if */
                            else {
                                VERIFY(ainfo.corder, ((max_compact * 2) - ((u * 2) + 2)), "H5Aget_info_by_idx");
                            } /* end else */
                        } /* end if */

                        /* Verify the name for first attribute in appropriate order */
                        HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE);
                        ret = H5Aget_name_by_idx(my_dataset, ".", idx_type, order, (hsize_t)u, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
                        if(order == H5_ITER_INC)
                            sprintf(attrname, "attr %02u", ((u * 2) + 1));
                        else
                            sprintf(attrname, "attr %02u", ((max_compact * 2) - ((u * 2) + 2)));
                        ret = HDstrcmp(attrname, tmpname);
                        VERIFY(ret, 0, "H5Aget_name_by_idx");
                    } /* end for */
                } /* end for */

                /* Work on all the datasets */
                for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
                    switch(curr_dset) {
                        case 0:
                            my_dataset = dset1;
                            break;

                        case 1:
                            my_dataset = dset2;
                            break;

                        case 2:
                            my_dataset = dset3;
                            break;

                        default:
                            HDassert(0 && "Too many datasets!");
                    } /* end switch */

                    /* Delete remaining attributes from dense storage, in appropriate order */
                    for(u = 0; u < (max_compact - 1); u++) {
                        /* Delete attribute */
                        ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
                        CHECK(ret, FAIL, "H5Adelete_by_idx");

                        /* Verify the attribute information for first attribute in appropriate order */
                        HDmemset(&ainfo, 0, sizeof(ainfo));
                        ret = H5Aget_info_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, &ainfo, H5P_DEFAULT);
                        if(new_format) {
                            if(order == H5_ITER_INC) {
                                VERIFY(ainfo.corder, ((u * 2) + 3), "H5Aget_info_by_idx");
                            } /* end if */
                            else {
                                VERIFY(ainfo.corder, ((max_compact * 2) - ((u * 2) + 4)), "H5Aget_info_by_idx");
                            } /* end else */
                        } /* end if */

                        /* Verify the name for first attribute in appropriate order */
                        HDmemset(tmpname, 0, (size_t)NAME_BUF_SIZE);
                        ret = H5Aget_name_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, tmpname, (size_t)NAME_BUF_SIZE, H5P_DEFAULT);
                        if(order == H5_ITER_INC)
                            sprintf(attrname, "attr %02u", ((u * 2) + 3));
                        else
                            sprintf(attrname, "attr %02u", ((max_compact * 2) - ((u * 2) + 4)));
                        ret = HDstrcmp(attrname, tmpname);
                        VERIFY(ret, 0, "H5Aget_name_by_idx");
                    } /* end for */

                    /* Delete last attribute */
                    ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
                    CHECK(ret, FAIL, "H5Adelete_by_idx");

                    /* Verify state of attribute storage (empty) */
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");

                    /* Check for deletion on empty attribute storage again */
                    ret = H5Adelete_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT);
                    VERIFY(ret, FAIL, "H5Adelete_by_idx");
                } /* end for */

                /* Close Datasets */
                ret = H5Dclose(dset1);
                CHECK(ret, FAIL, "H5Dclose");
                ret = H5Dclose(dset2);
                CHECK(ret, FAIL, "H5Dclose");
                ret = H5Dclose(dset3);
                CHECK(ret, FAIL, "H5Dclose");

                /* Close file */
                ret = H5Fclose(fid);
                CHECK(ret, FAIL, "H5Fclose");
            } /* end for */
        } /* end for */
    } /* end for */

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");
}   /* test_attr_delete_by_idx() */


/****************************************************************
**
**  attr_iterate2_cb(): Revised attribute operator
**
****************************************************************/
static herr_t
attr_iterate2_cb(hid_t loc_id, const char *attr_name, const H5A_info_t *info,
    void *_op_data)
{
    attr_iter_info_t *op_data = (attr_iter_info_t *)_op_data;   /* User data */
    char attrname[NAME_BUF_SIZE]; /* Object name */
    H5A_info_t my_info;         /* Local attribute info */

#ifdef QAK
HDfprintf(stderr, "attr_name = '%s'\n", attr_name);
if(info)
    HDfprintf(stderr, "info->corder = %u\n", (unsigned)info->corder);
HDfprintf(stderr, "op_data->curr = %Hd\n", op_data->curr);
#endif /* QAK */

    /* Increment # of times the callback was called */
    op_data->ncalled++;

    /* Get the attribute information directly to compare */
    if(H5Aget_info_by_name(loc_id, ".", attr_name, &my_info, H5P_DEFAULT) < 0)
        return(H5_ITER_ERROR);

    /* Check more things for revised attribute iteration (vs. older attribute iteration) */
    if(info) {
        /* Check for correct order of iteration */
        /* (if we are operating in increasing or decreasing order) */
        if(op_data->order != H5_ITER_NATIVE)
            if(info->corder != op_data->curr)
                return(H5_ITER_ERROR);

        /* Compare attribute info structs */
        if(info->corder_valid != my_info.corder_valid)
            return(H5_ITER_ERROR);
        if(info->corder != my_info.corder)
            return(H5_ITER_ERROR);
        if(info->cset != my_info.cset)
            return(H5_ITER_ERROR);
        if(info->data_size != my_info.data_size)
            return(H5_ITER_ERROR);
    } /* end if */

    /* Verify name of link */
    sprintf(attrname, "attr %02u", (unsigned)my_info.corder);
    if(HDstrcmp(attr_name, attrname))
        return(H5_ITER_ERROR);

    /* Check if we've visited this link before */
    if((size_t)op_data->curr >= op_data->max_visit)
        return(H5_ITER_ERROR);
    if(op_data->visited[op_data->curr])
        return(H5_ITER_ERROR);
    op_data->visited[op_data->curr] = TRUE;

    /* Advance to next value, in correct direction */
    if(op_data->order != H5_ITER_DEC)
        op_data->curr++;
    else
        op_data->curr--;

    /* Check for stopping in the middle of iterating */
    if(op_data->stop > 0)
        if(--op_data->stop == 0)
            return(CORDER_ITER_STOP);

    return(H5_ITER_CONT);
} /* end attr_iterate2_cb() */


/****************************************************************
**
**  attr_iterate_cb(): Attribute operator
**
****************************************************************/
static herr_t
attr_iterate_cb(hid_t loc_id, const char *attr_name, void *_op_data)
{
    return(attr_iterate2_cb(loc_id, attr_name, NULL, _op_data));
} /* end attr_iterate_cb() */


/*-------------------------------------------------------------------------
 * Function:    attr_iterate2_fail_cb
 *
 * Purpose:     Callback routine for iterating over attributes on object that
 *              always returns failure
 *
 * Return:      Success:        0
 *              Failure:        -1
 *
 * Programmer:  Quincey Koziol
 *              Tuesday, February 20, 2007
 *
 *-------------------------------------------------------------------------
 */
static int
attr_iterate2_fail_cb(hid_t UNUSED group_id, const char UNUSED *attr_name,
    const H5A_info_t UNUSED *info, void UNUSED *_op_data)
{
    return(H5_ITER_ERROR);
} /* end attr_iterate2_fail_cb() */


/*-------------------------------------------------------------------------
 * Function:    attr_iterate_check
 *
 * Purpose:     Check iteration over attributes on an object
 *
 * Return:      Success:        0
 *              Failure:        -1
 *
 * Programmer:  Quincey Koziol
 *              Tuesday, February 20, 2007
 *
 *-------------------------------------------------------------------------
 */
static int
attr_iterate_check(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
    unsigned max_attrs, attr_iter_info_t *iter_info)
{
    unsigned    v;              /* Local index variable */
    hsize_t     skip;           /* # of attributes to skip on object */
    unsigned    oskip;          /* # of attributes to skip on object, with H5Aiterate */
    int         old_nerrs;      /* Number of errors when entering this check */
    herr_t      ret;            /* Generic return value */

    /* Retrieve the current # of reported errors */
    old_nerrs = GetTestNumErrs();

    /* Iterate over attributes on object */
    iter_info->nskipped = (unsigned)(skip = 0);
    iter_info->order = order;
    iter_info->stop = -1;
    iter_info->ncalled = 0;
    iter_info->curr = order != H5_ITER_DEC ? 0 : (max_attrs - 1);
    HDmemset(iter_info->visited, 0, sizeof(hbool_t) * iter_info->max_visit);
    ret = H5Aiterate2(obj_id, ".", idx_type, order, &skip, attr_iterate2_cb, iter_info, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aiterate2");

    /* Verify that we visited all the attributes */
    VERIFY(skip, max_attrs, "H5Aiterate2");
    for(v = 0; v < max_attrs; v++)
        VERIFY(iter_info->visited[v], TRUE, "H5Aiterate2");


    /* Iterate over attributes on object, with H5Aiterate */
    iter_info->nskipped = oskip = 0;
    iter_info->order = order;
    iter_info->stop = -1;
    iter_info->ncalled = 0;
    iter_info->curr = order != H5_ITER_DEC ? 0 : (max_attrs - 1);
    HDmemset(iter_info->visited, 0, sizeof(hbool_t) * iter_info->max_visit);
    ret = H5Aiterate(obj_id, &oskip, attr_iterate_cb, iter_info);
    CHECK(ret, FAIL, "H5Aiterate");

    /* Verify that we visited all the attributes */
    VERIFY(skip, max_attrs, "H5Aiterate");
    for(v = 0; v < max_attrs; v++)
        VERIFY(iter_info->visited[v], TRUE, "H5Aiterate");


    /* Skip over some attributes on object */
    iter_info->nskipped = (unsigned)(skip = max_attrs / 2);
    iter_info->order = order;
    iter_info->stop = -1;
    iter_info->ncalled = 0;
    iter_info->curr = order != H5_ITER_DEC ? skip : ((max_attrs - 1) - skip);
    HDmemset(iter_info->visited, 0, sizeof(hbool_t) * iter_info->max_visit);
    ret = H5Aiterate2(obj_id, ".", idx_type, order, &skip, attr_iterate2_cb, iter_info, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aiterate2");

    /* Verify that we visited all the attributes */
    VERIFY(skip, max_attrs, "H5Aiterate2");
    if(order == H5_ITER_INC) {
        for(v = 0; v < (max_attrs / 2); v++)
            VERIFY(iter_info->visited[v + (max_attrs / 2)], TRUE, "H5Aiterate2");
    } /* end if */
    else if(order == H5_ITER_DEC) {
        for(v = 0; v < (max_attrs / 2); v++)
            VERIFY(iter_info->visited[v], TRUE, "H5Aiterate2");
    } /* end if */
    else {
        unsigned nvisit = 0;        /* # of links visited */

        HDassert(order == H5_ITER_NATIVE);
        for(v = 0; v < max_attrs; v++)
            if(iter_info->visited[v] == TRUE)
                nvisit++;

        VERIFY(skip, (max_attrs / 2), "H5Aiterate2");
    } /* end else */


    /* Skip over some attributes on object, with H5Aiterate */
    iter_info->nskipped = oskip = max_attrs / 2;
    iter_info->order = order;
    iter_info->stop = -1;
    iter_info->ncalled = 0;
    iter_info->curr = order != H5_ITER_DEC ? (unsigned)oskip : ((max_attrs - 1) - oskip);
    HDmemset(iter_info->visited, 0, sizeof(hbool_t) * iter_info->max_visit);
    ret = H5Aiterate(obj_id, &oskip, attr_iterate_cb, iter_info);
    CHECK(ret, FAIL, "H5Aiterate");

    /* Verify that we visited all the links */
    VERIFY(oskip, max_attrs, "H5Aiterate");
    if(order == H5_ITER_INC) {
        for(v = 0; v < (max_attrs / 2); v++)
            VERIFY(iter_info->visited[v + (max_attrs / 2)], TRUE, "H5Aiterate");
    } /* end if */
    else if(order == H5_ITER_DEC) {
        for(v = 0; v < (max_attrs / 2); v++)
            VERIFY(iter_info->visited[v], TRUE, "H5Aiterate");
    } /* end if */
    else {
        unsigned nvisit = 0;        /* # of links visited */

        HDassert(order == H5_ITER_NATIVE);
        for(v = 0; v < max_attrs; v++)
            if(iter_info->visited[v] == TRUE)
                nvisit++;

        VERIFY(skip, (max_attrs / 2), "H5Aiterate");
    } /* end else */


    /* Iterate over attributes on object, stopping in the middle */
    iter_info->nskipped = (unsigned)(skip = 0);
    iter_info->order = order;
    iter_info->stop = 3;
    iter_info->ncalled = 0;
    iter_info->curr = order != H5_ITER_DEC ? 0 : (max_attrs - 1);
    HDmemset(iter_info->visited, 0, sizeof(hbool_t) * iter_info->max_visit);
    ret = H5Aiterate2(obj_id, ".", idx_type, order, &skip, attr_iterate2_cb, iter_info, H5P_DEFAULT);
    CHECK(ret, FAIL, "H5Aiterate2");
    VERIFY(ret, CORDER_ITER_STOP, "H5Aiterate2");
    VERIFY(iter_info->ncalled, 3, "H5Aiterate2");


    /* Iterate over attributes on object, stopping in the middle, with H5Aiterate() */
    iter_info->nskipped = oskip = 0;
    iter_info->order = order;
    iter_info->stop = 3;
    iter_info->ncalled = 0;
    iter_info->curr = order != H5_ITER_DEC ? 0 : (max_attrs - 1);
    HDmemset(iter_info->visited, 0, sizeof(hbool_t) * iter_info->max_visit);
    ret = H5Aiterate(obj_id, &oskip, attr_iterate_cb, iter_info);
    CHECK(ret, FAIL, "H5Aiterate");
    VERIFY(ret, CORDER_ITER_STOP, "H5Aiterate2");
    VERIFY(iter_info->ncalled, 3, "H5Aiterate2");


    /* Check for iteration routine indicating failure */
    skip = 0;
    ret = H5Aiterate2(obj_id, ".", idx_type, order, &skip, attr_iterate2_fail_cb, NULL, H5P_DEFAULT);
    VERIFY(ret, FAIL, "H5Aiterate2");

    /* Retrieve current # of errors */
    if(old_nerrs == GetTestNumErrs())
        return(0);
    else
        return(-1);
} /* end attr_iterate_check() */


/****************************************************************
**
**  test_attr_iterate2(): Test basic H5A (attribute) code.
**      Tests iterating over attributes by index
**
****************************************************************/
static void
test_attr_iterate2(hbool_t new_format, hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dset1, dset2, dset3;	/* Dataset IDs			*/
    hid_t	my_dataset;	/* Current dataset ID		*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    unsigned    max_compact;    /* Maximum # of links to store in group compactly */
    unsigned    min_dense;      /* Minimum # of links to store in group "densely" */
    htri_t	is_empty;	/* Are there any attributes? */
    htri_t	is_dense;	/* Are attributes stored densely? */
    hsize_t     nattrs;         /* Number of attributes on object */
    hsize_t     name_count;     /* # of records in name index */
    hsize_t     corder_count;   /* # of records in creation order index */
    H5_index_t idx_type;        /* Type of index to operate on */
    H5_iter_order_t order;      /* Order within in the index */
    attr_iter_info_t iter_info; /* Iterator info */
    hbool_t     *visited = NULL;        /* Array of flags for visiting links */
    hsize_t     idx;            /* Start index for iteration */
    hbool_t     use_index;      /* Use index on creation order values */
    char	attrname[NAME_BUF_SIZE];    /* Name of attribute */
    unsigned    curr_dset;      /* Current dataset to work on */
    unsigned    u;              /* Local index variable */
    herr_t	ret;		/* Generic return value		*/

    /* Create dataspace for dataset & attributes */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create dataset creation property list */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Query the attribute creation properties */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Allocate the "visited link" array */
    iter_info.max_visit = max_compact * 2;
    visited = HDmalloc(sizeof(hbool_t) * iter_info.max_visit);
    CHECK(visited, NULL, "HDmalloc");
    iter_info.visited = visited;

    /* Loop over operating on different indices on link fields */
    for(idx_type = H5_INDEX_NAME; idx_type <=H5_INDEX_CRT_ORDER; idx_type++) {
        /* Loop over operating in different orders */
        for(order = H5_ITER_INC; order <=H5_ITER_DEC; order++) {
            /* Loop over using index for creation order value */
            for(use_index = FALSE; use_index <= TRUE; use_index++) {
                /* Print appropriate test message */
                if(idx_type == H5_INDEX_CRT_ORDER) {
                    if(order == H5_ITER_INC) {
                        if(use_index)
                            MESSAGE(5, ("Testing Iterating over Attributes By Creation Order Index in Increasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Iterating over Attributes By Creation Order Index in Increasing Order w/o Creation Order Index\n"))
                    } /* end if */
                    else {
                        if(use_index)
                            MESSAGE(5, ("Testing Iterating over Attributes By Creation Order Index in Decreasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Iterating over Attributes By Creation Order Index in Decreasing Order w/o Creation Order Index\n"))
                    } /* end else */
                } /* end if */
                else {
                    if(order == H5_ITER_INC) {
                        if(use_index)
                            MESSAGE(5, ("Testing Iterating over Attributes By Name Index in Increasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Iterating over Attributes By Name Index in Increasing Order w/o Creation Order Index\n"))
                    } /* end if */
                    else {
                        if(use_index)
                            MESSAGE(5, ("Testing Iterating over Attributes By Name Index in Decreasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Iterating over Attributes By Name Index in Decreasing Order w/o Creation Order Index\n"))
                    } /* end else */
                } /* end else */

                /* Create file */
                fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
                CHECK(fid, FAIL, "H5Fcreate");

                /* Set attribute creation order tracking & indexing for object */
                if(new_format == TRUE) {
                    ret = H5Pset_attr_creation_order(dcpl, (H5P_CRT_ORDER_TRACKED | (use_index ? H5P_CRT_ORDER_INDEXED : (unsigned)0)));
                    CHECK(ret, FAIL, "H5Pset_attr_creation_order");
                } /* end if */

                /* Create datasets */
                dset1 = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
                CHECK(dset1, FAIL, "H5Dcreate");
                dset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
                CHECK(dset2, FAIL, "H5Dcreate");
                dset3 = H5Dcreate(fid, DSET3_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
                CHECK(dset3, FAIL, "H5Dcreate");

                /* Work on all the datasets */
                for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
                    switch(curr_dset) {
                        case 0:
                            my_dataset = dset1;
                            break;

                        case 1:
                            my_dataset = dset2;
                            break;

                        case 2:
                            my_dataset = dset3;
                            break;

                        default:
                            HDassert(0 && "Too many datasets!");
                    } /* end switch */

                    /* Check on dataset's attribute storage status */
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
                    is_dense = H5O_is_attr_dense_test(my_dataset);
                    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

                    /* Check for iterating over object with no attributes (should be OK) */
                    ret = H5Aiterate2(my_dataset, ".", idx_type, order, NULL, attr_iterate2_cb, NULL, H5P_DEFAULT);
                    CHECK(ret, FAIL, "H5Aiterate2");

                    /* Create attributes, up to limit of compact form */
                    for(u = 0; u < max_compact; u++) {
                        /* Create attribute */
                        sprintf(attrname, "attr %02u", u);
                        attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                        CHECK(attr, FAIL, "H5Acreate");

                        /* Write data into the attribute */
                        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                        CHECK(ret, FAIL, "H5Awrite");

                        /* Close attribute */
                        ret = H5Aclose(attr);
                        CHECK(ret, FAIL, "H5Aclose");

                        /* Verify information for new attribute */
                        ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index);
                        CHECK(ret, FAIL, "attr_info_by_idx_check");
                    } /* end for */

                    /* Verify state of object */
                    ret = H5O_num_attrs_test(my_dataset, &nattrs);
                    CHECK(ret, FAIL, "H5O_num_attrs_test");
                    VERIFY(nattrs, max_compact, "H5O_num_attrs_test");
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
                    is_dense = H5O_is_attr_dense_test(my_dataset);
                    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

                    /* Check for out of bound iteration */
                    idx = u;
                    ret = H5Aiterate2(my_dataset, ".", idx_type, order, &idx, attr_iterate2_cb, NULL, H5P_DEFAULT);
                    VERIFY(ret, FAIL, "H5Aiterate2");

                    /* Test iteration over attributes stored compactly */
                    ret = attr_iterate_check(my_dataset, idx_type, order, u, &iter_info);
                    CHECK(ret, FAIL, "attr_iterate_check");
                } /* end for */


                /* Work on all the datasets */
                for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
                    switch(curr_dset) {
                        case 0:
                            my_dataset = dset1;
                            break;

                        case 1:
                            my_dataset = dset2;
                            break;

                        case 2:
                            my_dataset = dset3;
                            break;

                        default:
                            HDassert(0 && "Too many datasets!");
                    } /* end switch */

                    /* Create more attributes, to push into dense form */
                    for(u = max_compact; u < (max_compact * 2); u++) {
                        /* Create attribute */
                        sprintf(attrname, "attr %02u", u);
                        attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                        CHECK(attr, FAIL, "H5Acreate");

                        /* Write data into the attribute */
                        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                        CHECK(ret, FAIL, "H5Awrite");

                        /* Close attribute */
                        ret = H5Aclose(attr);
                        CHECK(ret, FAIL, "H5Aclose");

                        /* Verify state of object */
                        if(u >= max_compact) {
                            is_dense = H5O_is_attr_dense_test(my_dataset);
                            VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test");
                        } /* end if */

                        /* Verify information for new attribute */
                        ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index);
                        CHECK(ret, FAIL, "attr_info_by_idx_check");
                    } /* end for */

                    /* Verify state of object */
                    ret = H5O_num_attrs_test(my_dataset, &nattrs);
                    CHECK(ret, FAIL, "H5O_num_attrs_test");
                    VERIFY(nattrs, (max_compact * 2), "H5O_num_attrs_test");
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
                    is_dense = H5O_is_attr_dense_test(my_dataset);
                    VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test");

                    if(new_format) {
                        /* Retrieve & verify # of records in the name & creation order indices */
                        ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
                        CHECK(ret, FAIL, "H5O_attr_dense_info_test");
                        if(use_index)
                            VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");
                        VERIFY(name_count, (max_compact * 2), "H5O_attr_dense_info_test");
                    } /* end if */

                    /* Check for out of bound iteration */
                    idx = u;
                    ret = H5Aiterate2(my_dataset, ".", idx_type, order, &idx, attr_iterate2_cb, NULL, H5P_DEFAULT);
                    VERIFY(ret, FAIL, "H5Aiterate2");

                    /* Test iteration over attributes stored densely */
                    ret = attr_iterate_check(my_dataset, idx_type, order, u, &iter_info);
                    CHECK(ret, FAIL, "attr_iterate_check");
                } /* end for */

                /* Close Datasets */
                ret = H5Dclose(dset1);
                CHECK(ret, FAIL, "H5Dclose");
                ret = H5Dclose(dset2);
                CHECK(ret, FAIL, "H5Dclose");
                ret = H5Dclose(dset3);
                CHECK(ret, FAIL, "H5Dclose");

                /* Close file */
                ret = H5Fclose(fid);
                CHECK(ret, FAIL, "H5Fclose");
            } /* end for */
        } /* end for */
    } /* end for */

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");

    /* Free the "visited link" array */
    HDfree(visited);
}   /* test_attr_iterate2() */


/*-------------------------------------------------------------------------
 * Function:    attr_open_by_idx_check
 *
 * Purpose:     Check opening attribute by index on an object
 *
 * Return:      Success:        0
 *              Failure:        -1
 *
 * Programmer:  Quincey Koziol
 *              Wednesday, February 21, 2007
 *
 *-------------------------------------------------------------------------
 */
static int
attr_open_by_idx_check(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
    unsigned max_attrs)
{
    hid_t       attr_id;        /* ID of attribute to test */
    H5A_info_t  ainfo;          /* Attribute info */
    int         old_nerrs;      /* Number of errors when entering this check */
    unsigned    u;              /* Local index variable */
    herr_t	ret;		/* Generic return value	*/

    /* Retrieve the current # of reported errors */
    old_nerrs = GetTestNumErrs();

    /* Open each attribute on object by index and check that it's the correct one */
    for(u = 0; u < max_attrs; u++) {
        /* Open the attribute */
        attr_id = H5Aopen_by_idx(obj_id, ".", idx_type, order, (hsize_t)u, H5P_DEFAULT, H5P_DEFAULT);
        CHECK(attr_id, FAIL, "H5Aopen_by_idx");

        /* Get the attribute's information */
        ret = H5Aget_info(attr_id, &ainfo);
        CHECK(ret, FAIL, "H5Aget_info");

        /* Check that the object is the correct one */
        if(order == H5_ITER_INC) {
            VERIFY(ainfo.corder, u, "H5Aget_info");
        } /* end if */
        else if(order == H5_ITER_DEC) {
            VERIFY(ainfo.corder, (max_attrs - (u + 1)), "H5Aget_info");
        } /* end if */
        else {
            /* XXX: What to do about native order? */
        } /* end else */

        /* Close attribute */
        ret = H5Aclose(attr_id);
        CHECK(ret, FAIL, "H5Aclose");
    } /* end for */

    /* Retrieve current # of errors */
    if(old_nerrs == GetTestNumErrs())
        return(0);
    else
        return(-1);
} /* end attr_open_by_idx_check() */


/****************************************************************
**
**  test_attr_open_by_idx(): Test basic H5A (attribute) code.
**      Tests opening attributes by index
**
****************************************************************/
static void
test_attr_open_by_idx(hbool_t new_format, hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dset1, dset2, dset3;	/* Dataset IDs			*/
    hid_t	my_dataset;	/* Current dataset ID		*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    unsigned    max_compact;    /* Maximum # of links to store in group compactly */
    unsigned    min_dense;      /* Minimum # of links to store in group "densely" */
    htri_t	is_empty;	/* Are there any attributes? */
    htri_t	is_dense;	/* Are attributes stored densely? */
    hsize_t     nattrs;         /* Number of attributes on object */
    hsize_t     name_count;     /* # of records in name index */
    hsize_t     corder_count;   /* # of records in creation order index */
    H5_index_t idx_type;        /* Type of index to operate on */
    H5_iter_order_t order;      /* Order within in the index */
    hbool_t     use_index;      /* Use index on creation order values */
    char	attrname[NAME_BUF_SIZE];    /* Name of attribute */
    unsigned    curr_dset;      /* Current dataset to work on */
    unsigned    u;              /* Local index variable */
    herr_t	ret;		/* Generic return value		*/

    /* Create dataspace for dataset & attributes */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create dataset creation property list */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Query the attribute creation properties */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Loop over operating on different indices on link fields */
    for(idx_type = H5_INDEX_NAME; idx_type <=H5_INDEX_CRT_ORDER; idx_type++) {
        /* Loop over operating in different orders */
        for(order = H5_ITER_INC; order <=H5_ITER_DEC; order++) {
            /* Loop over using index for creation order value */
            for(use_index = FALSE; use_index <= TRUE; use_index++) {
                /* Print appropriate test message */
                if(idx_type == H5_INDEX_CRT_ORDER) {
                    if(order == H5_ITER_INC) {
                        if(use_index)
                            MESSAGE(5, ("Testing Opening Attributes By Creation Order Index in Increasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Opening Attributes By Creation Order Index in Increasing Order w/o Creation Order Index\n"))
                    } /* end if */
                    else {
                        if(use_index)
                            MESSAGE(5, ("Testing Opening Attributes By Creation Order Index in Decreasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Opening Attributes By Creation Order Index in Decreasing Order w/o Creation Order Index\n"))
                    } /* end else */
                } /* end if */
                else {
                    if(order == H5_ITER_INC) {
                        if(use_index)
                            MESSAGE(5, ("Testing Opening Attributes By Name Index in Increasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Opening Attributes By Name Index in Increasing Order w/o Creation Order Index\n"))
                    } /* end if */
                    else {
                        if(use_index)
                            MESSAGE(5, ("Testing Opening Attributes By Name Index in Decreasing Order w/Creation Order Index\n"))
                        else
                            MESSAGE(5, ("Testing Opening Attributes By Name Index in Decreasing Order w/o Creation Order Index\n"))
                    } /* end else */
                } /* end else */

                /* Create file */
                fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
                CHECK(fid, FAIL, "H5Fcreate");

                /* Set attribute creation order tracking & indexing for object */
                if(new_format == TRUE) {
                    ret = H5Pset_attr_creation_order(dcpl, (H5P_CRT_ORDER_TRACKED | (use_index ? H5P_CRT_ORDER_INDEXED : (unsigned)0)));
                    CHECK(ret, FAIL, "H5Pset_attr_creation_order");
                } /* end if */

                /* Create datasets */
                dset1 = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
                CHECK(dset1, FAIL, "H5Dcreate");
                dset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
                CHECK(dset2, FAIL, "H5Dcreate");
                dset3 = H5Dcreate(fid, DSET3_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
                CHECK(dset3, FAIL, "H5Dcreate");

                /* Work on all the datasets */
                for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
                    switch(curr_dset) {
                        case 0:
                            my_dataset = dset1;
                            break;

                        case 1:
                            my_dataset = dset2;
                            break;

                        case 2:
                            my_dataset = dset3;
                            break;

                        default:
                            HDassert(0 && "Too many datasets!");
                    } /* end switch */

                    /* Check on dataset's attribute storage status */
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
                    is_dense = H5O_is_attr_dense_test(my_dataset);
                    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

                    /* Check for opening an attribute on an object with no attributes */
                    ret = H5Aopen_by_idx(my_dataset, ".", idx_type, order, (hsize_t)0, H5P_DEFAULT, H5P_DEFAULT);
                    VERIFY(ret, FAIL, "H5Aopen_by_idx");

                    /* Create attributes, up to limit of compact form */
                    for(u = 0; u < max_compact; u++) {
                        /* Create attribute */
                        sprintf(attrname, "attr %02u", u);
                        attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                        CHECK(attr, FAIL, "H5Acreate");

                        /* Write data into the attribute */
                        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                        CHECK(ret, FAIL, "H5Awrite");

                        /* Close attribute */
                        ret = H5Aclose(attr);
                        CHECK(ret, FAIL, "H5Aclose");

                        /* Verify information for new attribute */
                        ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index);
                        CHECK(ret, FAIL, "attr_info_by_idx_check");
                    } /* end for */

                    /* Verify state of object */
                    ret = H5O_num_attrs_test(my_dataset, &nattrs);
                    CHECK(ret, FAIL, "H5O_num_attrs_test");
                    VERIFY(nattrs, max_compact, "H5O_num_attrs_test");
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
                    is_dense = H5O_is_attr_dense_test(my_dataset);
                    VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

                    /* Check for out of bound opening an attribute on an object */
                    ret = H5Aopen_by_idx(my_dataset, ".", idx_type, order, (hsize_t)u, H5P_DEFAULT, H5P_DEFAULT);
                    VERIFY(ret, FAIL, "H5Aopen_by_idx");

                    /* Test opening attributes by index stored compactly */
                    ret = attr_open_by_idx_check(my_dataset, idx_type, order, u);
                    CHECK(ret, FAIL, "attr_open_by_idx_check");
                } /* end for */


                /* Work on all the datasets */
                for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
                    switch(curr_dset) {
                        case 0:
                            my_dataset = dset1;
                            break;

                        case 1:
                            my_dataset = dset2;
                            break;

                        case 2:
                            my_dataset = dset3;
                            break;

                        default:
                            HDassert(0 && "Too many datasets!");
                    } /* end switch */

                    /* Create more attributes, to push into dense form */
                    for(u = max_compact; u < (max_compact * 2); u++) {
                        /* Create attribute */
                        sprintf(attrname, "attr %02u", u);
                        attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                        CHECK(attr, FAIL, "H5Acreate");

                        /* Write data into the attribute */
                        ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                        CHECK(ret, FAIL, "H5Awrite");

                        /* Close attribute */
                        ret = H5Aclose(attr);
                        CHECK(ret, FAIL, "H5Aclose");

                        /* Verify state of object */
                        if(u >= max_compact) {
                            is_dense = H5O_is_attr_dense_test(my_dataset);
                            VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test");
                        } /* end if */

                        /* Verify information for new attribute */
                        ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index);
                        CHECK(ret, FAIL, "attr_info_by_idx_check");
                    } /* end for */

                    /* Verify state of object */
                    ret = H5O_num_attrs_test(my_dataset, &nattrs);
                    CHECK(ret, FAIL, "H5O_num_attrs_test");
                    VERIFY(nattrs, (max_compact * 2), "H5O_num_attrs_test");
                    is_empty = H5O_is_attr_empty_test(my_dataset);
                    VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
                    is_dense = H5O_is_attr_dense_test(my_dataset);
                    VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test");

                    if(new_format) {
                        /* Retrieve & verify # of records in the name & creation order indices */
                        ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
                        CHECK(ret, FAIL, "H5O_attr_dense_info_test");
                        if(use_index)
                            VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");
                        VERIFY(name_count, (max_compact * 2), "H5O_attr_dense_info_test");
                    } /* end if */

                    /* Check for out of bound opening an attribute on an object */
                    ret = H5Aopen_by_idx(my_dataset, ".", idx_type, order, (hsize_t)u, H5P_DEFAULT, H5P_DEFAULT);
                    VERIFY(ret, FAIL, "H5Aopen_by_idx");

                    /* Test opening attributes by index stored compactly */
                    ret = attr_open_by_idx_check(my_dataset, idx_type, order, u);
                    CHECK(ret, FAIL, "attr_open_by_idx_check");
                } /* end for */

                /* Close Datasets */
                ret = H5Dclose(dset1);
                CHECK(ret, FAIL, "H5Dclose");
                ret = H5Dclose(dset2);
                CHECK(ret, FAIL, "H5Dclose");
                ret = H5Dclose(dset3);
                CHECK(ret, FAIL, "H5Dclose");

                /* Close file */
                ret = H5Fclose(fid);
                CHECK(ret, FAIL, "H5Fclose");
            } /* end for */
        } /* end for */
    } /* end for */

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");
}   /* test_attr_open_by_idx() */


/*-------------------------------------------------------------------------
 * Function:    attr_open_check
 *
 * Purpose:     Check opening attribute on an object
 *
 * Return:      Success:        0
 *              Failure:        -1
 *
 * Programmer:  Quincey Koziol
 *              Wednesday, February 21, 2007
 *
 *-------------------------------------------------------------------------
 */
static int
attr_open_check(hid_t obj_id, unsigned max_attrs)
{
    hid_t       attr_id;        /* ID of attribute to test */
    H5A_info_t  ainfo;          /* Attribute info */
    char	attrname[NAME_BUF_SIZE];    /* Name of attribute */
    int         old_nerrs;      /* Number of errors when entering this check */
    unsigned    u;              /* Local index variable */
    herr_t	ret;		/* Generic return value	*/

    /* Retrieve the current # of reported errors */
    old_nerrs = GetTestNumErrs();

    /* Open each attribute on object by index and check that it's the correct one */
    for(u = 0; u < max_attrs; u++) {
        /* Open the attribute */
        sprintf(attrname, "attr %02u", u);
        attr_id = H5Aopen(obj_id, ".", attrname, H5P_DEFAULT, H5P_DEFAULT);
        CHECK(attr_id, FAIL, "H5Aopen");

        /* Get the attribute's information */
        ret = H5Aget_info(attr_id, &ainfo);
        CHECK(ret, FAIL, "H5Aget_info");

        /* Check that the object is the correct one */
        VERIFY(ainfo.corder, u, "H5Aget_info");

        /* Close attribute */
        ret = H5Aclose(attr_id);
        CHECK(ret, FAIL, "H5Aclose");
    } /* end for */

    /* Retrieve current # of errors */
    if(old_nerrs == GetTestNumErrs())
        return(0);
    else
        return(-1);
} /* end attr_open_check() */


/****************************************************************
**
**  test_attr_open(): Test basic H5A (attribute) code.
**      Tests opening attributes by name
**
****************************************************************/
static void
test_attr_open(hbool_t new_format, hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	dset1, dset2, dset3;	/* Dataset IDs			*/
    hid_t	my_dataset;	/* Current dataset ID		*/
    hid_t	sid;	        /* Dataspace ID			*/
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    unsigned    max_compact;    /* Maximum # of links to store in group compactly */
    unsigned    min_dense;      /* Minimum # of links to store in group "densely" */
    htri_t	is_empty;	/* Are there any attributes? */
    htri_t	is_dense;	/* Are attributes stored densely? */
    hsize_t     nattrs;         /* Number of attributes on object */
    hsize_t     name_count;     /* # of records in name index */
    hsize_t     corder_count;   /* # of records in creation order index */
    hbool_t     use_index;      /* Use index on creation order values */
    char	attrname[NAME_BUF_SIZE];    /* Name of attribute */
    unsigned    curr_dset;      /* Current dataset to work on */
    unsigned    u;              /* Local index variable */
    herr_t	ret;		/* Generic return value		*/

    /* Create dataspace for dataset & attributes */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create dataset creation property list */
    dcpl = H5Pcreate(H5P_DATASET_CREATE);
    CHECK(dcpl, FAIL, "H5Pcreate");

    /* Query the attribute creation properties */
    ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
    CHECK(ret, FAIL, "H5Pget_attr_phase_change");

    /* Loop over using index for creation order value */
    for(use_index = FALSE; use_index <= TRUE; use_index++) {
        /* Print appropriate test message */
        if(use_index)
            MESSAGE(5, ("Testing Opening Attributes By Name w/Creation Order Index\n"))
        else
            MESSAGE(5, ("Testing Opening Attributes By Name w/o Creation Order Index\n"))

        /* Create file */
        fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl);
        CHECK(fid, FAIL, "H5Fcreate");

        /* Set attribute creation order tracking & indexing for object */
        if(new_format == TRUE) {
            ret = H5Pset_attr_creation_order(dcpl, (H5P_CRT_ORDER_TRACKED | (use_index ? H5P_CRT_ORDER_INDEXED : (unsigned)0)));
            CHECK(ret, FAIL, "H5Pset_attr_creation_order");
        } /* end if */

        /* Create datasets */
        dset1 = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dset1, FAIL, "H5Dcreate");
        dset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dset2, FAIL, "H5Dcreate");
        dset3 = H5Dcreate(fid, DSET3_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dset3, FAIL, "H5Dcreate");

        /* Work on all the datasets */
        for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
            switch(curr_dset) {
                case 0:
                    my_dataset = dset1;
                    break;

                case 1:
                    my_dataset = dset2;
                    break;

                case 2:
                    my_dataset = dset3;
                    break;

                default:
                    HDassert(0 && "Too many datasets!");
            } /* end switch */

            /* Check on dataset's attribute storage status */
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, TRUE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

            /* Check for opening a non-existant attribute on an object with no attributes */
            ret = H5Aopen(my_dataset, ".", "foo", H5P_DEFAULT, H5P_DEFAULT);
            VERIFY(ret, FAIL, "H5Aopen");

            /* Create attributes, up to limit of compact form */
            for(u = 0; u < max_compact; u++) {
                /* Create attribute */
                sprintf(attrname, "attr %02u", u);
                attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Write data into the attribute */
                ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                CHECK(ret, FAIL, "H5Awrite");

                /* Close attribute */
                ret = H5Aclose(attr);
                CHECK(ret, FAIL, "H5Aclose");

                /* Verify information for new attribute */
                ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index);
                CHECK(ret, FAIL, "attr_info_by_idx_check");
            } /* end for */

            /* Verify state of object */
            ret = H5O_num_attrs_test(my_dataset, &nattrs);
            CHECK(ret, FAIL, "H5O_num_attrs_test");
            VERIFY(nattrs, max_compact, "H5O_num_attrs_test");
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

            /* Check for opening a non-existant attribute on an object with compact attribute storage */
            ret = H5Aopen(my_dataset, ".", "foo", H5P_DEFAULT, H5P_DEFAULT);
            VERIFY(ret, FAIL, "H5Aopen");

            /* Test opening attributes stored compactly */
            ret = attr_open_check(my_dataset, u);
            CHECK(ret, FAIL, "attr_open_check");
        } /* end for */


        /* Work on all the datasets */
        for(curr_dset = 0; curr_dset < NUM_DSETS; curr_dset++) {
            switch(curr_dset) {
                case 0:
                    my_dataset = dset1;
                    break;

                case 1:
                    my_dataset = dset2;
                    break;

                case 2:
                    my_dataset = dset3;
                    break;

                default:
                    HDassert(0 && "Too many datasets!");
            } /* end switch */

            /* Create more attributes, to push into dense form */
            for(u = max_compact; u < (max_compact * 2); u++) {
                /* Create attribute */
                sprintf(attrname, "attr %02u", u);
                attr = H5Acreate(my_dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Write data into the attribute */
                ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
                CHECK(ret, FAIL, "H5Awrite");

                /* Close attribute */
                ret = H5Aclose(attr);
                CHECK(ret, FAIL, "H5Aclose");

                /* Verify state of object */
                if(u >= max_compact) {
                    is_dense = H5O_is_attr_dense_test(my_dataset);
                    VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test");
                } /* end if */

                /* Verify information for new attribute */
                ret = attr_info_by_idx_check(my_dataset, attrname, (hsize_t)u, use_index);
                CHECK(ret, FAIL, "attr_info_by_idx_check");
            } /* end for */

            /* Verify state of object */
            ret = H5O_num_attrs_test(my_dataset, &nattrs);
            CHECK(ret, FAIL, "H5O_num_attrs_test");
            VERIFY(nattrs, (max_compact * 2), "H5O_num_attrs_test");
            is_empty = H5O_is_attr_empty_test(my_dataset);
            VERIFY(is_empty, FALSE, "H5O_is_attr_empty_test");
            is_dense = H5O_is_attr_dense_test(my_dataset);
            VERIFY(is_dense, (new_format ? TRUE : FALSE), "H5O_is_attr_dense_test");

            if(new_format) {
                /* Retrieve & verify # of records in the name & creation order indices */
                ret = H5O_attr_dense_info_test(my_dataset, &name_count, &corder_count);
                CHECK(ret, FAIL, "H5O_attr_dense_info_test");
                if(use_index)
                    VERIFY(name_count, corder_count, "H5O_attr_dense_info_test");
                VERIFY(name_count, (max_compact * 2), "H5O_attr_dense_info_test");
            } /* end if */

            /* Check for opening a non-existant attribute on an object with dense attribute storage */
            ret = H5Aopen(my_dataset, ".", "foo", H5P_DEFAULT, H5P_DEFAULT);
            VERIFY(ret, FAIL, "H5Aopen");

            /* Test opening attributes stored compactly */
            ret = attr_open_check(my_dataset, u);
            CHECK(ret, FAIL, "attr_open_check");
        } /* end for */

        /* Close Datasets */
        ret = H5Dclose(dset1);
        CHECK(ret, FAIL, "H5Dclose");
        ret = H5Dclose(dset2);
        CHECK(ret, FAIL, "H5Dclose");
        ret = H5Dclose(dset3);
        CHECK(ret, FAIL, "H5Dclose");

        /* Close file */
        ret = H5Fclose(fid);
        CHECK(ret, FAIL, "H5Fclose");
    } /* end for */

    /* Close property list */
    ret = H5Pclose(dcpl);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close dataspace */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");
}   /* test_attr_open() */

/****************************************************************
**
**  test_attr_shared_write(): Test basic H5A (attribute) code.
**      Tests writing mix of shared & un-shared attributes in "compact" & "dense" storage
**
****************************************************************/
static void
test_attr_shared_write(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* File ID			*/
    hid_t	my_fcpl;	/* File creation property list ID */
    hid_t	dataset, dataset2;	/* Dataset IDs			*/
    hid_t	attr_tid;	/* Attribute's datatype ID	*/
    hid_t	sid, big_sid;	/* Dataspace IDs		*/
    hsize_t	big_dims[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3};   /* Dimensions for "big" attribute */
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute */
    unsigned    max_compact;    /* Maximum # of attributes to store compactly */
    unsigned    min_dense;      /* Minimum # of attributes to store "densely" */
    htri_t	is_dense;	/* Are attributes stored densely? */
    htri_t	is_shared;	/* Is attributes shared? */
    hsize_t     shared_refcount;        /* Reference count of shared attribute */
    unsigned    attr_value;     /* Attribute value */
    unsigned	big_value[SPACE1_DIM1 * SPACE1_DIM2 * SPACE1_DIM3];   /* Data for "big" attribute */
    size_t      mesg_count;     /* # of shared messages */
    unsigned    test_shared;    /* Index over shared component type */
    unsigned    u;              /* Local index variable */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Writing Shared & Unshared Attributes in Compact & Dense Storage\n"));

    /* Initialize "big" attribute data */
    HDmemset(big_value, 1, sizeof(big_value));

    /* Create dataspace for dataset */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create "big" dataspace for "large" attributes */
    big_sid = H5Screate_simple(SPACE1_RANK, big_dims, NULL);
    CHECK(sid, FAIL, "H5Screate_simple");

    /* Loop over type of shared components */
    for(test_shared = 0; test_shared < 3; test_shared++) {
        /* Make copy of file creation property list */
        my_fcpl = H5Pcopy(fcpl);
        CHECK(my_fcpl, FAIL, "H5Pcopy");

        /* Set up datatype for attributes */
        attr_tid = H5Tcopy(H5T_NATIVE_UINT);
        CHECK(attr_tid, FAIL, "H5Tcopy");

        /* Special setup for each type of shared components */
        if(test_shared == 0) {
            /* Make attributes > 500 bytes shared */
            ret = H5Pset_shared_mesg_nindexes(my_fcpl, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)0, H5O_MESG_ATTR_FLAG, (unsigned)500);
        } /* end if */
        else {
            /* Set up copy of file creation property list */

            ret = H5Pset_shared_mesg_nindexes(my_fcpl, (unsigned)3);
            CHECK_I(ret, "H5Pset_shared_mesg_nindexes");

            /* Make attributes > 500 bytes shared */
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)0, H5O_MESG_ATTR_FLAG, (unsigned)500);

            /* Make datatypes & dataspaces > 1 byte shared (i.e. all of them :-) */
            CHECK_I(ret, "H5Pset_shared_mesg_index");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)1, H5O_MESG_DTYPE_FLAG, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_index");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)2, H5O_MESG_SDSPACE_FLAG, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_index");
        } /* end else */

        /* Create file */
        fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, my_fcpl, fapl);
        CHECK(fid, FAIL, "H5Fcreate");

        /* Close FCPL copy */
        ret = H5Pclose(my_fcpl);
        CHECK(ret, FAIL, "H5Pclose");

        /* Close file */
        ret = H5Fclose(fid);
        CHECK(ret, FAIL, "H5Fclose");

        /* Get size of file */
        empty_filesize = h5_get_file_size(FILENAME);
        if(empty_filesize < 0)
            TestErrPrintf("Line %d: file size wrong!\n", __LINE__);


        /* Re-open file */
        fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
        CHECK(fid, FAIL, "H5Fopen");

        /* Commit datatype to file */
        if(test_shared == 2) {
            ret = H5Tcommit(fid, TYPE1_NAME, attr_tid);
            CHECK(ret, FAIL, "H5Tcommit");
        } /* end if */

        /* Set up to query the object creation properties */
        dcpl = H5Pcreate(H5P_DATASET_CREATE);
        CHECK(dcpl, FAIL, "H5Pcreate");

        /* Create datasets */
        dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dataset, FAIL, "H5Dcreate");
        dataset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dataset2, FAIL, "H5Dcreate");

        /* Check on dataset's message storage status */
        if(test_shared != 0) {
            /* Dataset's datatypes are immutable and shouldn't be shared */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_DTYPE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

            /* Dataset's dataspace can be shared */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_SDSPACE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 1, "H5F_get_sohm_mesg_count_test");
        } /* end if */

        /* Retrieve limits for compact/dense attribute storage */
        ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
        CHECK(ret, FAIL, "H5Pget_attr_phase_change");

        /* Close property list */
        ret = H5Pclose(dcpl);
        CHECK(ret, FAIL, "H5Pclose");

        /* Check on datasets' attribute storage status */
        is_dense = H5O_is_attr_dense_test(dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
        is_dense = H5O_is_attr_dense_test(dataset2);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

        /* Add attributes to each dataset, until after converting to dense storage */
        for(u = 0; u < max_compact * 2; u++) {
            /* Create attribute name */
            sprintf(attrname, "attr %02u", u);

            /* Alternate between creating "small" & "big" attributes */
            if(u % 2) {
                /* Create "small" attribute on first dataset */
                attr = H5Acreate2(dataset, ".", attrname, attr_tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate2");

                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");

                /* Write data into the attribute */
                attr_value = u + 1;
                ret = H5Awrite(attr, attr_tid, &attr_value);
                CHECK(ret, FAIL, "H5Awrite");
            } /* end if */
            else {
                /* Create "big" attribute on first dataset */
                attr = H5Acreate2(dataset, ".", attrname, attr_tid, big_sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate2");

                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");

                /* Write data into the attribute */
                big_value[0] = u + 1;
                ret = H5Awrite(attr, attr_tid, big_value);
                CHECK(ret, FAIL, "H5Awrite");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Check on dataset's attribute storage status */
            is_dense = H5O_is_attr_dense_test(dataset);
            if(u < max_compact)
                VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
            else
                VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");


            /* Alternate between creating "small" & "big" attributes */
            if(u % 2) {
                /* Create "small" attribute on second dataset */
                attr = H5Acreate2(dataset2, ".", attrname, attr_tid, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate2");

                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");

                /* Write data into the attribute */
                attr_value = u + 1;
                ret = H5Awrite(attr, attr_tid, &attr_value);
                CHECK(ret, FAIL, "H5Awrite");
            } /* end if */
            else {
                /* Create "big" attribute on second dataset */
                attr = H5Acreate2(dataset2, ".", attrname, attr_tid, big_sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate2");

                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");

                /* Write data into the attribute */
                big_value[0] = u + 1;
                ret = H5Awrite(attr, attr_tid, big_value);
                CHECK(ret, FAIL, "H5Awrite");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 2, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Check on dataset's attribute storage status */
            is_dense = H5O_is_attr_dense_test(dataset2);
            if(u < max_compact)
                VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
            else
                VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");
        } /* end for */

        /* Close attribute's datatype */
        ret = H5Tclose(attr_tid);
        CHECK(ret, FAIL, "H5Tclose");

        /* Close Datasets */
        ret = H5Dclose(dataset);
        CHECK(ret, FAIL, "H5Dclose");
        ret = H5Dclose(dataset2);
        CHECK(ret, FAIL, "H5Dclose");

        /* Check on shared message status now */
        if(test_shared != 0) {
            if(test_shared == 1) {
                /* Check on datatype storage status */
                ret = H5F_get_sohm_mesg_count_test(fid, H5O_DTYPE_ID, &mesg_count);
                CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
                VERIFY(mesg_count, 1, "H5F_get_sohm_mesg_count_test");
            } /* end if */

            /* Check on dataspace storage status */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_SDSPACE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 2, "H5F_get_sohm_mesg_count_test");
        } /* end if */

        /* Unlink datasets with attributes */
        ret = H5Gunlink(fid, DSET1_NAME);
        CHECK(ret, FAIL, "H5Gunlink");
        ret = H5Gunlink(fid, DSET2_NAME);
        CHECK(ret, FAIL, "H5Gunlink");

        /* Unlink committed datatype */
        if(test_shared == 2) {
            ret = H5Gunlink(fid, TYPE1_NAME);
            CHECK(ret, FAIL, "H5Gunlink");
        } /* end if */

        /* Check on attribute storage status */
        ret = H5F_get_sohm_mesg_count_test(fid, H5O_ATTR_ID, &mesg_count);
        CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
        VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

        if(test_shared != 0) {
            /* Check on datatype storage status */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_DTYPE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

            /* Check on dataspace storage status */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_SDSPACE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");
        } /* end if */

        /* Close file */
        ret = H5Fclose(fid);
        CHECK(ret, FAIL, "H5Fclose");

        /* Check size of file */
        filesize = h5_get_file_size(FILENAME);
        VERIFY(filesize, empty_filesize, "h5_get_file_size");
    } /* end for */

    /* Close dataspaces */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");
    ret = H5Sclose(big_sid);
    CHECK(ret, FAIL, "H5Sclose");
}   /* test_attr_shared_write() */

/****************************************************************
**
**  test_attr_shared_rename(): Test basic H5A (attribute) code.
**      Tests renaming shared attributes in "compact" & "dense" storage
**
****************************************************************/
static void
test_attr_shared_rename(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* HDF5 File ID			*/
    hid_t	my_fcpl;	/* File creation property list ID */
    hid_t	dataset, dataset2;	/* Dataset ID2			*/
    hid_t	attr_tid;	/* Attribute's datatype ID	*/
    hid_t	sid, big_sid;	/* Dataspace IDs		*/
    hsize_t	big_dims[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3};   /* Dimensions for "big" attribute */
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute on first dataset */
    char	attrname2[NAME_BUF_SIZE];       /* Name of attribute on second dataset */
    unsigned    max_compact;    /* Maximum # of attributes to store compactly */
    unsigned    min_dense;      /* Minimum # of attributes to store "densely" */
    htri_t	is_dense;	/* Are attributes stored densely? */
    htri_t	is_shared;	/* Is attributes shared? */
    hsize_t     shared_refcount;        /* Reference count of shared attribute */
    unsigned    attr_value;     /* Attribute value */
    unsigned	big_value[SPACE1_DIM1 * SPACE1_DIM2 * SPACE1_DIM3];   /* Data for "big" attribute */
    size_t      mesg_count;     /* # of shared messages */
    unsigned    test_shared;    /* Index over shared component type */
    unsigned    u;              /* Local index variable */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Renaming Shared & Unshared Attributes in Compact & Dense Storage\n"));

    /* Initialize "big" attribute data */
    HDmemset(big_value, 1, sizeof(big_value));

    /* Create dataspace for dataset */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create "big" dataspace for "large" attributes */
    big_sid = H5Screate_simple(SPACE1_RANK, big_dims, NULL);
    CHECK(sid, FAIL, "H5Screate_simple");

    /* Loop over type of shared components */
    for(test_shared = 0; test_shared < 3; test_shared++) {
        /* Make copy of file creation property list */
        my_fcpl = H5Pcopy(fcpl);
        CHECK(my_fcpl, FAIL, "H5Pcopy");

        /* Set up datatype for attributes */
        attr_tid = H5Tcopy(H5T_NATIVE_UINT);
        CHECK(attr_tid, FAIL, "H5Tcopy");

        /* Special setup for each type of shared components */
        if(test_shared == 0) {
            /* Make attributes > 500 bytes shared */
            ret = H5Pset_shared_mesg_nindexes(my_fcpl, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)0, H5O_MESG_ATTR_FLAG, (unsigned)500);
        } /* end if */
        else {
            /* Set up copy of file creation property list */

            ret = H5Pset_shared_mesg_nindexes(my_fcpl, (unsigned)3);
            CHECK_I(ret, "H5Pset_shared_mesg_nindexes");

            /* Make attributes > 500 bytes shared */
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)0, H5O_MESG_ATTR_FLAG, (unsigned)500);

            /* Make datatypes & dataspaces > 1 byte shared (i.e. all of them :-) */
            CHECK_I(ret, "H5Pset_shared_mesg_index");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)1, H5O_MESG_DTYPE_FLAG, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_index");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)2, H5O_MESG_SDSPACE_FLAG, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_index");
        } /* end else */

        /* Create file */
        fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, my_fcpl, fapl);
        CHECK(fid, FAIL, "H5Fcreate");

        /* Close FCPL copy */
        ret = H5Pclose(my_fcpl);
        CHECK(ret, FAIL, "H5Pclose");

        /* Close file */
        ret = H5Fclose(fid);
        CHECK(ret, FAIL, "H5Fclose");

        /* Get size of file */
        empty_filesize = h5_get_file_size(FILENAME);
        if(empty_filesize < 0)
            TestErrPrintf("Line %d: file size wrong!\n", __LINE__);


        /* Re-open file */
        fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
        CHECK(fid, FAIL, "H5Fopen");

        /* Commit datatype to file */
        if(test_shared == 2) {
            ret = H5Tcommit(fid, TYPE1_NAME, attr_tid);
            CHECK(ret, FAIL, "H5Tcommit");
        } /* end if */

        /* Set up to query the object creation properties */
        dcpl = H5Pcreate(H5P_DATASET_CREATE);
        CHECK(dcpl, FAIL, "H5Pcreate");

        /* Create datasets */
        dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dataset, FAIL, "H5Dcreate");
        dataset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dataset2, FAIL, "H5Dcreate");

        /* Check on dataset's message storage status */
        if(test_shared != 0) {
            /* Dataset's datatypes are immutable and shouldn't be shared */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_DTYPE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

            /* Dataset's dataspace can be shared */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_SDSPACE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 1, "H5F_get_sohm_mesg_count_test");
        } /* end if */

        /* Retrieve limits for compact/dense attribute storage */
        ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
        CHECK(ret, FAIL, "H5Pget_attr_phase_change");

        /* Close property list */
        ret = H5Pclose(dcpl);
        CHECK(ret, FAIL, "H5Pclose");

        /* Check on datasets' attribute storage status */
        is_dense = H5O_is_attr_dense_test(dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
        is_dense = H5O_is_attr_dense_test(dataset2);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

        /* Add attributes to each dataset, until after converting to dense storage */
        for(u = 0; u < max_compact * 2; u++) {
            /* Create attribute name */
            sprintf(attrname, "attr %02u", u);

            /* Alternate between creating "small" & "big" attributes */
            if(u % 2) {
                /* Create "small" attribute on first dataset */
                attr = H5Acreate(dataset, attrname, attr_tid, sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");

                /* Write data into the attribute */
                attr_value = u + 1;
                ret = H5Awrite(attr, attr_tid, &attr_value);
                CHECK(ret, FAIL, "H5Awrite");
            } /* end if */
            else {
                /* Create "big" attribute on first dataset */
                attr = H5Acreate(dataset, attrname, attr_tid, big_sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");

                /* Write data into the attribute */
                big_value[0] = u + 1;
                ret = H5Awrite(attr, attr_tid, big_value);
                CHECK(ret, FAIL, "H5Awrite");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Check on dataset's attribute storage status */
            is_dense = H5O_is_attr_dense_test(dataset);
            if(u < max_compact)
                VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
            else
                VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");


            /* Alternate between creating "small" & "big" attributes */
            if(u % 2) {
                /* Create "small" attribute on second dataset */
                attr = H5Acreate(dataset2, attrname, attr_tid, sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");

                /* Write data into the attribute */
                attr_value = u + 1;
                ret = H5Awrite(attr, attr_tid, &attr_value);
                CHECK(ret, FAIL, "H5Awrite");
            } /* end if */
            else {
                /* Create "big" attribute on second dataset */
                attr = H5Acreate(dataset2, attrname, attr_tid, big_sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");

                /* Write data into the attribute */
                big_value[0] = u + 1;
                ret = H5Awrite(attr, attr_tid, big_value);
                CHECK(ret, FAIL, "H5Awrite");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 2, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Check on dataset's attribute storage status */
            is_dense = H5O_is_attr_dense_test(dataset2);
            if(u < max_compact)
                VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
            else
                VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");


            /* Create new attribute name */
            sprintf(attrname2, "new attr %02u", u);

            /* Change second dataset's attribute's name */
            ret = H5Arename2(fid, DSET2_NAME, attrname, attrname2, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Arename2");


            /* Check refcount on attributes now */

            /* Check refcount on renamed attribute */
            attr = H5Aopen_name(dataset2, attrname2);
            CHECK(attr, FAIL, "H5Aopen_name");

            if(u % 2) {
                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");
            } /* end if */
            else {
                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Check refcount on original attribute */
            attr = H5Aopen_name(dataset, attrname);
            CHECK(attr, FAIL, "H5Aopen_name");

            if(u % 2) {
                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");
            } /* end if */
            else {
                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");


            /* Change second dataset's attribute's name back to original */
            ret = H5Arename2(fid, DSET2_NAME, attrname2, attrname, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Arename2");


            /* Check refcount on attributes now */

            /* Check refcount on renamed attribute */
            attr = H5Aopen_name(dataset2, attrname);
            CHECK(attr, FAIL, "H5Aopen_name");

            if(u % 2) {
                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");
            } /* end if */
            else {
                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 2, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Check refcount on original attribute */
            attr = H5Aopen_name(dataset, attrname);
            CHECK(attr, FAIL, "H5Aopen_name");

            if(u % 2) {
                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");
            } /* end if */
            else {
                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 2, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");
        } /* end for */


        /* Close attribute's datatype */
        ret = H5Tclose(attr_tid);
        CHECK(ret, FAIL, "H5Tclose");

        /* Close Datasets */
        ret = H5Dclose(dataset);
        CHECK(ret, FAIL, "H5Dclose");
        ret = H5Dclose(dataset2);
        CHECK(ret, FAIL, "H5Dclose");

        /* Check on shared message status now */
        if(test_shared != 0) {
            if(test_shared == 1) {
                /* Check on datatype storage status */
                ret = H5F_get_sohm_mesg_count_test(fid, H5O_DTYPE_ID, &mesg_count);
                CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
                VERIFY(mesg_count, 1, "H5F_get_sohm_mesg_count_test");
            } /* end if */

            /* Check on dataspace storage status */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_SDSPACE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 2, "H5F_get_sohm_mesg_count_test");
        } /* end if */

        /* Unlink datasets with attributes */
        ret = H5Gunlink(fid, DSET1_NAME);
        CHECK(ret, FAIL, "H5Gunlink");
        ret = H5Gunlink(fid, DSET2_NAME);
        CHECK(ret, FAIL, "H5Gunlink");

        /* Unlink committed datatype */
        if(test_shared == 2) {
            ret = H5Gunlink(fid, TYPE1_NAME);
            CHECK(ret, FAIL, "H5Gunlink");
        } /* end if */

        /* Check on attribute storage status */
        ret = H5F_get_sohm_mesg_count_test(fid, H5O_ATTR_ID, &mesg_count);
        CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
        VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

        if(test_shared != 0) {
            /* Check on datatype storage status */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_DTYPE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

            /* Check on dataspace storage status */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_SDSPACE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");
        } /* end if */

        /* Close file */
        ret = H5Fclose(fid);
        CHECK(ret, FAIL, "H5Fclose");

        /* Check size of file */
        filesize = h5_get_file_size(FILENAME);
        VERIFY(filesize, empty_filesize, "h5_get_file_size");
    } /* end for */

    /* Close dataspaces */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");
    ret = H5Sclose(big_sid);
    CHECK(ret, FAIL, "H5Sclose");
}   /* test_attr_shared_rename() */

/****************************************************************
**
**  test_attr_shared_delete(): Test basic H5A (attribute) code.
**      Tests deleting shared attributes in "compact" & "dense" storage
**
****************************************************************/
static void
test_attr_shared_delete(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* File ID			*/
    hid_t	my_fcpl;	/* File creation property list ID */
    hid_t	dataset, dataset2;	/* Dataset IDs			*/
    hid_t	attr_tid;	/* Attribute's datatype ID	*/
    hid_t	sid, big_sid;	/* Dataspace IDs		*/
    hsize_t	big_dims[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3};   /* Dimensions for "big" attribute */
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute on first dataset */
    unsigned    max_compact;    /* Maximum # of attributes to store compactly */
    unsigned    min_dense;      /* Minimum # of attributes to store "densely" */
    htri_t	is_dense;	/* Are attributes stored densely? */
    htri_t	is_shared;	/* Is attributes shared? */
    hsize_t     shared_refcount;        /* Reference count of shared attribute */
    unsigned    attr_value;     /* Attribute value */
    unsigned	big_value[SPACE1_DIM1 * SPACE1_DIM2 * SPACE1_DIM3];   /* Data for "big" attribute */
    size_t      mesg_count;     /* # of shared messages */
    unsigned    test_shared;    /* Index over shared component type */
    unsigned    u;              /* Local index variable */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Deleting Shared & Unshared Attributes in Compact & Dense Storage\n"));

    /* Initialize "big" attribute data */
    HDmemset(big_value, 1, sizeof(big_value));

    /* Create dataspace for dataset */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create "big" dataspace for "large" attributes */
    big_sid = H5Screate_simple(SPACE1_RANK, big_dims, NULL);
    CHECK(sid, FAIL, "H5Screate_simple");

    /* Loop over type of shared components */
    for(test_shared = 0; test_shared < 3; test_shared++) {
        /* Make copy of file creation property list */
        my_fcpl = H5Pcopy(fcpl);
        CHECK(my_fcpl, FAIL, "H5Pcopy");

        /* Set up datatype for attributes */
        attr_tid = H5Tcopy(H5T_NATIVE_UINT);
        CHECK(attr_tid, FAIL, "H5Tcopy");

        /* Special setup for each type of shared components */
        if(test_shared == 0) {
            /* Make attributes > 500 bytes shared */
            ret = H5Pset_shared_mesg_nindexes(my_fcpl, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)0, H5O_MESG_ATTR_FLAG, (unsigned)500);
        } /* end if */
        else {
            /* Set up copy of file creation property list */

            ret = H5Pset_shared_mesg_nindexes(my_fcpl, (unsigned)3);
            CHECK_I(ret, "H5Pset_shared_mesg_nindexes");

            /* Make attributes > 500 bytes shared */
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)0, H5O_MESG_ATTR_FLAG, (unsigned)500);

            /* Make datatypes & dataspaces > 1 byte shared (i.e. all of them :-) */
            CHECK_I(ret, "H5Pset_shared_mesg_index");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)1, H5O_MESG_DTYPE_FLAG, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_index");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)2, H5O_MESG_SDSPACE_FLAG, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_index");
        } /* end else */

        /* Create file */
        fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, my_fcpl, fapl);
        CHECK(fid, FAIL, "H5Fcreate");

        /* Close FCPL copy */
        ret = H5Pclose(my_fcpl);
        CHECK(ret, FAIL, "H5Pclose");

        /* Close file */
        ret = H5Fclose(fid);
        CHECK(ret, FAIL, "H5Fclose");

        /* Get size of file */
        empty_filesize = h5_get_file_size(FILENAME);
        if(empty_filesize < 0)
            TestErrPrintf("Line %d: file size wrong!\n", __LINE__);


        /* Re-open file */
        fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
        CHECK(fid, FAIL, "H5Fopen");

        /* Commit datatype to file */
        if(test_shared == 2) {
            ret = H5Tcommit(fid, TYPE1_NAME, attr_tid);
            CHECK(ret, FAIL, "H5Tcommit");
        } /* end if */

        /* Set up to query the object creation properties */
        dcpl = H5Pcreate(H5P_DATASET_CREATE);
        CHECK(dcpl, FAIL, "H5Pcreate");

        /* Create datasets */
        dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dataset, FAIL, "H5Dcreate");
        dataset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dataset2, FAIL, "H5Dcreate");

        /* Check on dataset's message storage status */
        if(test_shared != 0) {
            /* Dataset's datatypes are immutable and shouldn't be shared */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_DTYPE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

            /* Dataset's dataspace can be shared */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_SDSPACE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 1, "H5F_get_sohm_mesg_count_test");
        } /* end if */

        /* Retrieve limits for compact/dense attribute storage */
        ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
        CHECK(ret, FAIL, "H5Pget_attr_phase_change");

        /* Close property list */
        ret = H5Pclose(dcpl);
        CHECK(ret, FAIL, "H5Pclose");

        /* Check on datasets' attribute storage status */
        is_dense = H5O_is_attr_dense_test(dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
        is_dense = H5O_is_attr_dense_test(dataset2);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

        /* Add attributes to each dataset, until after converting to dense storage */
        for(u = 0; u < max_compact * 2; u++) {
            /* Create attribute name */
            sprintf(attrname, "attr %02u", u);

            /* Alternate between creating "small" & "big" attributes */
            if(u % 2) {
                /* Create "small" attribute on first dataset */
                attr = H5Acreate(dataset, attrname, attr_tid, sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");

                /* Write data into the attribute */
                attr_value = u + 1;
                ret = H5Awrite(attr, attr_tid, &attr_value);
                CHECK(ret, FAIL, "H5Awrite");
            } /* end if */
            else {
                /* Create "big" attribute on first dataset */
                attr = H5Acreate(dataset, attrname, attr_tid, big_sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");

                /* Write data into the attribute */
                big_value[0] = u + 1;
                ret = H5Awrite(attr, attr_tid, big_value);
                CHECK(ret, FAIL, "H5Awrite");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Check on dataset's attribute storage status */
            is_dense = H5O_is_attr_dense_test(dataset);
            if(u < max_compact)
                VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
            else
                VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");


            /* Alternate between creating "small" & "big" attributes */
            if(u % 2) {
                /* Create "small" attribute on second dataset */
                attr = H5Acreate(dataset2, attrname, attr_tid, sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");

                /* Write data into the attribute */
                attr_value = u + 1;
                ret = H5Awrite(attr, attr_tid, &attr_value);
                CHECK(ret, FAIL, "H5Awrite");
            } /* end if */
            else {
                /* Create "big" attribute on second dataset */
                attr = H5Acreate(dataset2, attrname, attr_tid, big_sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");

                /* Write data into the attribute */
                big_value[0] = u + 1;
                ret = H5Awrite(attr, attr_tid, big_value);
                CHECK(ret, FAIL, "H5Awrite");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 2, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Check on dataset's attribute storage status */
            is_dense = H5O_is_attr_dense_test(dataset2);
            if(u < max_compact)
                VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
            else
                VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");
        } /* end for */


        /* Delete attributes from second dataset */
        for(u = 0; u < max_compact * 2; u++) {
            /* Create attribute name */
            sprintf(attrname, "attr %02u", u);

            /* Delete second dataset's attribute */
            ret = H5Adelete2(fid, DSET2_NAME, attrname, H5P_DEFAULT);
            CHECK(ret, FAIL, "H5Adelete2");


            /* Check refcount on attributes now */

            /* Check refcount on first dataset's attribute */
            attr = H5Aopen_name(dataset, attrname);
            CHECK(attr, FAIL, "H5Aopen_name");

            if(u % 2) {
                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");
            } /* end if */
            else {
                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");
        } /* end for */


        /* Close attribute's datatype */
        ret = H5Tclose(attr_tid);
        CHECK(ret, FAIL, "H5Tclose");

        /* Close Datasets */
        ret = H5Dclose(dataset);
        CHECK(ret, FAIL, "H5Dclose");
        ret = H5Dclose(dataset2);
        CHECK(ret, FAIL, "H5Dclose");

        /* Check on shared message status now */
        if(test_shared != 0) {
            if(test_shared == 1) {
                /* Check on datatype storage status */
                ret = H5F_get_sohm_mesg_count_test(fid, H5O_DTYPE_ID, &mesg_count);
                CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
                VERIFY(mesg_count, 1, "H5F_get_sohm_mesg_count_test");
            } /* end if */

            /* Check on dataspace storage status */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_SDSPACE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 2, "H5F_get_sohm_mesg_count_test");
        } /* end if */

        /* Unlink datasets with attributes */
        ret = H5Gunlink(fid, DSET1_NAME);
        CHECK(ret, FAIL, "H5Gunlink");
        ret = H5Gunlink(fid, DSET2_NAME);
        CHECK(ret, FAIL, "H5Gunlink");

        /* Unlink committed datatype */
        if(test_shared == 2) {
            ret = H5Gunlink(fid, TYPE1_NAME);
            CHECK(ret, FAIL, "H5Gunlink");
        } /* end if */

        /* Check on attribute storage status */
        ret = H5F_get_sohm_mesg_count_test(fid, H5O_ATTR_ID, &mesg_count);
        CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
        VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

        if(test_shared != 0) {
            /* Check on datatype storage status */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_DTYPE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

            /* Check on dataspace storage status */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_SDSPACE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");
        } /* end if */

        /* Close file */
        ret = H5Fclose(fid);
        CHECK(ret, FAIL, "H5Fclose");

        /* Check size of file */
        filesize = h5_get_file_size(FILENAME);
        VERIFY(filesize, empty_filesize, "h5_get_file_size");
    } /* end for */

    /* Close dataspaces */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");
    ret = H5Sclose(big_sid);
    CHECK(ret, FAIL, "H5Sclose");
}   /* test_attr_shared_delete() */

/****************************************************************
**
**  test_attr_shared_unlink(): Test basic H5A (attribute) code.
**      Tests unlinking object with  shared attributes in "compact" & "dense" storage
**
****************************************************************/
static void
test_attr_shared_unlink(hid_t fcpl, hid_t fapl)
{
    hid_t	fid;		/* File ID			*/
    hid_t	my_fcpl;	/* File creation property list ID */
    hid_t	dataset, dataset2;	/* Dataset IDs			*/
    hid_t	attr_tid;	/* Attribute's datatype ID	*/
    hid_t	sid, big_sid;	/* Dataspace IDs		*/
    hsize_t	big_dims[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3};   /* Dimensions for "big" attribute */
    hid_t	attr;	        /* Attribute ID			*/
    hid_t	dcpl;	        /* Dataset creation property list ID */
    char	attrname[NAME_BUF_SIZE];        /* Name of attribute on first dataset */
    unsigned    max_compact;    /* Maximum # of attributes to store compactly */
    unsigned    min_dense;      /* Minimum # of attributes to store "densely" */
    htri_t	is_dense;	/* Are attributes stored densely? */
    htri_t	is_shared;	/* Is attributes shared? */
    hsize_t     shared_refcount;        /* Reference count of shared attribute */
    unsigned    attr_value;     /* Attribute value */
    unsigned	big_value[SPACE1_DIM1 * SPACE1_DIM2 * SPACE1_DIM3];   /* Data for "big" attribute */
    size_t      mesg_count;     /* # of shared messages */
    unsigned    test_shared;    /* Index over shared component type */
    unsigned    u;              /* Local index variable */
    h5_stat_size_t empty_filesize;       /* Size of empty file */
    h5_stat_size_t filesize;             /* Size of file after modifications */
    herr_t	ret;		/* Generic return value		*/

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Unlinking Object with Shared Attributes in Compact & Dense Storage\n"));

    /* Initialize "big" attribute data */
    HDmemset(big_value, 1, sizeof(big_value));

    /* Create dataspace for dataset */
    sid = H5Screate(H5S_SCALAR);
    CHECK(sid, FAIL, "H5Screate");

    /* Create "big" dataspace for "large" attributes */
    big_sid = H5Screate_simple(SPACE1_RANK, big_dims, NULL);
    CHECK(sid, FAIL, "H5Screate_simple");

    /* Loop over type of shared components */
    for(test_shared = 0; test_shared < 3; test_shared++) {
        /* Make copy of file creation property list */
        my_fcpl = H5Pcopy(fcpl);
        CHECK(my_fcpl, FAIL, "H5Pcopy");

        /* Set up datatype for attributes */
        attr_tid = H5Tcopy(H5T_NATIVE_UINT);
        CHECK(attr_tid, FAIL, "H5Tcopy");

        /* Special setup for each type of shared components */
        if(test_shared == 0) {
            /* Make attributes > 500 bytes shared */
            ret = H5Pset_shared_mesg_nindexes(my_fcpl, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)0, H5O_MESG_ATTR_FLAG, (unsigned)500);
        } /* end if */
        else {
            /* Set up copy of file creation property list */

            ret = H5Pset_shared_mesg_nindexes(my_fcpl, (unsigned)3);
            CHECK_I(ret, "H5Pset_shared_mesg_nindexes");

            /* Make attributes > 500 bytes shared */
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)0, H5O_MESG_ATTR_FLAG, (unsigned)500);

            /* Make datatypes & dataspaces > 1 byte shared (i.e. all of them :-) */
            CHECK_I(ret, "H5Pset_shared_mesg_index");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)1, H5O_MESG_DTYPE_FLAG, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_index");
            ret = H5Pset_shared_mesg_index(my_fcpl, (unsigned)2, H5O_MESG_SDSPACE_FLAG, (unsigned)1);
            CHECK_I(ret, "H5Pset_shared_mesg_index");
        } /* end else */

        /* Create file */
        fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, my_fcpl, fapl);
        CHECK(fid, FAIL, "H5Fcreate");

        /* Close FCPL copy */
        ret = H5Pclose(my_fcpl);
        CHECK(ret, FAIL, "H5Pclose");

        /* Close file */
        ret = H5Fclose(fid);
        CHECK(ret, FAIL, "H5Fclose");

        /* Get size of file */
        empty_filesize = h5_get_file_size(FILENAME);
        if(empty_filesize < 0)
            TestErrPrintf("Line %d: file size wrong!\n", __LINE__);


        /* Re-open file */
        fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl);
        CHECK(fid, FAIL, "H5Fopen");

        /* Commit datatype to file */
        if(test_shared == 2) {
            ret = H5Tcommit(fid, TYPE1_NAME, attr_tid);
            CHECK(ret, FAIL, "H5Tcommit");
        } /* end if */

        /* Set up to query the object creation properties */
        dcpl = H5Pcreate(H5P_DATASET_CREATE);
        CHECK(dcpl, FAIL, "H5Pcreate");

        /* Create datasets */
        dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dataset, FAIL, "H5Dcreate");
        dataset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
        CHECK(dataset2, FAIL, "H5Dcreate");

        /* Check on dataset's message storage status */
        if(test_shared != 0) {
            /* Dataset's datatypes are immutable and shouldn't be shared */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_DTYPE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

            /* Dataset's dataspace can be shared */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_SDSPACE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 1, "H5F_get_sohm_mesg_count_test");
        } /* end if */

        /* Retrieve limits for compact/dense attribute storage */
        ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
        CHECK(ret, FAIL, "H5Pget_attr_phase_change");

        /* Close property list */
        ret = H5Pclose(dcpl);
        CHECK(ret, FAIL, "H5Pclose");

        /* Check on datasets' attribute storage status */
        is_dense = H5O_is_attr_dense_test(dataset);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
        is_dense = H5O_is_attr_dense_test(dataset2);
        VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");

        /* Add attributes to each dataset, until after converting to dense storage */
        for(u = 0; u < max_compact * 2; u++) {
            /* Create attribute name */
            sprintf(attrname, "attr %02u", u);

            /* Alternate between creating "small" & "big" attributes */
            if(u % 2) {
                /* Create "small" attribute on first dataset */
                attr = H5Acreate(dataset, attrname, attr_tid, sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");

                /* Write data into the attribute */
                attr_value = u + 1;
                ret = H5Awrite(attr, attr_tid, &attr_value);
                CHECK(ret, FAIL, "H5Awrite");
            } /* end if */
            else {
                /* Create "big" attribute on first dataset */
                attr = H5Acreate(dataset, attrname, attr_tid, big_sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");

                /* Write data into the attribute */
                big_value[0] = u + 1;
                ret = H5Awrite(attr, attr_tid, big_value);
                CHECK(ret, FAIL, "H5Awrite");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Check on dataset's attribute storage status */
            is_dense = H5O_is_attr_dense_test(dataset);
            if(u < max_compact)
                VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
            else
                VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");


            /* Alternate between creating "small" & "big" attributes */
            if(u % 2) {
                /* Create "small" attribute on second dataset */
                attr = H5Acreate(dataset2, attrname, attr_tid, sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");

                /* Write data into the attribute */
                attr_value = u + 1;
                ret = H5Awrite(attr, attr_tid, &attr_value);
                CHECK(ret, FAIL, "H5Awrite");
            } /* end if */
            else {
                /* Create "big" attribute on second dataset */
                attr = H5Acreate(dataset2, attrname, attr_tid, big_sid, H5P_DEFAULT);
                CHECK(attr, FAIL, "H5Acreate");

                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");

                /* Write data into the attribute */
                big_value[0] = u + 1;
                ret = H5Awrite(attr, attr_tid, big_value);
                CHECK(ret, FAIL, "H5Awrite");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 2, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");

            /* Check on dataset's attribute storage status */
            is_dense = H5O_is_attr_dense_test(dataset2);
            if(u < max_compact)
                VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
            else
                VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");
        } /* end for */


        /* Close attribute's datatype */
        ret = H5Tclose(attr_tid);
        CHECK(ret, FAIL, "H5Tclose");

        /* Close second dataset */
        ret = H5Dclose(dataset2);
        CHECK(ret, FAIL, "H5Dclose");

        /* Unlink second dataset */
        ret = H5Gunlink(fid, DSET2_NAME);
        CHECK(ret, FAIL, "H5Gunlink");


        /* Check on first dataset's attribute storage status */
        is_dense = H5O_is_attr_dense_test(dataset);
        VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");

        /* Check ref count on  attributes of first dataset */
        for(u = 0; u < max_compact * 2; u++) {
            /* Create attribute name */
            sprintf(attrname, "attr %02u", u);

            /* Open attribute on first dataset */
            attr = H5Aopen_name(dataset, attrname);
            CHECK(attr, FAIL, "H5Acreate");

            if(u % 2) {
                /* Check that attribute is not shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, FALSE, "H5A_is_shared_test");
            } /* end if */
            else {
                /* Check that attribute is shared */
                is_shared = H5A_is_shared_test(attr);
                VERIFY(is_shared, TRUE, "H5A_is_shared_test");

                /* Check refcount for attribute */
                ret = H5A_get_shared_rc_test(attr, &shared_refcount);
                CHECK(ret, FAIL, "H5A_get_shared_rc_test");
                VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test");
            } /* end else */

            /* Close attribute */
            ret = H5Aclose(attr);
            CHECK(ret, FAIL, "H5Aclose");
        } /* end for */

        /* Close Datasets */
        ret = H5Dclose(dataset);
        CHECK(ret, FAIL, "H5Dclose");

        /* Unlink first dataset */
        ret = H5Gunlink(fid, DSET1_NAME);
        CHECK(ret, FAIL, "H5Gunlink");

        /* Unlink committed datatype */
        if(test_shared == 2) {
            ret = H5Gunlink(fid, TYPE1_NAME);
            CHECK(ret, FAIL, "H5Gunlink");
        } /* end if */

        /* Check on attribute storage status */
        ret = H5F_get_sohm_mesg_count_test(fid, H5O_ATTR_ID, &mesg_count);
        CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
        VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

        if(test_shared != 0) {
            /* Check on datatype storage status */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_DTYPE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");

            /* Check on dataspace storage status */
            ret = H5F_get_sohm_mesg_count_test(fid, H5O_SDSPACE_ID, &mesg_count);
            CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test");
            VERIFY(mesg_count, 0, "H5F_get_sohm_mesg_count_test");
        } /* end if */

        /* Close file */
        ret = H5Fclose(fid);
        CHECK(ret, FAIL, "H5Fclose");

        /* Check size of file */
        filesize = h5_get_file_size(FILENAME);
        VERIFY(filesize, empty_filesize, "h5_get_file_size");
    } /* end for */

    /* Close dataspaces */
    ret = H5Sclose(sid);
    CHECK(ret, FAIL, "H5Sclose");
    ret = H5Sclose(big_sid);
    CHECK(ret, FAIL, "H5Sclose");
}   /* test_attr_shared_unlink() */

/****************************************************************
**
**  test_attr(): Main H5A (attribute) testing routine.
**
****************************************************************/
void
test_attr(void)
{
    hid_t	fapl = (-1), fapl2 = (-1);    /* File access property lists */
    hid_t	fcpl = (-1), fcpl2 = (-1);    /* File creation property lists */
    hbool_t new_format;         /* Whether to use the new format or not */
    hbool_t use_shared;         /* Whether to use shared attributes or not */
    herr_t ret;                 /* Generic return value */

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Attributes\n"));

    /* Create a default file access property list */
    fapl = H5Pcreate(H5P_FILE_ACCESS);
    CHECK(fapl, FAIL, "H5Pcreate");

    /* Copy the file access property list */
    fapl2 = H5Pcopy(fapl);
    CHECK(fapl2, FAIL, "H5Pcopy");

    /* Set the "use the latest version of the format" flag for creating objects in the file */
    ret = H5Pset_latest_format(fapl2, TRUE);
    CHECK(ret, FAIL, "H5Pset_latest_format");

    /* Create a default file creation property list */
    fcpl = H5Pcreate(H5P_FILE_CREATE);
    CHECK(fcpl, FAIL, "H5Pcreate");

    /* Copy the file creation property list */
    fcpl2 = H5Pcopy(fcpl);
    CHECK(fcpl2, FAIL, "H5Pcopy");

    /* Make attributes > 1 byte shared (i.e. all of them :-) */
    ret = H5Pset_shared_mesg_nindexes(fcpl2, (unsigned)1);
    CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
    ret = H5Pset_shared_mesg_index(fcpl2, (unsigned)0, H5O_MESG_ATTR_FLAG, (unsigned)1);
    CHECK_I(ret, "H5Pset_shared_mesg_index");

    /* Loop over using new group format */
    for(new_format = FALSE; new_format <= TRUE; new_format++) {
        hid_t my_fapl;

        /* Set the FAPL for the type of format */
        if(new_format) {
            MESSAGE(7, ("testing with new file format\n"));
            my_fapl = fapl2;
        } /* end if */
        else {
            MESSAGE(7, ("testing with old file format\n"));
            my_fapl = fapl;
        } /* end else */

        /* These next two tests use the same file information */
        test_attr_basic_write(my_fapl);    /* Test basic H5A writing code */
        test_attr_basic_read(my_fapl);     /* Test basic H5A reading code */

        /* These next two tests use their own file information */
        test_attr_flush(my_fapl);          /* Test H5A I/O in the presence of H5Fflush calls */
        test_attr_plist(my_fapl);          /* Test attribute property lists */

        /* These next two tests use the same file information */
        test_attr_compound_write(my_fapl);  /* Test complex datatype H5A writing code */
        test_attr_compound_read(my_fapl);   /* Test complex datatype H5A reading code */

        /* These next two tests use the same file information */
        test_attr_scalar_write(my_fapl);  /* Test scalar dataspace H5A writing code */
        test_attr_scalar_read(my_fapl);   /* Test scalar dataspace H5A reading code */

        /* These next four tests use the same file information */
        test_attr_mult_write(my_fapl);     /* Test H5A writing code for multiple attributes */
        test_attr_mult_read(my_fapl);      /* Test H5A reading code for multiple attributes */
        test_attr_iterate(my_fapl);        /* Test H5A iterator code */
        test_attr_delete(my_fapl);         /* Test H5A code for deleting attributes */

        /* This next test uses its own file information */
        test_attr_dtype_shared(my_fapl);   /* Test using shared dataypes in attributes */

        /* Tests on "new format" attribute storage */
        if(new_format == TRUE) {
            /* Loop over using shared attributes */
            for(use_shared = FALSE; use_shared <= TRUE; use_shared++) {
                hid_t my_fcpl;

                /* Set the FCPL for shared or not */
                if(use_shared) {
                    MESSAGE(7, ("testing with shared attributes\n"));
                    my_fcpl = fcpl2;
                } /* end if */
                else {
                    MESSAGE(7, ("testing without shared attributes\n"));
                    my_fcpl = fcpl;
                } /* end else */

                /* General attribute tests */
                test_attr_dense_create(my_fcpl, my_fapl);       /* Test dense attribute storage creation */
                test_attr_dense_open(my_fcpl, my_fapl);         /* Test opening attributes in dense storage */
                test_attr_dense_delete(my_fcpl, my_fapl);       /* Test deleting attributes in dense storage */
                test_attr_dense_rename(my_fcpl, my_fapl);       /* Test renaming attributes in dense storage */
                test_attr_dense_unlink(my_fcpl, my_fapl);       /* Test unlinking object with attributes in dense storage */
                test_attr_dense_limits(my_fcpl, my_fapl);       /* Test dense attribute storage limits */
                test_attr_big(my_fcpl, my_fapl);                /* Test storing big attribute */

                /* Attribute creation order tests */
                test_attr_corder_create_basic(my_fcpl, my_fapl);/* Test creating an object w/attribute creation order info */
                test_attr_corder_create_compact(my_fcpl, my_fapl);  /* Test compact attribute storage on an object w/attribute creation order info */
                test_attr_corder_create_dense(my_fcpl, my_fapl);/* Test dense attribute storage on an object w/attribute creation order info */
                test_attr_corder_transition(my_fcpl, my_fapl);  /* Test attribute storage transitions on an object w/attribute creation order info */
                test_attr_corder_delete(my_fcpl, my_fapl);      /* Test deleting object using dense storage w/attribute creation order info */

                /* New attribute API routine tests */
                test_attr_info_by_idx(new_format, my_fcpl, my_fapl);    /* Test querying attribute info by index */
                test_attr_delete_by_idx(new_format, my_fcpl, my_fapl);  /* Test deleting attribute by index */
                test_attr_iterate2(new_format, my_fcpl, my_fapl);       /* Test iterating over attributes by index */
                test_attr_open_by_idx(new_format, my_fcpl, my_fapl);    /* Test opening attributes by index */
                test_attr_open(new_format, my_fcpl, my_fapl);           /* Test opening attributes by name */

                /* More complex tests with both "new format" and "shared" attributes */
                if(use_shared == TRUE) {
                    test_attr_shared_write(my_fcpl, my_fapl);   /* Test writing to shared attributes in compact & dense storage */
                    test_attr_shared_rename(my_fcpl, my_fapl);  /* Test renaming shared attributes in compact & dense storage */
                    test_attr_shared_delete(my_fcpl, my_fapl);  /* Test deleting shared attributes in compact & dense storage */
                    test_attr_shared_unlink(my_fcpl, my_fapl);  /* Test unlinking object with shared attributes in compact & dense storage */
                } /* end if */
            } /* end for */
        } /* end if */
        else {
            /* New attribute API routine tests, on old-format storage */
            test_attr_info_by_idx(new_format, fcpl, my_fapl);   /* Test querying attribute info by index */
            test_attr_delete_by_idx(new_format, fcpl, my_fapl); /* Test deleting attribute by index */
            test_attr_iterate2(new_format, fcpl, my_fapl);      /* Test iterating over attributes by index */
            test_attr_open_by_idx(new_format, fcpl, my_fapl);   /* Test opening attributes by index */
            test_attr_open(new_format, fcpl, my_fapl);          /* Test opening attributes by name */
            test_attr_big(fcpl, my_fapl);                       /* Test storing big attribute */
        } /* end else */
    } /* end for */

    /* Close  FCPLs */
    ret = H5Pclose(fcpl);
    CHECK(ret, FAIL, "H5Pclose");
    ret = H5Pclose(fcpl2);
    CHECK(ret, FAIL, "H5Pclose");

    /* Close  FAPLs */
    ret = H5Pclose(fapl);
    CHECK(ret, FAIL, "H5Pclose");
    ret = H5Pclose(fapl2);
    CHECK(ret, FAIL, "H5Pclose");
}   /* test_attr() */


/*-------------------------------------------------------------------------
 * Function:	cleanup_attr
 *
 * Purpose:	Cleanup temporary test files
 *
 * Return:	none
 *
 * Programmer:	Albert Cheng
 *              July 2, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
void
cleanup_attr(void)
{
    remove(FILENAME);
}

