Files
hdf5/c++/test/tarray.cpp
T
jhendersonHDF 34d6ef545a Refactor h5test.c, testframe.c and testpar.h testing frameworks (#4891)
Added new testframe.h header to document testing framework functions and
split them away from h5test.h and from test programs that don't
integrate with the testframe.c testing framework

Added new test setup callback to testframe.c testing framework

Added parameters to AddTest() to specify size of test parameters so they
can be copied for later use

Enabled HDF5 error stacks in testframe.c framework by default and added
some error stack suppressions to some testhdf5 tests

Added new maxthreads option to testframe.c framework to allow specifying
the maximum number of threads a multi-threaded test can use

Moved TestExpress functionality out of testframe.c and into more general
h5test.c for wider use by tests through getter and setter

Updated some tests to not mix and match functionality between h5test.c/h
and testframe.c/h

Moved some functionality from testphdf5.h into testpar.h for parallel
tests that aren't part of testphdf5

Added new parallel test library that contains common shared
functionality for parallel tests (similar to h5test library)
2024-10-01 16:10:03 -05:00

511 lines
17 KiB
C++

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://www.hdfgroup.org/licenses. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*****************************************************************************
FILE
tarray.cpp - HDF5 C++ testing the array datatype functionality
***************************************************************************/
#include <iostream>
using std::cerr;
using std::endl;
#include <string>
#include "H5Cpp.h" // C++ API header file
using namespace H5;
#include "h5test.h"
#include "h5cpputil.h" // C++ utilility header file
const H5std_string FILENAME("tarray.h5");
const H5std_string ARRAYTYPE_NAME("/Array type 1");
const int SPACE1_RANK = 1;
const hsize_t SPACE1_DIM1 = 4;
const int ARRAY1_RANK = 1;
const hsize_t ARRAY1_DIM1 = 4;
typedef enum flt_t { FLT_FLOAT, FLT_DOUBLE, FLT_LDOUBLE, FLT_OTHER } flt_t;
typedef enum int_t {
INT_CHAR,
INT_UCHAR,
INT_SHORT,
INT_USHORT,
INT_INT,
INT_UINT,
INT_LONG,
INT_ULONG,
INT_LLONG,
INT_ULLONG,
INT_OTHER
} int_t;
/*-------------------------------------------------------------------------
* Function: test_array_compound_array
*
* Purpose Tests 1-D array of compound datatypes (with array fields)
*
* Return None
*-------------------------------------------------------------------------
*/
static void
test_array_compound_array()
{
SUBTEST("ArrayType::getArrayNDims & ArrayType::getArrayDims");
typedef struct { // Typedef for compound datatype */
int i;
float f[ARRAY1_DIM1];
} s1_t;
s1_t wdata[SPACE1_DIM1][ARRAY1_DIM1]; // Information to write
s1_t rdata[SPACE1_DIM1][ARRAY1_DIM1]; // Information read in
hsize_t sdims1[] = {SPACE1_DIM1};
hsize_t tdims1[] = {ARRAY1_DIM1};
int nmemb; // Number of compound members
int ii; // counting variables
hsize_t idxi, idxj, idxk; // dimension indicing variables
H5T_class_t mclass; // Datatype class for field
// Initialize array data to write
for (idxi = 0; idxi < SPACE1_DIM1; idxi++)
for (idxj = 0; idxj < ARRAY1_DIM1; idxj++) {
wdata[idxi][idxj].i = static_cast<int>(idxi * 10 + idxj);
for (idxk = 0; idxk < ARRAY1_DIM1; idxk++) {
float temp = static_cast<float>(idxi) * 10.0F + static_cast<float>(idxj) * 2.5F +
static_cast<float>(idxk);
wdata[idxi][idxj].f[idxk] = temp;
}
} // end for
try {
// Create File
H5File file1(FILENAME, H5F_ACC_TRUNC);
// Create dataspace for datasets
DataSpace space(SPACE1_RANK, sdims1, NULL);
/*
* Create an array datatype of compounds, arrtype. Each compound
* datatype, comptype, contains an integer and an array of floats,
* arrfltype.
*/
// Create a compound datatype
CompType comptype(sizeof(s1_t));
// Insert integer field
comptype.insertMember("i", HOFFSET(s1_t, i), PredType::NATIVE_INT);
// Create an array of floats datatype
ArrayType arrfltype(PredType::NATIVE_FLOAT, ARRAY1_RANK, tdims1);
// Insert float array field
comptype.insertMember("f", HOFFSET(s1_t, f), arrfltype);
// Close array of floats field datatype
arrfltype.close();
// Create an array datatype of the compound datatype
ArrayType arrtype(comptype, ARRAY1_RANK, tdims1);
// Close compound datatype comptype
comptype.close();
// Create a dataset
DataSet dataset = file1.createDataSet("Dataset1", arrtype, space);
// Write dataset to disk
dataset.write(wdata, arrtype);
// Test opening ArrayType with opening constructor (Dec 2016)
// Commit the arrtype to give it a name
arrtype.commit(file1, ARRAYTYPE_NAME);
// Close it, then re-open with the opening constructor
arrtype.close();
ArrayType named_type(file1, ARRAYTYPE_NAME);
// Get and verify the type's name
H5std_string type_name = named_type.getObjName();
verify_val(type_name, ARRAYTYPE_NAME, "DataType::getObjName tests constructor", __LINE__, __FILE__);
named_type.close();
// Close all
dataset.close();
space.close();
file1.close();
// Re-open file
file1.openFile(FILENAME, H5F_ACC_RDONLY);
// Open the dataset
dataset = file1.openDataSet("Dataset1");
/*
* Check the datatype array of compounds
*/
// Verify that it is an array of compounds
DataType dstype = dataset.getDataType();
mclass = dstype.getClass();
verify_val(mclass == H5T_ARRAY, true, "f2_type.getClass", __LINE__, __FILE__);
dstype.close();
// Get the array datatype to check
ArrayType atype_check = dataset.getArrayType();
// Check the array rank
int ndims = atype_check.getArrayNDims();
verify_val(ndims, ARRAY1_RANK, "atype_check.getArrayNDims", __LINE__, __FILE__);
// Get the array dimensions
hsize_t rdims1[H5S_MAX_RANK];
atype_check.getArrayDims(rdims1);
// Check the array dimensions
for (ii = 0; ii < ndims; ii++)
if (rdims1[ii] != tdims1[ii]) {
TestErrPrintf("Array dimension information doesn't match!, rdims1[%d]=%" PRIuHSIZE
", tdims1[%d]=%" PRIuHSIZE "\n",
ii, rdims1[ii], ii, tdims1[ii]);
continue;
} // end if
// Test ArrayType::ArrayType(const hid_t existing_id)
ArrayType new_arrtype(atype_check.getId());
// Check the array rank
ndims = new_arrtype.getArrayNDims();
verify_val(ndims, ARRAY1_RANK, "new_arrtype.getArrayNDims", __LINE__, __FILE__);
// Get the array dimensions
new_arrtype.getArrayDims(rdims1);
// Check the array dimensions
for (ii = 0; ii < ndims; ii++)
if (rdims1[ii] != tdims1[ii]) {
TestErrPrintf("Array dimension information doesn't match!, rdims1[%d]=%" PRIuHSIZE
", tdims1[%d]=%" PRIuHSIZE "\n",
ii, rdims1[ii], ii, tdims1[ii]);
continue;
} // end if
/*
* Check the compound datatype and the array of floats datatype
* in the compound.
*/
// Get the compound datatype, which is the base datatype of the
// array datatype atype_check.
DataType base_type = atype_check.getSuper();
mclass = base_type.getClass();
verify_val(mclass == H5T_COMPOUND, true, "atype_check.getClass", __LINE__, __FILE__);
// Verify the compound datatype info
CompType ctype_check(base_type.getId());
base_type.close();
// Check the number of members
nmemb = ctype_check.getNmembers();
verify_val(nmemb, 2, "ctype_check.getNmembers", __LINE__, __FILE__);
// Check the 2nd field's name
H5std_string field2_name = ctype_check.getMemberName(1);
if (strcmp(field2_name.c_str(), "f") != 0)
TestErrPrintf("Compound field name doesn't match!, field2_name=%s\n", field2_name.c_str());
// Get the 2nd field's datatype
DataType f2_type = ctype_check.getMemberDataType(1);
// Get the 2nd field's class, this 2nd field should have an array type
mclass = f2_type.getClass();
verify_val(mclass == H5T_ARRAY, true, "f2_type.getClass", __LINE__, __FILE__);
f2_type.close();
// Get the 2nd field, array of floats datatype, to check
ArrayType f2_atype_check = ctype_check.getMemberArrayType(1);
// Check the array rank
ndims = f2_atype_check.getArrayNDims();
verify_val(ndims, ARRAY1_RANK, "f2_atype_check.getArrayNDims", __LINE__, __FILE__);
// Get the array dimensions
memset(rdims1, 0, sizeof(rdims1));
f2_atype_check.getArrayDims(rdims1);
// Check the array dimensions
for (ii = 0; ii < ndims; ii++)
if (rdims1[ii] != tdims1[ii]) {
TestErrPrintf("Array dimension information doesn't match!, rdims1[%d]=%" PRIuHSIZE
", tdims1[%d]=%" PRIuHSIZE "\n",
ii, rdims1[ii], ii, tdims1[ii]);
continue;
} // end if
// Close done datatypes
f2_atype_check.close();
ctype_check.close();
// Read dataset from disk
dataset.read(rdata, atype_check);
// Compare data read in
for (idxi = 0; idxi < SPACE1_DIM1; idxi++) {
for (idxj = 0; idxj < ARRAY1_DIM1; idxj++) {
if (wdata[idxi][idxj].i != rdata[idxi][idxj].i) {
TestErrPrintf("Array data information doesn't match!, wdata[%" PRIuHSIZE "][%" PRIuHSIZE
"].i=%d, "
"rdata[%" PRIuHSIZE "][%" PRIuHSIZE "].i=%d\n",
idxi, idxj, wdata[idxi][idxj].i, idxi, idxj, rdata[idxi][idxj].i);
continue;
} // end if
} // end for
} // end for
// Close all
atype_check.close();
dataset.close();
file1.close();
PASSED();
} // end of try block
catch (Exception &E) {
issue_fail_msg("test_array_compound_array", __LINE__, __FILE__, E.getCDetailMsg());
}
} // end test_array_compound_array()
/*
* Helper routine to demonstrate the issue in HDFFV-9562
*/
static H5::DataType
getArr()
{
hsize_t *dims = new hsize_t;
*dims = 5;
H5::ArrayType ret;
ret = H5::ArrayType(H5::PredType::NATIVE_INT, 1, dims);
delete dims;
return ret;
}
/*-------------------------------------------------------------------------
* Function: test_array_assignment
*
* Purpose Tests the operator=
*
* Return None
*
* Description:
* Used user's sample code in HDFFV-9562
*-------------------------------------------------------------------------
*/
static void
test_array_assignment()
{
hsize_t sdims1[] = {SPACE1_DIM1};
SUBTEST("ArrayType::operator=");
try {
// Create File
H5File file1(FILENAME, H5F_ACC_TRUNC);
// Create dataspace for datasets
DataSpace space(SPACE1_RANK, sdims1, NULL);
/*
* Create an array datatype of compounds, arrtype. Each compound
* datatype, comptype, contains an integer and an array of floats,
* arrfltype.
*/
// Create a compound datatype
CompType comptype(static_cast<size_t>(24));
// Insert integer field
comptype.insertMember("i", 0, PredType::NATIVE_INT);
// Insert float array field
comptype.insertMember("a", 4, getArr());
// Create a dataset
DataSet dataset = file1.createDataSet("Dataset1", comptype, space);
// Close all
dataset.close();
comptype.close();
space.close();
file1.close();
PASSED();
} // end of try block
catch (Exception &E) {
issue_fail_msg("test_array_assignment", __LINE__, __FILE__, E.getCDetailMsg());
}
} // end test_array_assignment()
/*-------------------------------------------------------------------------
* Function: test_array_info
*
* Purpose Tests getting array information using the const methods.
*
* Return None
*-------------------------------------------------------------------------
*/
static void
test_array_info()
{
SUBTEST("ArrayType Const Methods");
typedef struct { // Typedef for compound datatype */
int i;
float f[ARRAY1_DIM1];
} s1_t;
s1_t wdata[SPACE1_DIM1][ARRAY1_DIM1]; // Information to write
hsize_t sdims1[] = {SPACE1_DIM1};
hsize_t tdims1[] = {ARRAY1_DIM1};
int ii; // counting variables
hsize_t idxi, idxj, idxk; // dimension indicing variables
H5T_class_t mclass; // Datatype class for field
// Initialize array data to write
for (idxi = 0; idxi < SPACE1_DIM1; idxi++)
for (idxj = 0; idxj < ARRAY1_DIM1; idxj++) {
wdata[idxi][idxj].i = static_cast<int>(idxi * 10 + idxj);
for (idxk = 0; idxk < ARRAY1_DIM1; idxk++) {
float temp = static_cast<float>(idxi) * 10.0F + static_cast<float>(idxj) * 2.5F +
static_cast<float>(idxk);
wdata[idxi][idxj].f[idxk] = temp;
}
}
try {
// Create File
H5File file1(FILENAME, H5F_ACC_TRUNC);
// Create dataspace for datasets
DataSpace space(SPACE1_RANK, sdims1, NULL);
/*
* Create some array datatypes, then close the file.
*/
// Create an array of floats datatype
ArrayType arrfltype(PredType::NATIVE_FLOAT, ARRAY1_RANK, tdims1);
// Create an array datatype of the compound datatype
ArrayType arrtype(PredType::NATIVE_UINT, ARRAY1_RANK, tdims1);
// Create a dataset
DataSet dataset = file1.createDataSet("Dataset1", arrtype, space);
// Write dataset to disk
dataset.write(wdata, arrtype);
// Close array of floats field datatype
arrfltype.close();
// Close all
dataset.close();
arrtype.close();
space.close();
file1.close();
// Re-open file
file1.openFile(FILENAME, H5F_ACC_RDONLY);
// Open the dataset
dataset = file1.openDataSet("Dataset1");
/*
* Check the datatype array of compounds
*/
// Verify that it is an array of compounds
DataType dstype = dataset.getDataType();
mclass = dstype.getClass();
verify_val(mclass == H5T_ARRAY, true, "f2_type.getClass", __LINE__, __FILE__);
dstype.close();
{ // Let atype_check go out of scope
// Get the array datatype, declared as const
const ArrayType atype_check = dataset.getArrayType();
// Check the array rank with the const method
int ndims = atype_check.getArrayNDims();
verify_val(ndims, ARRAY1_RANK, "atype_check.getArrayNDims", __LINE__, __FILE__);
// Get the array dimensions with the const method
hsize_t rdims1[H5S_MAX_RANK];
atype_check.getArrayDims(rdims1);
// Check the array dimensions
for (ii = 0; ii < ndims; ii++)
if (rdims1[ii] != tdims1[ii]) {
TestErrPrintf("Array dimension information doesn't match!, rdims1[%d]=%" PRIuHSIZE
", tdims1[%d]=%" PRIuHSIZE "\n",
ii, rdims1[ii], ii, tdims1[ii]);
continue;
}
}
// Close all
dataset.close();
file1.close();
PASSED();
} // end of try block
catch (Exception &E) {
issue_fail_msg("test_array_info", __LINE__, __FILE__, E.getCDetailMsg());
}
} // end test_array_info()
/*-------------------------------------------------------------------------
* Function: test_array
*
* Purpose Main datatypes testing routine
*
* Return None
*-------------------------------------------------------------------------
*/
extern "C" void
test_array(const void *params)
{
// Output message about test being performed
MESSAGE(5, ("Testing Array Datatypes\n"));
// Test array of compounds with array field
test_array_compound_array();
// Test operator= (HDFFV-9562)
test_array_assignment();
// Test const functions (HDFFV-9725)
test_array_info();
} // test_array()
/*-------------------------------------------------------------------------
* Function: cleanup_array
*
* Purpose Cleanup temporary test files
*
* Return None
*-------------------------------------------------------------------------
*/
extern "C" void
cleanup_array(void *params)
{
if (GetTestCleanup()) {
HDremove(FILENAME.c_str());
}
} // cleanup_array