/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the COPYING file, which can be found at the root of the source code * * distribution tree, or in https://www.hdfgroup.org/licenses. * * 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) ***************************************************************************/ #include #include #include using std::cerr; using std::endl; #include #include "H5Cpp.h" // C++ API header file using namespace H5; #include "h5test.h" #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 = -5.123F; // Test data for 5th attribute /* Info for another attribute */ const H5std_string ATTR1A_NAME("Attr1_a"); int attr_data1a[ATTR1_DIM1] = {256, 11945, -22107}; /*------------------------------------------------------------------------- * Function: test_attr_basic_write * * Purpose Test basic write attribute on both datasets and groups. * * Return None *------------------------------------------------------------------------- */ 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; i < ATTR1_DIM1; i++) if (attr_data1[i] != read_data1[i]) TestErrPrintf("%d: attribute data different: attr_data1[%" PRIuHSIZE "]=%d,read_data1[%" PRIuHSIZE "]=%d\n", __LINE__, i, attr_data1[i], i, read_data1[i]); // Create two more attributes for this dataset, but only write to one. Attribute ds_attr2 = dataset.createAttribute(ATTR2_NAME, PredType::NATIVE_INT, att_space); Attribute ds_attr3 = dataset.createAttribute(ATTR3_NAME, PredType::NATIVE_INT, att_space); // Write attribute information ds_attr2.write(PredType::NATIVE_INT, attr_data1a); // Read attribute information immediately, without closing attribute ds_attr2.read(PredType::NATIVE_INT, read_data1); // 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[%" PRIuHSIZE "]=%d,read_data1[%" PRIuHSIZE "]=%d\n", __LINE__, i, attr_data1a[i], i, read_data1[i]); // Close both attributes ds_attr1.close(); ds_attr2.close(); ds_attr3.close(); /* * Test attribute with group */ // Create group in file fid1 Group group = fid1.createGroup(GROUP1_NAME); // Create dataspace for attribute DataSpace sid3(ATTR2_RANK, dims3); // Create an attribute for the group Attribute gr_attr = group.createAttribute(ATTR2_NAME, PredType::NATIVE_INT, sid3); // Check storage size for attribute hsize_t attr_size = gr_attr.getStorageSize(); verify_val(static_cast(attr_size), static_cast(ATTR2_DIM1 * ATTR2_DIM2 * sizeof(int)), "Attribute::getStorageSize", __LINE__, __FILE__); // Try to create the same attribute again (should fail) try { Attribute invalid_attr = group.createAttribute(ATTR2_NAME, PredType::NATIVE_INT, sid3); // continuation here, that means no exception has been thrown throw InvalidActionException("H5Group::createAttribute", "Attempting to create an existing attribute"); } catch (AttributeIException &E) // catching invalid creating attribute { } // do nothing, exception expected // Write attribute information gr_attr.write(PredType::NATIVE_INT, attr_data2); // Check storage size for attribute attr_size = gr_attr.getStorageSize(); verify_val(static_cast(attr_size), static_cast(ATTR2_DIM1 * ATTR2_DIM2 * sizeof(int)), "Attribute::getStorageSize", __LINE__, __FILE__); PASSED(); } // end try block catch (Exception &E) { issue_fail_msg("test_attr_basic_write()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_basic_write() /*------------------------------------------------------------------------- * Function: test_attr_getname * * Purpose Test getting attribute name. * * Description * Test these functions: * A. ssize_t Attribute::getName(char* attr_name, size_t buf_size) * 1. With arbitrary buf_size that is larger than the name size * 2. With arbitrary buf_size that is smaller than the name's length. * 3. With a buf_size that equals the name's length. * * B. ssize_t Attribute::getName(H5std_string& attr_name, size_t buf_size) * 1. With buffer smaller than the actual name * 2. Same test but with retiring overloaded function * ssize_t Attribute::getName(size_t buf_size, H5std_string& attr_name) * * C. H5std_string Attribute::getName() * * D. H5std_string Attribute::getName(size_t len) * * E. ssize_t Attribute::getName(H5std_string& attr_name, size_t buf_size) * With buffer size equals the name's length, i.e., buf_size=0 * * Return None *------------------------------------------------------------------------- */ static void test_attr_getname() { // Output message about test being performed SUBTEST("Testing all overloads of Attribute::getName"); try { // // Open the file FILE_BASIC and test getName with its attribute // // Open file H5File fid1(FILE_BASIC, H5F_ACC_RDWR); // Check for existence of attribute FATTR1_NAME bool attr_exists = fid1.attrExists(FATTR1_NAME); if (!attr_exists) throw InvalidActionException("H5File::attrExists", "Attribute should exist but does not"); // Open attribute Attribute fattr1(fid1.openAttribute(FATTR1_NAME)); // A. Get attribute name with // ssize_t Attribute::getName(char* attr_name, size_t buf_size) // using different buffer sizes and verify against FATTR1_NAME (3 cases) // 1. With arbitrary buf_size that is larger than the name size size_t buf_size = FATTR1_NAME.length() + 10; char * fattr1_name = new char[buf_size + 1]; HDmemset(fattr1_name, 0, buf_size + 1); ssize_t name_size = 0; // actual length of attribute name name_size = fattr1.getName(fattr1_name, buf_size + 1); CHECK(name_size, FAIL, "Attribute::getName", __LINE__, __FILE__); verify_val(static_cast(name_size), FATTR1_NAME.length(), "Attribute::getName", __LINE__, __FILE__); verify_val(const_cast(fattr1_name), FATTR1_NAME, "Attribute::getName", __LINE__, __FILE__); delete[] fattr1_name; // 2. With arbitrary buf_size that is smaller than the name's length. // Let's try 4 first characters in the name. buf_size = 4; char short_name[5] = "File"; // to verify the read name fattr1_name = new char[buf_size + 1]; HDmemset(fattr1_name, 0, buf_size + 1); name_size = fattr1.getName(fattr1_name, buf_size + 1); CHECK(name_size, FAIL, "Attribute::getName", __LINE__, __FILE__); verify_val(static_cast(name_size), FATTR1_NAME.size(), "Attribute::getName", __LINE__, __FILE__); verify_val(const_cast(fattr1_name), const_cast(short_name), "Attribute::getName", __LINE__, __FILE__); delete[] fattr1_name; // 3. With a buf_size that equals the name's length. buf_size = FATTR1_NAME.length(); fattr1_name = new char[buf_size + 1]; HDmemset(fattr1_name, 0, buf_size + 1); name_size = fattr1.getName(fattr1_name, buf_size + 1); CHECK(name_size, FAIL, "Attribute::getName", __LINE__, __FILE__); verify_val(fattr1_name, FATTR1_NAME, "Attribute::getName", __LINE__, __FILE__); delete[] fattr1_name; // B. Get attribute name with // ssize_t Attribute::getName(H5std_string& attr_name, size_t buf_size) // using buffer smaller than the actual name buf_size = 4; H5std_string fattr1_name2; name_size = fattr1.getName(fattr1_name2, buf_size); verify_val(fattr1_name2, "File", "Attribute::getName", __LINE__, __FILE__); // Same test as above, but with deprecated overloaded function // ssize_t Attribute::getName(size_t buf_size, H5std_string& attr_name) // using buffer smaller than the actual name H5std_string fattr1_name2a; name_size = fattr1.getName(fattr1_name2a, buf_size); verify_val(fattr1_name2a, "File", "Attribute::getName", __LINE__, __FILE__); // C. Get file attribute's name with // H5std_string Attribute::getName() H5std_string fattr1_name3 = fattr1.getName(); verify_val(fattr1_name3, FATTR1_NAME, "Attribute::getName", __LINE__, __FILE__); // // D. Test getName getting part of an attribute's name using // H5std_string Attribute::getName(len) // // Open dataset DSET1_NAME DataSet dataset = fid1.openDataSet(DSET1_NAME); // Check for existence of attribute attr_exists = dataset.attrExists(ATTR1_NAME); if (!attr_exists) throw InvalidActionException("H5File::attrExists", "Attribute should exist but does not"); // Open attribute Attribute attr1(dataset.openAttribute(ATTR1_NAME)); size_t len = 4; H5std_string dattr_name1 = attr1.getName(len); verify_val(dattr_name1, "Attr", "Attribute::getName", __LINE__, __FILE__); // E. Get dataset's attribute name with // H5std_string Attribute::getName(H5std_string attr_name, buf_size=0) H5std_string dattr_name2; name_size = attr1.getName(dattr_name2); verify_val(dattr_name2, ATTR1_NAME, "Attribute::getName", __LINE__, __FILE__); PASSED(); } // end try block catch (Exception &E) { issue_fail_msg("test_attr_getname()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_getname() /*------------------------------------------------------------------------- * Function: test_attr_rename * * Purpose Test renaming attribute function. * * Return None *------------------------------------------------------------------------- */ static void test_attr_rename() { int read_data1[ATTR1_DIM1] = {0}; // Buffer for reading the attribute hsize_t i; // Output message about test being performed SUBTEST("Checking for Existence and Renaming Attribute"); try { // Open file H5File fid1(FILE_BASIC, H5F_ACC_RDWR); // Check and rename attribute belonging to a file // Check for existence of attribute bool attr_exists = fid1.attrExists(FATTR1_NAME); if (!attr_exists) throw InvalidActionException("H5File::attrExists", "Attribute should exist but does not"); // Change attribute name fid1.renameAttr(FATTR1_NAME, FATTR_TMP_NAME); // Open attribute again Attribute fattr1(fid1.openAttribute(FATTR_TMP_NAME)); // Verify new attribute name H5std_string fattr_name = fattr1.getName(); verify_val(fattr_name, FATTR_TMP_NAME, "Attribute::getName", __LINE__, __FILE__); int num_attrs = fid1.getNumAttrs(); verify_val(num_attrs, 2, "Attribute::getNumAttrs", __LINE__, __FILE__); // Change first file attribute back to the original name fid1.renameAttr(FATTR_TMP_NAME, FATTR1_NAME); // Open the dataset DataSet dataset = fid1.openDataSet(DSET1_NAME); // Check and rename attribute belonging to a dataset // Check for existence of attribute attr_exists = dataset.attrExists(ATTR1_NAME); if (!attr_exists) throw InvalidActionException("H5File::attrExists", "Attribute should exist but does not"); // Change attribute name dataset.renameAttr(ATTR1_NAME, ATTR_TMP_NAME); // Open attribute again Attribute attr1(dataset.openAttribute(ATTR_TMP_NAME)); // Verify new attribute name H5std_string attr_name = attr1.getName(); verify_val(attr_name, ATTR_TMP_NAME, "Attribute::getName", __LINE__, __FILE__); // Read attribute information immediately, without closing attribute attr1.read(PredType::NATIVE_INT, read_data1); // 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[%" PRIuHSIZE "]=%d,read_data1[%" PRIuHSIZE "]=%d\n", __LINE__, i, attr_data1[i], i, read_data1[i]); // Close attribute attr1.close(); // Check for existence of second attribute attr_exists = dataset.attrExists(ATTR2_NAME); if (!attr_exists) throw InvalidActionException("H5File::attrExists", "Attribute should exist but does not"); // Open the second attribute Attribute attr2(dataset.openAttribute(ATTR2_NAME)); // Verify second attribute name H5std_string attr2_name = attr2.getName(); verify_val(attr2_name, ATTR2_NAME, "Attribute::getName", __LINE__, __FILE__); // Read attribute information immediately, without closing attribute attr2.read(PredType::NATIVE_INT, read_data1); // 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[%" PRIuHSIZE "]=%d,read_data1[%" PRIuHSIZE "]=%d\n", __LINE__, i, attr_data1a[i], i, read_data1[i]); // Close attribute attr2.close(); // Change first attribute back to the original name dataset.renameAttr(ATTR_TMP_NAME, ATTR1_NAME); // Check for existence of attribute after renaming attr_exists = dataset.attrExists(ATTR1_NAME); if (!attr_exists) throw InvalidActionException("H5File::attrExists", "Attribute should exist but does not"); PASSED(); } // end try block catch (Exception &E) { issue_fail_msg("test_attr_rename()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_rename() /*------------------------------------------------------------------------- * Function: test_attr_basic_read * * Purpose Test basic read attribute. * * Return None *------------------------------------------------------------------------- */ static void test_attr_basic_read() { hsize_t i, j; // Output message about test being performed SUBTEST("Basic Attribute Reading Functions"); try { // Open file H5File fid1(FILE_BASIC, H5F_ACC_RDWR); // Open the dataset DataSet dataset = fid1.openDataSet(DSET1_NAME); // Verify the correct number of attributes int num_attrs = dataset.getNumAttrs(); verify_val(num_attrs, 3, "DataSet::getNumAttrs", __LINE__, __FILE__); // Verify the correct number of attributes another way H5O_info2_t oinfo; HDmemset(&oinfo, 0, sizeof(oinfo)); dataset.getObjinfo(oinfo, H5O_INFO_NUM_ATTRS); verify_val(static_cast(oinfo.num_attrs), 3, "DataSet::getObjinfo", __LINE__, __FILE__); // Open an attribute for the dataset Attribute ds_attr = dataset.openAttribute(ATTR1_NAME); // Read attribute information int read_data1[ATTR1_DIM1] = {0}; // Buffer for reading 1st attribute ds_attr.read(PredType::NATIVE_INT, &read_data1); // 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[%" PRIuHSIZE "]=%d, read_data1[%" PRIuHSIZE "]=%d\n", __LINE__, i, attr_data1[i], i, read_data1[i]); /* * Test attribute with group */ // Open the group Group group = fid1.openGroup(GROUP1_NAME); // Verify the correct number of attributes num_attrs = group.getNumAttrs(); verify_val(num_attrs, 1, "Group::getNumAttrs", __LINE__, __FILE__); // Verify the correct number of attributes another way HDmemset(&oinfo, 0, sizeof(oinfo)); group.getObjinfo(oinfo, H5O_INFO_NUM_ATTRS); verify_val(static_cast(oinfo.num_attrs), 1, "Group::getObjinfo", __LINE__, __FILE__); // Open an attribute for the group Attribute gr_attr = group.openAttribute(ATTR2_NAME); // Buffer for reading 2nd attribute int read_data2[ATTR2_DIM1][ATTR2_DIM2] = {{0}}; // Read attribute information gr_attr.read(PredType::NATIVE_INT, read_data2); // 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[%" PRIuHSIZE "][%" PRIuHSIZE "]=%d, " "read_data2[%" PRIuHSIZE "][%" PRIuHSIZE "]=%d\n", __LINE__, i, j, attr_data2[i][j], i, j, read_data2[i][j]); } PASSED(); } // end try block catch (Exception &E) { issue_fail_msg("test_attr_basic_read()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_basic_read() /*------------------------------------------------------------------------- * Function: test_attr_compound_write * * Purpose Test writing attributes with compound datatype. * * Return None *------------------------------------------------------------------------- */ static void test_attr_compound_write() { // Output message about test being performed SUBTEST("Multiple Attribute Functions"); try { // Create file H5File fid1(FILE_COMPOUND.c_str(), H5F_ACC_TRUNC); // Create dataspace for dataset hsize_t dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3}; DataSpace sid1(SPACE1_RANK, dims1); // Create a dataset DataSet dataset = fid1.createDataSet(DSET1_NAME, PredType::NATIVE_UCHAR, sid1); // Create the attribute datatype. CompType comp_type(sizeof(struct attr4_struct)); attr4_field1_off = HOFFSET(struct attr4_struct, i); comp_type.insertMember(ATTR4_FIELDNAME1, attr4_field1_off, PredType::NATIVE_INT); attr4_field2_off = HOFFSET(struct attr4_struct, d); comp_type.insertMember(ATTR4_FIELDNAME2, attr4_field2_off, PredType::NATIVE_DOUBLE); attr4_field3_off = HOFFSET(struct attr4_struct, c); comp_type.insertMember(ATTR4_FIELDNAME3, attr4_field3_off, PredType::NATIVE_SCHAR); // Create dataspace for 1st attribute hsize_t dims2[] = {ATTR4_DIM1, ATTR4_DIM2}; DataSpace sid2(ATTR4_RANK, dims2); // Create complex attribute for the dataset Attribute attr = dataset.createAttribute(ATTR4_NAME, comp_type, sid2); // Try to create the same attribute again (should fail) try { Attribute invalid_attr = dataset.createAttribute(ATTR4_NAME, comp_type, sid2); } catch (AttributeIException &E) // catching invalid creating attribute { } // do nothing, exception expected // Write complex attribute data attr.write(comp_type, attr_data4); PASSED(); } // end try block catch (Exception &E) { issue_fail_msg("test_attr_compound_write()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_compound_write() /*------------------------------------------------------------------------- * Function: test_attr_compound_read * * Purpose Test reading attributes with compound datatype. * * Return None *------------------------------------------------------------------------- */ static void test_attr_compound_read() { hsize_t dims[ATTR_MAX_DIMS]; // Attribute dimensions size_t size; // Attribute datatype size as stored in file size_t offset; // Attribute datatype field offset struct attr4_struct read_data4[ATTR4_DIM1][ATTR4_DIM2]; // Buffer for reading 4th attribute // Output message about test being performed SUBTEST("Basic Attribute Functions"); try { // Open file H5File fid1(FILE_COMPOUND, H5F_ACC_RDWR); // Open the dataset DataSet dataset = fid1.openDataSet(DSET1_NAME); // Verify the correct number of attributes int num_attrs = dataset.getNumAttrs(); verify_val(num_attrs, 1, "DataSet::getNumAttrs", __LINE__, __FILE__); // Verify the correct number of attributes another way H5O_info2_t oinfo; HDmemset(&oinfo, 0, sizeof(oinfo)); dataset.getObjinfo(oinfo, H5O_INFO_NUM_ATTRS); verify_val(static_cast(oinfo.num_attrs), 1, "DataSet::getObjinfo", __LINE__, __FILE__); // Open 1st attribute for the dataset Attribute attr = dataset.openAttribute(static_cast(0)); /* Verify Dataspace */ // Get the dataspace of the attribute DataSpace space = attr.getSpace(); // Get the rank of the dataspace and verify it int rank = space.getSimpleExtentNdims(); verify_val(rank, ATTR4_RANK, "DataSpace::getSimpleExtentNdims", __LINE__, __FILE__); // Get the dims of the dataspace and verify them int ndims = space.getSimpleExtentDims(dims); verify_val(ndims, ATTR4_RANK, "DataSpace::getSimpleExtentDims", __LINE__, __FILE__); verify_val(static_cast(dims[0]), static_cast(ATTR4_DIM1), "DataSpace::getSimpleExtentDims", __LINE__, __FILE__); verify_val(static_cast(dims[1]), static_cast(ATTR4_DIM2), "DataSpace::getSimpleExtentDims", __LINE__, __FILE__); // Get the class of the datatype that is used by attr H5T_class_t type_class = attr.getTypeClass(); // Verify that the type is of compound datatype verify_val(static_cast(type_class), static_cast(H5T_COMPOUND), "Attribute::getTypeClass", __LINE__, __FILE__); // Get the compound datatype CompType datatype = attr.getCompType(); // Verify the number of fields in the datatype, which must be 3 int fields = datatype.getNmembers(); verify_val(fields, 3, "CompType::getNmembers", __LINE__, __FILE__); // Verify that the fields have the same names as when the type // was created int j; for (j = 0; j < fields; j++) { H5std_string fieldname = datatype.getMemberName(j); if (!((fieldname == ATTR4_FIELDNAME1) || (fieldname == ATTR4_FIELDNAME2) || (fieldname == ATTR4_FIELDNAME3))) TestErrPrintf("%d:invalid field name for field #%d: %s\n", __LINE__, j, fieldname.c_str()); } /* end for */ offset = datatype.getMemberOffset(0); verify_val(offset, attr4_field1_off, "DataType::getMemberOffset", __LINE__, __FILE__); offset = datatype.getMemberOffset(1); verify_val(offset, attr4_field2_off, "DataType::getMemberOffset", __LINE__, __FILE__); offset = datatype.getMemberOffset(2); verify_val(offset, attr4_field3_off, "DataType::getMemberOffset", __LINE__, __FILE__); /* Verify each field's type, class & size */ // Get and verify the type class of the first member type_class = datatype.getMemberClass(0); verify_val(static_cast(type_class), static_cast(H5T_INTEGER), "DataType::getMemberClass", __LINE__, __FILE__); // Get and verify the order of this member's type IntType i_type = datatype.getMemberIntType(0); H5T_order_t order = i_type.getOrder(); verify_val(static_cast(order), static_cast(PredType::NATIVE_INT.getOrder()), "DataType::getOrder", __LINE__, __FILE__); // Get and verify the size of this member's type size = i_type.getSize(); verify_val(size, PredType::NATIVE_INT.getSize(), "DataType::getSize", __LINE__, __FILE__); // Get and verify class, order, and size of the second member's type type_class = datatype.getMemberClass(1); verify_val(static_cast(type_class), static_cast(H5T_FLOAT), "DataType::getMemberClass", __LINE__, __FILE__); FloatType f_type = datatype.getMemberFloatType(1); order = f_type.getOrder(); verify_val(static_cast(order), static_cast(PredType::NATIVE_DOUBLE.getOrder()), "DataType::getOrder", __LINE__, __FILE__); size = f_type.getSize(); verify_val(size, PredType::NATIVE_DOUBLE.getSize(), "DataType::getSize", __LINE__, __FILE__); // Get and verify class, order, and size of the third member's type type_class = datatype.getMemberClass(2); verify_val(static_cast(type_class), static_cast(H5T_INTEGER), "DataType::getMemberClass", __LINE__, __FILE__); // Note: H5T_INTEGER is correct here! StrType s_type = datatype.getMemberStrType(2); order = s_type.getOrder(); verify_val(static_cast(order), static_cast(PredType::NATIVE_SCHAR.getOrder()), "DataType::getOrder", __LINE__, __FILE__); size = s_type.getSize(); verify_val(size, PredType::NATIVE_SCHAR.getSize(), "DataType::getSize", __LINE__, __FILE__); // Read attribute information attr.read(datatype, read_data4); // Verify values read in hsize_t ii, jj; for (ii = 0; ii < ATTR4_DIM1; ii++) for (jj = 0; jj < ATTR4_DIM2; jj++) if (HDmemcmp(&attr_data4[ii][jj], &read_data4[ii][jj], sizeof(struct attr4_struct)) != 0) { TestErrPrintf("%d:attribute data different: attr_data4[%" PRIuHSIZE "][%" PRIuHSIZE "].i=%d, " "read_data4[%" PRIuHSIZE "][%" PRIuHSIZE "].i=%d\n", __LINE__, ii, jj, attr_data4[ii][jj].i, ii, jj, read_data4[ii][jj].i); TestErrPrintf("%d:attribute data different: attr_data4[%" PRIuHSIZE "][%" PRIuHSIZE "].d=%f, " "read_data4[%" PRIuHSIZE "][%" PRIuHSIZE "].d=%f\n", __LINE__, ii, jj, attr_data4[ii][jj].d, ii, jj, read_data4[ii][jj].d); TestErrPrintf("%d:attribute data different: attr_data4[%" PRIuHSIZE "][%" PRIuHSIZE "].c=%c, " "read_data4[%" PRIuHSIZE "][%" PRIuHSIZE "].c=%c\n", __LINE__, ii, jj, attr_data4[ii][jj].c, ii, jj, read_data4[ii][jj].c); } /* end if */ // Verify name H5std_string attr_name = attr.getName(); verify_val(attr_name, ATTR4_NAME, "Attribute::getName", __LINE__, __FILE__); } // end try block catch (Exception &E) { issue_fail_msg("test_attr_compound_read()", __LINE__, __FILE__, E.getCDetailMsg()); } try { // Now, try truncating the file to make sure reference counting is good. // If any references to ids in the previous block are left unterminated, // the truncating will fail, because the file will not be closed in // the file.close() above. H5File file1(FILE_COMPOUND, H5F_ACC_TRUNC); PASSED(); } // end try block catch (FileIException &E) { issue_fail_msg("test_attr_compound_read()", __LINE__, __FILE__, "Unable to truncate file, possibly because some objects are left opened"); } } // test_attr_compound_read() /*------------------------------------------------------------------------- * Function: test_attr_scalar_write * * Purpose Test scalar attribute writing functionality. * * Return None *------------------------------------------------------------------------- */ static void test_attr_scalar_write() { // Output message about test being performed SUBTEST("Basic Scalar Attribute Writing Functions"); try { // Create file H5File fid1(FILE_SCALAR, H5F_ACC_TRUNC); // Create dataspace for dataset hsize_t dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3}; DataSpace sid1(SPACE1_RANK, dims1); // Create a dataset DataSet dataset = fid1.createDataSet(DSET1_NAME, PredType::NATIVE_UCHAR, sid1); // Close dataset's dataspace sid1.close(); // Create dataspace for attribute DataSpace att_space(ATTR5_RANK, NULL); // Create an attribute for the dataset Attribute ds_attr = dataset.createAttribute(ATTR5_NAME, PredType::NATIVE_FLOAT, 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(ATTR5_NAME, PredType::NATIVE_FLOAT, 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_attr.write(PredType::NATIVE_FLOAT, &attr_data5); PASSED(); } // end try block catch (Exception &E) { issue_fail_msg("test_attr_scalar_write()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_scalar_write() /*------------------------------------------------------------------------- * Function: test_attr_scalar_read * * Purpose Test scalar attribute reading functionality. * * Return None *------------------------------------------------------------------------- */ /* Epsilon for floating-point comparisons */ #define FP_EPSILON 0.000001F static void test_attr_scalar_read() { // Output message about test being performed SUBTEST("Basic Scalar Attribute Reading Functions"); try { // Open file H5File fid1(FILE_SCALAR, H5F_ACC_RDWR); // Open the dataset DataSet dataset = fid1.openDataSet(DSET1_NAME); // Verify the correct number of attributes int num_attrs = dataset.getNumAttrs(); verify_val(num_attrs, 1, "DataSet::getNumAttrs", __LINE__, __FILE__); // Open an attribute for the dataset Attribute ds_attr = dataset.openAttribute(ATTR5_NAME); // Read attribute information float read_data2 = 0.0; // Buffer for reading 1st attribute ds_attr.read(PredType::NATIVE_FLOAT, &read_data2); if (abs(read_data2 - attr_data5) > FLT_EPSILON) TestErrPrintf("%d: attribute data different: read_data2=%f, " "attr_data5=%f\n", __LINE__, static_cast(read_data2), static_cast(attr_data5)); // Get the dataspace of the attribute DataSpace att_space = ds_attr.getSpace(); // Make certain the dataspace is scalar H5S_class_t space_type = att_space.getSimpleExtentType(); verify_val(static_cast(space_type), static_cast(H5S_SCALAR), "DataSpace::getSimpleExtentType", __LINE__, __FILE__); PASSED(); } // end try block catch (Exception &E) { issue_fail_msg("test_attr_scalar_read()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_scalar_read() /*------------------------------------------------------------------------- * Function: test_attr_mult_write * * Purpose Test writing multiple attributes. * * Return None *------------------------------------------------------------------------- */ static void test_attr_mult_write() { // Output message about test being performed SUBTEST("Multiple Attribute Writing Functions"); try { // Create file H5File fid1(FILE_MULTI, H5F_ACC_TRUNC); // Create dataspace for dataset hsize_t dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3}; DataSpace ds_space(SPACE1_RANK, dims1); // Create a dataset DataSet dataset = fid1.createDataSet(DSET1_NAME, PredType::NATIVE_UCHAR, ds_space); // Create dataspace for 1st attribute hsize_t dims2[] = {ATTR1_DIM1}; DataSpace att_space(ATTR1_RANK, dims2); // Create 1st attribute for the dataset Attribute ds_attr = dataset.createAttribute(ATTR1_NAME, PredType::NATIVE_INT, att_space); // Write attribute information ds_attr.write(PredType::NATIVE_INT, attr_data1); // Create dataspace for 2nd attribute hsize_t dims3[] = {ATTR2_DIM1, ATTR2_DIM2}; DataSpace att2_space(ATTR2_RANK, dims3); // Create 2nd attribute for the dataset Attribute ds_attr2 = dataset.createAttribute(ATTR2_NAME, PredType::NATIVE_INT, att2_space); // Write 2nd attribute information ds_attr2.write(PredType::NATIVE_INT, attr_data2); // Create dataspace for 3rd attribute hsize_t dims4[] = {ATTR3_DIM1, ATTR3_DIM2, ATTR3_DIM3}; DataSpace att3_space(ATTR3_RANK, dims4); // Create 3rd attribute for the dataset Attribute ds_attr3 = dataset.createAttribute(ATTR3_NAME, PredType::NATIVE_DOUBLE, att3_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(ATTR3_NAME, PredType::NATIVE_DOUBLE, att3_space); // continuation here, that means no exception has been thrown throw InvalidActionException("DataSet::createAttribute", "Attempting to create a duplicate attribute"); } catch (AttributeIException &E) // catching invalid creating attribute { } // do nothing, exception expected // Write 3rd attribute information ds_attr3.write(PredType::NATIVE_DOUBLE, attr_data3); PASSED(); } // end try block catch (Exception &E) { issue_fail_msg("test_attr_mult_write()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_mult_write() /*------------------------------------------------------------------------- * Function: test_attr_mult_read * * Purpose Test reading multiple attributes. * * Return None *------------------------------------------------------------------------- */ static void test_attr_mult_read() { 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 hsize_t i, j, k; // Output message about test being performed SUBTEST("Multiple Attribute Reading Functions"); try { // Open file H5File fid1(FILE_MULTI, H5F_ACC_RDWR); // Open the dataset DataSet dataset = fid1.openDataSet(DSET1_NAME); // Verify the correct number of attributes int num_attrs = dataset.getNumAttrs(); verify_val(num_attrs, 3, "DataSet::getNumAttrs", __LINE__, __FILE__); // Open 1st attribute for the dataset Attribute attr = dataset.openAttribute(static_cast(0)); /* Verify Dataspace */ // Get the dataspace of the attribute DataSpace space = attr.getSpace(); // Get the rank of the dataspace and verify it int rank = space.getSimpleExtentNdims(); verify_val(rank, ATTR1_RANK, "DataSpace::getSimpleExtentNdims", __LINE__, __FILE__); // Get the dims of the dataspace and verify them hsize_t dims[ATTR_MAX_DIMS]; // Attribute dimensions (void)space.getSimpleExtentDims(dims); if (dims[0] != ATTR1_DIM1) TestErrPrintf("%d:attribute dimensions different: dims[0]=%d, should be %" PRIuHSIZE "\n", __LINE__, static_cast(dims[0]), ATTR1_DIM1); /* Verify Datatype */ // Get the class of the datatype that is used by attr H5T_class_t type_class = attr.getTypeClass(); // Verify that the type is of integer datatype verify_val(static_cast(type_class), static_cast(H5T_INTEGER), "Attribute::getTypeClass", __LINE__, __FILE__); // Get the integer datatype IntType i_type1 = attr.getIntType(); // Get and verify the order of this type H5T_order_t order = i_type1.getOrder(); verify_val(static_cast(order), static_cast(PredType::NATIVE_INT.getOrder()), "DataType::getOrder", __LINE__, __FILE__); // Get and verify the size of this type size_t size = i_type1.getSize(); verify_val(size, PredType::NATIVE_INT.getSize(), "DataType::getSize", __LINE__, __FILE__); // Read attribute information attr.read(PredType::NATIVE_INT, read_data1); // 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[%" PRIuHSIZE "]=%d,read_data1[%" PRIuHSIZE "]=%d\n", __LINE__, i, attr_data1[i], i, read_data1[i]); // Verify Name H5std_string attr_name = attr.getName(); verify_val(attr_name, ATTR1_NAME, "DataType::getName", __LINE__, __FILE__); attr.close(); space.close(); // Open 2nd attribute for the dataset attr = dataset.openAttribute(static_cast(1)); /* Verify Dataspace */ // Get the dataspace of the attribute space = attr.getSpace(); // Get the rank of the dataspace and verify it rank = space.getSimpleExtentNdims(); verify_val(rank, ATTR2_RANK, "DataSpace::getSimpleExtentNdims", __LINE__, __FILE__); // Get the dims of the dataspace and verify them (void)space.getSimpleExtentDims(dims); verify_val(static_cast(dims[0]), static_cast(ATTR2_DIM1), "DataSpace::getSimpleExtentDims", __LINE__, __FILE__); verify_val(static_cast(dims[1]), static_cast(ATTR2_DIM2), "DataSpace::getSimpleExtentDims", __LINE__, __FILE__); /* Verify Datatype */ // Get the class of the datatype that is used by attr type_class = attr.getTypeClass(); // Verify that the type is of integer datatype verify_val(static_cast(type_class), static_cast(H5T_INTEGER), "Attribute::getTypeClass", __LINE__, __FILE__); // Get the integer datatype IntType i_type2 = attr.getIntType(); // Get and verify the order of this type order = i_type2.getOrder(); verify_val(static_cast(order), static_cast(PredType::NATIVE_INT.getOrder()), "DataType::getOrder", __LINE__, __FILE__); // Get and verify the size of this type size = i_type2.getSize(); verify_val(size, PredType::NATIVE_INT.getSize(), "DataType::getSize", __LINE__, __FILE__); // Read attribute information attr.read(PredType::NATIVE_INT, read_data2); // attr.read(i_type, read_data2); // 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[%" PRIuHSIZE "][%" PRIuHSIZE "]=%d, " "read_data2[%" PRIuHSIZE "][%" PRIuHSIZE "]=%d\n", __LINE__, i, j, attr_data2[i][j], i, j, read_data2[i][j]); // Verify Name attr_name = attr.getName(); verify_val(attr_name, ATTR2_NAME, "DataType::getName", __LINE__, __FILE__); attr.close(); space.close(); // Open 3rd attribute for the dataset attr = dataset.openAttribute(static_cast(2)); /* Verify Dataspace */ // Get the dataspace of the attribute space = attr.getSpace(); // Get the rank of the dataspace and verify it rank = space.getSimpleExtentNdims(); verify_val(rank, ATTR3_RANK, "DataSpace::getSimpleExtentNdims", __LINE__, __FILE__); // Get the dims of the dataspace and verify them (void)space.getSimpleExtentDims(dims); verify_val(static_cast(dims[0]), static_cast(ATTR3_DIM1), "attribute dimensions", __FILE__, __LINE__); verify_val(static_cast(dims[1]), static_cast(ATTR3_DIM2), "attribute dimensions", __FILE__, __LINE__); verify_val(static_cast(dims[2]), static_cast(ATTR3_DIM3), "attribute dimensions", __FILE__, __LINE__); /* Verify Datatype */ // Get the class of the datatype that is used by attr type_class = attr.getTypeClass(); // Verify that the type is of compound datatype verify_val(static_cast(type_class), static_cast(H5T_FLOAT), "Attribute::getTypeClass", __LINE__, __FILE__); // Get the double datatype FloatType f_type = attr.getFloatType(); // Get and verify the order of this type order = f_type.getOrder(); verify_val(static_cast(order), static_cast(PredType::NATIVE_DOUBLE.getOrder()), "DataType::getOrder", __LINE__, __FILE__); // Get and verify the size of this type size = f_type.getSize(); verify_val(size, PredType::NATIVE_DOUBLE.getSize(), "DataType::getSize", __LINE__, __FILE__); // Read attribute information attr.read(PredType::NATIVE_DOUBLE, read_data3); // 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 (abs(attr_data3[i][j][k] - read_data3[i][j][k]) > DBL_EPSILON) TestErrPrintf("%d: attribute data different: attr_data3[%" PRIuHSIZE "][%" PRIuHSIZE "][%" PRIuHSIZE "]=%f, " "read_data3[%" PRIuHSIZE "][%" PRIuHSIZE "][%" PRIuHSIZE "]=%f\n", __LINE__, i, j, k, attr_data3[i][j][k], i, j, k, read_data3[i][j][k]); // Verify Name attr_name = attr.getName(); verify_val(attr_name, ATTR3_NAME, "DataType::getName", __LINE__, __FILE__); PASSED(); } // end try block catch (Exception &E) { issue_fail_msg("test_attr_mult_read()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_mult_read() /*------------------------------------------------------------------------- * Function: test_attr_delete * * Purpose Test deleting attribute from different hdf5 objects. * * Return None *------------------------------------------------------------------------- */ static void test_attr_delete() { H5std_string attr_name; // Buffer for attribute names // Output message about test being performed SUBTEST("Removing Attribute Function"); try { // Open file. H5File fid1(FILE_BASIC, H5F_ACC_RDWR); // Get the number of file attributes int num_attrs = fid1.getNumAttrs(); verify_val(num_attrs, 2, "H5File::getNumAttrs", __LINE__, __FILE__); // Delete the second file attribute fid1.removeAttr(FATTR2_NAME); // Get the number of file attributes num_attrs = fid1.getNumAttrs(); verify_val(num_attrs, 1, "H5File::getNumAttrs", __LINE__, __FILE__); // Verify the name of the only file attribute left Attribute fattr = fid1.openAttribute(static_cast(0)); attr_name = fattr.getName(); verify_val(attr_name, FATTR1_NAME, "Attribute::getName", __LINE__, __FILE__); fattr.close(); // Test deleting non-existing attribute // Open the dataset DataSet dataset = fid1.openDataSet(DSET1_NAME); // Verify the correct number of attributes num_attrs = dataset.getNumAttrs(); verify_val(num_attrs, 3, "DataSet::getNumAttrs", __LINE__, __FILE__); // Try to delete bogus attribute, should fail try { dataset.removeAttr("Bogus"); // continuation here, that means no exception has been thrown throw InvalidActionException("DataSet::removeAttr", "Attempting to remove non-existing attribute"); } catch (AttributeIException &E) // catching invalid removing attribute { } // do nothing, exception expected // Test deleting dataset's attributes // Verify the correct number of attributes num_attrs = dataset.getNumAttrs(); verify_val(num_attrs, 3, "DataSet::getNumAttrs", __LINE__, __FILE__); // Delete middle (2nd) attribute dataset.removeAttr(ATTR2_NAME); // Verify the correct number of attributes num_attrs = dataset.getNumAttrs(); verify_val(num_attrs, 2, "DataSet::getNumAttrs", __LINE__, __FILE__); // Open 1st attribute for the dataset Attribute attr = dataset.openAttribute(static_cast(0)); // Verify Name attr_name = attr.getName(); verify_val(attr_name, ATTR1_NAME, "Attribute::getName", __LINE__, __FILE__); // Close attribute attr.close(); // Open last (formally 3rd) attribute for the dataset attr = dataset.openAttribute(static_cast(1)); // Verify Name attr_name = attr.getName(); verify_val(attr_name, ATTR3_NAME, "Attribute::getName", __LINE__, __FILE__); attr.close(); // Delete first attribute dataset.removeAttr(ATTR1_NAME); // Verify the correct number of attributes num_attrs = dataset.getNumAttrs(); verify_val(num_attrs, 1, "DataSet::getNumAttrs", __LINE__, __FILE__); // Open the only attribute for the dataset (formally 3rd) attr = dataset.openAttribute(static_cast(0)); // Verify Name attr_name = attr.getName(); verify_val(attr_name, ATTR3_NAME, "Attribute::getName", __LINE__, __FILE__); // Close attribute attr.close(); // Delete first attribute dataset.removeAttr(ATTR3_NAME); // Verify the correct number of attributes num_attrs = dataset.getNumAttrs(); verify_val(num_attrs, 0, "DataSet::getNumAttrs", __LINE__, __FILE__); PASSED(); } // end try block catch (Exception &E) { issue_fail_msg("test_attr_delete()", __LINE__, __FILE__, E.getCDetailMsg()); } } // test_attr_delete() /*------------------------------------------------------------------------- * Function: test_attr_dtype_shared * * Purpose Test accessing attributes using shared datatypes. * * Return None *------------------------------------------------------------------------- */ static void test_attr_dtype_shared() { int data = 8; // Data to write int rdata = 0; // Data read in #ifndef H5_NO_DEPRECATED_SYMBOLS H5G_stat_t statbuf; // Object's information #endif h5_stat_size_t filesize; // Size of file after modifications // Output message about test being performed SUBTEST("Shared Datatypes with Attributes"); try { // Create a file H5File fid1(FILE_DTYPE, H5F_ACC_TRUNC); // 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_DTYPE.c_str(), H5P_DEFAULT); if (empty_filesize < 0) TestErrPrintf("Line %d: file size wrong!\n", __LINE__); // Open the file again fid1.openFile(FILE_DTYPE, H5F_ACC_RDWR); // Enclosing to work around the issue of unused variables and/or // objects created by copy constructors stay around until end of // scope, causing incorrect number of ref counts. { // First enclosed block // Create a datatype to commit and use IntType dtype(PredType::NATIVE_INT); // Commit datatype to file dtype.commit(fid1, TYPE1_NAME); #ifndef H5_NO_DEPRECATED_SYMBOLS // Check reference count on named datatype fid1.getObjinfo(TYPE1_NAME, statbuf); verify_val(static_cast(statbuf.nlink), 1, "DataType::getObjinfo", __LINE__, __FILE__); #endif // Create dataspace for dataset DataSpace dspace; DataSet dset = fid1.createDataSet(DSET1_NAME, dtype, dspace); #ifndef H5_NO_DEPRECATED_SYMBOLS // Check reference count on named datatype fid1.getObjinfo(TYPE1_NAME, statbuf); verify_val(static_cast(statbuf.nlink), 2, "H5File::getObjinfo", __LINE__, __FILE__); #endif // Create attribute on dataset Attribute attr = dset.createAttribute(ATTR1_NAME, dtype, dspace); #ifndef H5_NO_DEPRECATED_SYMBOLS // Check reference count on named datatype fid1.getObjinfo(TYPE1_NAME, statbuf); verify_val(static_cast(statbuf.nlink), 3, "DataSet::getObjinfo", __LINE__, __FILE__); #endif // Close attribute attr.close(); // Delete attribute dset.removeAttr(ATTR1_NAME); #ifndef H5_NO_DEPRECATED_SYMBOLS // Check reference count on named datatype fid1.getObjinfo(TYPE1_NAME, statbuf); verify_val(static_cast(statbuf.nlink), 2, "DataSet::getObjinfo after DataSet::removeAttr", __LINE__, __FILE__); #endif // Create attribute on dataset attr = dset.createAttribute(ATTR1_NAME, dtype, dspace); #ifndef H5_NO_DEPRECATED_SYMBOLS // Check reference count on named datatype fid1.getObjinfo(TYPE1_NAME, statbuf); verify_val(static_cast(statbuf.nlink), 3, "DataSet::createAttribute", __LINE__, __FILE__); #endif // Write data into the attribute attr.write(PredType::NATIVE_INT, &data); // Close attribute, dataset, dataspace, datatype, and file attr.close(); dset.close(); dspace.close(); dtype.close(); } // end of first enclosing fid1.close(); // Open the file again fid1.openFile(FILE_DTYPE, H5F_ACC_RDWR); { // Second enclosed block... // Open dataset DataSet *dset2 = new DataSet(fid1.openDataSet(DSET1_NAME)); // Open attribute Attribute *attr2 = new Attribute(dset2->openAttribute(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(static_cast(statbuf.nlink), 3, "DataSet::openAttribute", __LINE__, __FILE__); #endif } // 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(static_cast(statbuf.nlink), 1, "H5File::unlink", __LINE__, __FILE__); #endif // 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(static_cast(filesize), static_cast(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() /*------------------------------------------------------------------------- * Function: test_string_attr * * Purpose Test read/write string attribute. * * Return None *------------------------------------------------------------------------- */ /* 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() /*------------------------------------------------------------------------- * Function: test_attr_exists * * Purpose Test checking for attribute existence. * * Return None * * Note * 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) 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) 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) 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() /*------------------------------------------------------------------------- * Function: test_attr_dense_create * * Purpose Test phase change properties * * Return None *------------------------------------------------------------------------- */ 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, static_cast(7), "DSetCreatPropList::getAttrPhaseChange", __LINE__, __FILE__); verify_val(min_dense, static_cast(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 snprintf(attr_name, sizeof(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 snprintf(attr_name, sizeof(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 snprintf(attr_name, sizeof(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() /*------------------------------------------------------------------------- * Function: test_attr_corder_create_basic * * Purpose Test creation order properties * * Return None *------------------------------------------------------------------------- */ 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(static_cast(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, static_cast(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, static_cast(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() /*------------------------------------------------------------------------- * Function: test_attr * * Purpose Main attribute testing routine * * Return None *------------------------------------------------------------------------- */ extern "C" 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 *------------------------------------------------------------------------- */ extern "C" 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()); }