/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /***************************************************************************** FILE tattr.cpp - HDF5 C++ testing the functionalities associated with the C attribute interface (H5A) ***************************************************************************/ #ifdef OLD_HEADER_FILENAME #include #else #include #endif #include #ifndef H5_NO_NAMESPACE #ifndef H5_NO_STD using std::cerr; using std::endl; #endif // H5_NO_STD #endif #include "H5Cpp.h" // C++ API header file #ifndef H5_NO_NAMESPACE using namespace H5; #endif #include "h5cpputil.h" // C++ utilility header file const H5std_string FILE_BASIC("tattr_basic.h5"); const H5std_string FILE_COMPOUND("tattr_compound.h5"); const H5std_string FILE_SCALAR("tattr_scalar.h5"); const H5std_string FILE_MULTI("tattr_multi.h5"); const H5std_string FILE_DTYPE("tattr_dtype.h5"); const H5std_string ATTR_TMP_NAME("temp_attr_name"); const H5std_string FATTR_TMP_NAME("temp_fattr_name"); const size_t ATTR_MAX_DIMS = 7; /* 3-D dataset with fixed dimensions */ const int SPACE1_RANK = 3; const hsize_t SPACE1_DIM1 = 3; const hsize_t SPACE1_DIM2 = 15; const hsize_t SPACE1_DIM3 = 13; /* Object names */ const H5std_string DSET1_NAME("Dataset1"); const H5std_string GROUP1_NAME("/Group1"); const H5std_string TYPE1_NAME("/Type"); /* Attribute Rank & Dimensions */ const H5std_string ATTR1_NAME("Attr1"); const int ATTR1_RANK = 1; const hsize_t ATTR1_DIM1 = 3; int attr_data1[ATTR1_DIM1]={512,-234,98123}; /* Test data for 1st attribute */ // File attribute, using the same rank and dimensions as ATTR1_NAME's const H5std_string FATTR1_NAME("File Attr1"); const H5std_string FATTR2_NAME("File Attr2"); const H5std_string ATTR2_NAME("Attr2"); const int ATTR2_RANK = 2; const hsize_t ATTR2_DIM1 = 2; const hsize_t ATTR2_DIM2 = 2; int attr_data2[ATTR2_DIM1][ATTR2_DIM2]={{7614,-416},{197814,-3}}; /* Test data for 2nd attribute */ const H5std_string ATTR3_NAME("Attr3"); const int ATTR3_RANK = 3; const hsize_t ATTR3_DIM1 = 2; const hsize_t ATTR3_DIM2 = 2; const hsize_t ATTR3_DIM3 = 2; double attr_data3[ATTR3_DIM1][ATTR3_DIM2][ATTR3_DIM3]={{{2.3,-26.1},{0.123,-10.0}},{{981724.2,-0.91827},{2.0,23.0}}}; /* Test data for 3rd attribute */ const H5std_string ATTR4_NAME("Attr4"); const int ATTR4_RANK = 2; const hsize_t ATTR4_DIM1 = 2; const hsize_t ATTR4_DIM2 = 2; const H5std_string ATTR4_FIELDNAME1("i"); const H5std_string ATTR4_FIELDNAME2("d"); const H5std_string 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 const H5std_string ATTR5_NAME("Attr5"); const int ATTR5_RANK = 0; float attr_data5 = (float)-5.123; // Test data for 5th attribute /* Info for another attribute */ const H5std_string ATTR1A_NAME("Attr1_a"); int attr_data1a[ATTR1_DIM1]={256,11945,-22107}; /**************************************************************** ** ** test_attr_basic_write(): Test basic write attribute. ** Tests integer attributes on both datasets and groups ** ****************************************************************/ static void test_attr_basic_write() { 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 hsize_t i; // Output message about test being performed SUBTEST("Basic Attribute Writing Functions"); try { // Create file H5File fid1 (FILE_BASIC, H5F_ACC_TRUNC); // Create dataspace for dataset DataSpace ds_space (SPACE1_RANK, dims1); /* * Test attribute with dataset */ // Create a dataset DataSet dataset = fid1.createDataSet(DSET1_NAME, PredType::NATIVE_UCHAR, ds_space); // Create dataspace for attribute DataSpace att_space (ATTR1_RANK, dims2); // Create a file attribute Attribute file_attr2 = fid1.createAttribute (FATTR1_NAME, PredType::NATIVE_INT, att_space); // Create a file attribute Attribute file_attr1 = fid1.createAttribute (FATTR2_NAME, PredType::NATIVE_INT, att_space); // Create an attribute for the dataset Attribute ds_attr1 = dataset.createAttribute (ATTR1_NAME, PredType::NATIVE_INT, att_space); // Try creating an attribute that already exists. This should fail // since two attributes cannot have the same name. If an exception // is not thrown for this action by createAttribute, then throw an // invalid action exception. try { Attribute invalid_attr = dataset.createAttribute (ATTR1_NAME, PredType::NATIVE_INT, att_space); // continuation here, that means no exception has been thrown throw InvalidActionException("H5File::createDataSet", "Library allowed overwrite of existing dataset"); } catch (AttributeIException E) // catching invalid creating attribute {} // do nothing, exception expected // Write attribute information ds_attr1.write (PredType::NATIVE_INT, attr_data1); // Read attribute information immediately, without closing attribute ds_attr1.read (PredType::NATIVE_INT, read_data1); // Verify values read in for(i=0; iopenAttribute(ATTR1_NAME)); // Read data from the attribute attr2->read(PredType::NATIVE_INT, &rdata); verify_val(data, rdata, "Attribute::read", __LINE__, __FILE__); // Close attribute and dataset delete attr2; delete dset2; #ifndef H5_NO_DEPRECATED_SYMBOLS // Check reference count on named datatype fid1.getObjinfo(TYPE1_NAME, statbuf); verify_val((int)statbuf.nlink, 3, "DataSet::openAttribute", __LINE__, __FILE__); #endif /* H5_NO_DEPRECATED_SYMBOLS */ } // end of second enclosing // Unlink the dataset fid1.unlink(DSET1_NAME); #ifndef H5_NO_DEPRECATED_SYMBOLS // Check reference count on named datatype fid1.getObjinfo(TYPE1_NAME, statbuf); verify_val((int)statbuf.nlink, 1, "H5File::unlink", __LINE__, __FILE__); #endif /* H5_NO_DEPRECATED_SYMBOLS */ // Unlink the named datatype fid1.unlink(TYPE1_NAME); // Close file fid1.close(); // Check size of file filesize = h5_get_file_size(FILE_DTYPE.c_str(), H5P_DEFAULT); verify_val((long)filesize, (long)empty_filesize, "Checking file size", __LINE__, __FILE__); PASSED(); } // end try block catch (Exception E) { issue_fail_msg("test_attr_dtype_shared()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_dtype_shared() /**************************************************************** ** ** test_string_attr(): Test read/write string attribute. ** Tests string attributes on groups. ** ****************************************************************/ /* Info for a string attribute */ const H5std_string ATTR1_FL_STR_NAME("String_attr 1"); const H5std_string ATTR2_FL_STR_NAME("String_attr 2"); const H5std_string ATTR_VL_STR_NAME("String_attr"); const H5std_string ATTRSTR_DATA("String Attribute"); const int ATTR_LEN = 17; static void test_string_attr() { // Output message about test being performed SUBTEST("I/O on FL and VL String Attributes"); try { // Create file H5File fid1(FILE_BASIC, H5F_ACC_RDWR); // // Fixed-lenth string attributes // // Create a fixed-length string datatype to refer to. StrType fls_type(0, ATTR_LEN); // Open the root group. Group root = fid1.openGroup("/"); // Create dataspace for the attribute. DataSpace att_space (H5S_SCALAR); /* Test Attribute::write(...,const void *buf) with Fixed len string */ // Create an attribute for the root group. Attribute gr_flattr1 = root.createAttribute(ATTR1_FL_STR_NAME, fls_type, att_space); // Write data to the attribute. gr_flattr1.write(fls_type, ATTRSTR_DATA.c_str()); /* Test Attribute::write(...,const H5std_string& strg) with FL string */ // Create an attribute for the root group. Attribute gr_flattr2 = root.createAttribute(ATTR2_FL_STR_NAME, fls_type, att_space); // Write data to the attribute. gr_flattr2.write(fls_type, ATTRSTR_DATA); /* Test Attribute::read(...,void *buf) with FL string */ // Read and verify the attribute string as a string of chars. char flstring_att_check[ATTR_LEN]; gr_flattr1.read(fls_type, flstring_att_check); if(HDstrcmp(flstring_att_check, ATTRSTR_DATA.c_str())!=0) TestErrPrintf("Line %d: Attribute data different: ATTRSTR_DATA=%s,flstring_att_check=%s\n",__LINE__, ATTRSTR_DATA.c_str(), flstring_att_check); // Read and verify the attribute string as a string of chars; buffer // is dynamically allocated. size_t attr_size = gr_flattr1.getInMemDataSize(); char *fl_dyn_string_att_check; fl_dyn_string_att_check = new char[attr_size+1]; gr_flattr1.read(fls_type, fl_dyn_string_att_check); if(HDstrcmp(fl_dyn_string_att_check, ATTRSTR_DATA.c_str())!=0) TestErrPrintf("Line %d: Attribute data different: ATTRSTR_DATA=%s,flstring_att_check=%s\n",__LINE__, ATTRSTR_DATA.c_str(), fl_dyn_string_att_check); delete []fl_dyn_string_att_check; /* Test Attribute::read(...,H5std_string& strg) with FL string */ // Read and verify the attribute string as an std::string. H5std_string read_flstr1; gr_flattr1.read(fls_type, read_flstr1); if (read_flstr1 != ATTRSTR_DATA) TestErrPrintf("Line %d: Attribute data different: ATTRSTR_DATA=%s,read_flstr1=%s\n",__LINE__, ATTRSTR_DATA.c_str(), read_flstr1.c_str()); // Read and verify the attribute string as a string of chars. HDstrcpy(flstring_att_check, ""); gr_flattr2.read(fls_type, flstring_att_check); if(HDstrcmp(flstring_att_check, ATTRSTR_DATA.c_str())!=0) TestErrPrintf("Line %d: Attribute data different: ATTRSTR_DATA=%s,flstring_att_check=%s\n",__LINE__, ATTRSTR_DATA.c_str(), flstring_att_check); /* Test Attribute::read(...,H5std_string& strg) with FL string */ // Read and verify the attribute string as an std::string. H5std_string read_flstr2; gr_flattr2.read(fls_type, read_flstr2); if (read_flstr2 != ATTRSTR_DATA) TestErrPrintf("Line %d: Attribute data different: ATTRSTR_DATA=%s,read_flstr2=%s\n",__LINE__, ATTRSTR_DATA.c_str(), read_flstr2.c_str()); // // Variable-lenth string attributes // // Create a variable length string datatype to refer to. StrType vls_type(0, H5T_VARIABLE); // Create an attribute for the root group. Attribute gr_vlattr = root.createAttribute(ATTR_VL_STR_NAME, vls_type, att_space); // Write data to the attribute. gr_vlattr.write(vls_type, ATTRSTR_DATA); /* Test Attribute::read(...,void *buf) with Variable len string */ // Read and verify the attribute string as a string of chars. char *string_att_check; gr_vlattr.read(vls_type, &string_att_check); if(HDstrcmp(string_att_check, ATTRSTR_DATA.c_str())!=0) TestErrPrintf("Line %d: Attribute data different: ATTRSTR_DATA=%s,string_att_check=%s\n",__LINE__, ATTRSTR_DATA.c_str(), string_att_check); HDfree(string_att_check); /* Test Attribute::read(...,H5std_string& strg) with VL string */ // Read and verify the attribute string as an std::string. H5std_string read_str; gr_vlattr.read(vls_type, read_str); if (read_str != ATTRSTR_DATA) TestErrPrintf("Line %d: Attribute data different: ATTRSTR_DATA=%s,read_str=%s\n",__LINE__, ATTRSTR_DATA.c_str(), read_str.c_str()); PASSED(); } // end try block catch (Exception E) { issue_fail_msg("test_string_attr()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_string_attr() /**************************************************************** ** ** test_attr_exists(): Test checking for attribute existence. ** (additional attrExists tests are in test_attr_rename()) ** ****************************************************************/ static void test_attr_exists() { // Output message about test being performed SUBTEST("Check Attribute Existence"); try { // Open file. H5File fid1(FILE_BASIC, H5F_ACC_RDWR); // Open the root group. Group root = fid1.openGroup("/"); // Check for existence of attribute bool attr_exists = fid1.attrExists(ATTR1_FL_STR_NAME); if (attr_exists == false) throw InvalidActionException("H5File::attrExists", "fid1, ATTR1_FL_STR_NAMEAttribute should exist but does not"); // Check for existence of attribute attr_exists = fid1.attrExists(FATTR1_NAME); if (attr_exists == false) throw InvalidActionException("H5File::attrExists", "fid1,FATTR2_NAMEAttribute should exist but does not"); // Open a group. Group group = fid1.openGroup(GROUP1_NAME); // Check for existence of attribute attr_exists = group.attrExists(ATTR2_NAME); if (attr_exists == false) throw InvalidActionException("H5File::attrExists", "group, ATTR2_NAMEAttribute should exist but does not"); PASSED(); } // end try block catch (InvalidActionException E) { issue_fail_msg("test_attr_exists()", __LINE__, __FILE__, E.getCDetailMsg()); } catch (Exception E) { issue_fail_msg("test_attr_exists()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_exists() /**************************************************************** ** ** test_attr_dense_create(): Test phase change properties ** Tests "dense" attribute storage creation ** ****************************************************************/ const H5std_string FILE_CRTPROPS("tattr_crt_properties.h5"); const int NAME_BUF_SIZE = 1024; const unsigned MAX_COMPACT_DEF = 8; const unsigned MIN_DENSE_DEF = 6; static void test_attr_dense_create(FileCreatPropList& fcpl, FileAccPropList& fapl) { // Output message about test being performed SUBTEST("Dense Attribute Storage Creation"); try { // Create file H5File fid1 (FILE_CRTPROPS, H5F_ACC_TRUNC, fcpl, fapl); // Close file fid1.close(); // Get size of file h5_stat_size_t empty_filesize; // Size of empty file empty_filesize = h5_get_file_size(FILE_CRTPROPS.c_str(), fapl.getId()); if (empty_filesize < 0) TestErrPrintf("Line %d: file size wrong!\n", __LINE__); // Re-open file fid1.openFile(FILE_CRTPROPS, H5F_ACC_RDWR, fapl); // Create dataspace for dataset DataSpace ds_space(H5S_SCALAR); // Create dataset creation property list. DSetCreatPropList dcpl; // Create a dataset DataSet dataset = fid1.createDataSet(DSET1_NAME, PredType::NATIVE_UCHAR, ds_space, dcpl); unsigned max_compact = 0, min_dense = 0; // Retrieve limits for compact/dense attribute storage dcpl.getAttrPhaseChange(max_compact, min_dense); verify_val(max_compact, MAX_COMPACT_DEF, "DSetCreatPropList::getAttrPhaseChange",__LINE__,__FILE__); verify_val(min_dense, MIN_DENSE_DEF, "DSetCreatPropList::getAttrPhaseChange",__LINE__,__FILE__); // Set new compact/dense attribute storage limits to some random numbers dcpl.setAttrPhaseChange(7, 5); // Retrieve limits for compact/dense attribute storage and verify them dcpl.getAttrPhaseChange(max_compact, min_dense); verify_val(max_compact, 7, "DSetCreatPropList::getAttrPhaseChange",__LINE__,__FILE__); verify_val(min_dense, 5, "DSetCreatPropList::getAttrPhaseChange",__LINE__,__FILE__); // Close property list dcpl.close(); // H5O_is_attr_dense_test - un-usable // Add attributes, until just before converting to dense storage char attr_name[NAME_BUF_SIZE]; unsigned attr_num; for (attr_num = 0; attr_num < max_compact; attr_num++) { // Create attribute sprintf(attr_name, "attr %02u", attr_num); Attribute attr = dataset.createAttribute(attr_name, PredType::NATIVE_UINT, ds_space); // Write data to the attribute attr.write(PredType::NATIVE_UINT, &attr_num); } // end for // H5O_is_attr_dense_test - un-usable { // Add one more attribute, to push into "dense" storage // Create another attribute sprintf(attr_name, "attr %02u", attr_num); Attribute attr = dataset.createAttribute(attr_name, PredType::NATIVE_UINT, ds_space); // Write data to the attribute attr.write(PredType::NATIVE_UINT, &attr_num); } // Attempt to add attribute again, which should fail try { // Create another attribute sprintf(attr_name, "attr %02u", attr_num); Attribute attr = dataset.createAttribute(attr_name, PredType::NATIVE_UINT, ds_space); // continuation here, that means no exception has been thrown throw InvalidActionException("DataSet::createAttribute", "Maximum number of attributes has been reached"); } catch (AttributeIException E) // catching invalid action {} // do nothing, exception expected PASSED(); } // end try block catch (Exception E) { issue_fail_msg("test_attr_dense_create()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_dense_create() /**************************************************************** ** ** test_attr_corder_create_basic(): Test creation order properties ** Tests creating an object w/attribute creation order info ** ****************************************************************/ static void test_attr_corder_create_basic(FileCreatPropList& fcpl, FileAccPropList& fapl) { // Output message about test being performed SUBTEST("Basic Code for Attributes with Creation Order Info"); try { // Create file H5File fid1 (FILE_CRTPROPS, H5F_ACC_TRUNC, fcpl, fapl); // Create dataset creation property list. DSetCreatPropList dcpl; // Get creation order indexing on object unsigned crt_order_flags = 0; crt_order_flags = dcpl.getAttrCrtOrder(); verify_val(crt_order_flags, 0, "DSetCreatPropList::getAttrCrtOrder",__LINE__,__FILE__); // Setting invalid combination of a attribute order creation order // indexing on should fail try { dcpl.setAttrCrtOrder(H5P_CRT_ORDER_INDEXED); // continuation here, that means no exception has been thrown throw InvalidActionException("DSetCreatPropList::getAttrCrtOrder", "Indexing cannot be set alone, order tracking is required"); } catch (PropListIException E) // catching invalid action {} // do nothing, exception expected // Set attribute creation order tracking & indexing for object then // verify them dcpl.setAttrCrtOrder(H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED); crt_order_flags = dcpl.getAttrCrtOrder(); verify_val(crt_order_flags, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED), "DSetCreatPropList::getAttrCrtOrder",__LINE__,__FILE__); // Create dataspace for dataset DataSpace ds_space(H5S_SCALAR); // Create a dataset DataSet dataset = fid1.createDataSet(DSET1_NAME, PredType::NATIVE_UCHAR, ds_space, dcpl); // Close dataspace ds_space.close(); // Check on dataset's attribute storage status. // NOTE: Wrappers not available yet (H5O_is_attr_empty_test // and H5O_is_attr_dense_test) // Close dataset dataset.close(); // Close property list dcpl.close(); // Close file fid1.close(); // Re-open file fid1.openFile(FILE_CRTPROPS, H5F_ACC_RDWR, fapl); // Open dataset created previously dataset = fid1.openDataSet(DSET1_NAME); // Retrieve dataset creation property list for the dataset dcpl = dataset.getCreatePlist(); // Query the attribute creation properties crt_order_flags = dcpl.getAttrCrtOrder(); verify_val(crt_order_flags, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED), "DSetCreatPropList::getAttrCrtOrder",__LINE__,__FILE__); PASSED(); } // end try block catch (Exception E) { issue_fail_msg("test_attr_corder_create_basic()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_corder_create_basic() /**************************************************************** ** ** test_attr(): Main attribute testing routine. ** ****************************************************************/ #ifdef __cplusplus extern "C" #endif void test_attr() { // Output message about test being performed MESSAGE(5, ("Testing Attributes\n")); try { // Create a default file access property list FileAccPropList fapl; // Copy the file access property list for new format test FileAccPropList fapl_new = fapl; // Set the "use the latest version of the format" bounds for creating // objects in the file fapl_new.setLibverBounds(H5F_LIBVER_LATEST, H5F_LIBVER_LATEST); // Create a default file creation property list FileCreatPropList fcpl; // Copy the file creation property list for new format test FileCreatPropList fcpl_new = fcpl; // Wrappers for ..._shared_mesg_nindexes are not available, skip // use_shared test // Loop over using new group format unsigned new_format; for (new_format = FALSE; new_format <= TRUE; new_format++) { FileAccPropList curr_fapl; // Set the file access proplist for the type of format if (new_format) { MESSAGE(7, ("testing with new file format\n")); curr_fapl = fapl_new; } else { MESSAGE(7, ("testing with old file format\n")); curr_fapl = fapl; } test_attr_basic_write(); // Test basic H5A writing code test_attr_getname(); // Test overloads of Attribute::getName test_attr_rename(); // Test renaming attribute test_attr_basic_read(); // Test basic H5A reading code test_attr_compound_write(); // Test complex datatype H5A writing code test_attr_compound_read(); // Test complex datatype H5A reading code test_attr_scalar_write(); // Test scalar dataspace H5A writing code test_attr_scalar_read(); // Test scalar dataspace H5A reading code test_attr_mult_write(); // Test writing multiple attributes test_attr_mult_read(); // Test reading multiple attributes test_attr_delete(); // Test deleting attributes test_attr_dtype_shared(); // Test using shared datatypes in attributes test_string_attr(); // Test read/write string attribute test_attr_exists(); // Test H5Location::attrExists // Test with new format if (new_format) { // Test dense attribute storage creation test_attr_dense_create(fcpl, curr_fapl); // Test create objects with attribute creation info test_attr_corder_create_basic(fcpl, curr_fapl); } } // end for } // end try block catch (Exception E) { issue_fail_msg("test_attr()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr() /*------------------------------------------------------------------------- * Function: cleanup_attr * * Purpose: Cleanup temporary test files * * Return: none * * Programmer: Albert Cheng * July 2, 1998 * * Modifications: * *------------------------------------------------------------------------- */ #ifdef __cplusplus extern "C" #endif void cleanup_attr() { HDremove(FILE_BASIC.c_str()); HDremove(FILE_COMPOUND.c_str()); HDremove(FILE_SCALAR.c_str()); HDremove(FILE_MULTI.c_str()); HDremove(FILE_DTYPE.c_str()); HDremove(FILE_CRTPROPS.c_str()); }