diff options
-rw-r--r-- | c++/test/Makefile.am | 4 | ||||
-rw-r--r-- | c++/test/Makefile.in | 13 | ||||
-rw-r--r-- | c++/test/h5cpputil.cpp | 4 | ||||
-rw-r--r-- | c++/test/h5cpputil.h | 46 | ||||
-rw-r--r-- | c++/test/tcompound.cpp | 762 | ||||
-rw-r--r-- | c++/test/testhdf5.cpp | 12 | ||||
-rw-r--r-- | c++/test/trefer.cpp | 17 | ||||
-rw-r--r-- | c++/test/ttypes.cpp | 810 |
8 files changed, 1648 insertions, 20 deletions
diff --git a/c++/test/Makefile.am b/c++/test/Makefile.am index 61933f5..103d55b 100644 --- a/c++/test/Makefile.am +++ b/c++/test/Makefile.am @@ -37,8 +37,8 @@ check_PROGRAMS=$(TEST_PROG) LDADD=$(LIBH5CPP) $(LIBH5TEST) $(LIBHDF5) dsets_SOURCES=dsets.cpp h5cpputil.cpp -testhdf5_SOURCES=testhdf5.cpp tattr.cpp tfile.cpp th5s.cpp trefer.cpp \ - tvlstr.cpp h5cpputil.cpp +testhdf5_SOURCES=testhdf5.cpp tattr.cpp tcompound.cpp tfile.cpp th5s.cpp \ + trefer.cpp ttypes.cpp tvlstr.cpp h5cpputil.cpp # Tell conclude.am that these are C++ tests. HDF_CXX=yes diff --git a/c++/test/Makefile.in b/c++/test/Makefile.in index 2fa6a03..51bc77d 100644 --- a/c++/test/Makefile.in +++ b/c++/test/Makefile.in @@ -73,8 +73,9 @@ am__DEPENDENCIES_3 = $(top_builddir)/src/libhdf5.la dsets_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \ $(am__DEPENDENCIES_3) am_testhdf5_OBJECTS = testhdf5.$(OBJEXT) tattr.$(OBJEXT) \ - tfile.$(OBJEXT) th5s.$(OBJEXT) trefer.$(OBJEXT) \ - tvlstr.$(OBJEXT) h5cpputil.$(OBJEXT) + tcompound.$(OBJEXT) tfile.$(OBJEXT) th5s.$(OBJEXT) \ + trefer.$(OBJEXT) ttypes.$(OBJEXT) tvlstr.$(OBJEXT) \ + h5cpputil.$(OBJEXT) testhdf5_OBJECTS = $(am_testhdf5_OBJECTS) testhdf5_LDADD = $(LDADD) testhdf5_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \ @@ -229,7 +230,6 @@ SIZE_T = @SIZE_T@ STATIC_SHARED = @STATIC_SHARED@ STRIP = @STRIP@ TESTPARALLEL = @TESTPARALLEL@ -TIME = @TIME@ TR = @TR@ TRACE_API = @TRACE_API@ USE_FILTER_DEFLATE = @USE_FILTER_DEFLATE@ @@ -293,6 +293,7 @@ target_alias = @target_alias@ # Shell commands used in Makefiles RM = rm -f CP = cp +TIME = time # Some machines need a command to run executables; this is that command # so that our tests will run. @@ -345,8 +346,8 @@ TEST_PROG = dsets testhdf5 # The tests depend on the hdf5 library, test library, and the c++ library LDADD = $(LIBH5CPP) $(LIBH5TEST) $(LIBHDF5) dsets_SOURCES = dsets.cpp h5cpputil.cpp -testhdf5_SOURCES = testhdf5.cpp tattr.cpp tfile.cpp th5s.cpp trefer.cpp \ - tvlstr.cpp h5cpputil.cpp +testhdf5_SOURCES = testhdf5.cpp tattr.cpp tcompound.cpp tfile.cpp th5s.cpp \ + trefer.cpp ttypes.cpp tvlstr.cpp h5cpputil.cpp # Tell conclude.am that these are C++ tests. @@ -424,10 +425,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsets.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h5cpputil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tattr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcompound.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testhdf5.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/th5s.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trefer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttypes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tvlstr.Po@am__quote@ .cpp.o: diff --git a/c++/test/h5cpputil.cpp b/c++/test/h5cpputil.cpp index 03f0c9f..e1c3468 100644 --- a/c++/test/h5cpputil.cpp +++ b/c++/test/h5cpputil.cpp @@ -97,9 +97,9 @@ int test_report( int nerrors, const H5std_string& testname ) void issue_fail_msg(const char* where, int line, const char* file_name, const char* message) { - if (GetTestVerbosity()>=VERBO_HI) + //if (GetTestVerbosity()>=VERBO_HI) { - cerr << "--> From " << where << " at line " << line + cerr << "ERROR>>> From " << where << " at line " << line << " in " << file_name << " - " << message << endl << endl; } } diff --git a/c++/test/h5cpputil.h b/c++/test/h5cpputil.h index 0173d2f..7aa77a9 100644 --- a/c++/test/h5cpputil.h +++ b/c++/test/h5cpputil.h @@ -34,8 +34,9 @@ using std::cerr; using std::endl; #endif -int test_report (int, const H5std_string&); +#define SUBTEST(WHAT) {printf(" Subtest: %-52s",WHAT); fflush(stdout);} +int test_report (int, const H5std_string&); void issue_fail_msg(const char* where, int line, const char* file_name, const char* message=""); @@ -68,6 +69,22 @@ template <class Type1, class Type2> } } +template <class Type1, class Type2> + void verify_val_noteq(Type1 x, Type2 value, const char* where, int line, const char* file_name) +{ + if (GetTestVerbosity()>=VERBO_HI) + { + cerr << " Call to routine: " << where << " at line " << line + << " in " << file_name << " had value " << x << endl; + } + if (x == value) + { + cerr << "*** UNEXPECTED VALUE from " << where << " should not be " + << value << " at line " << line << " in " << file_name << endl; + IncTestNumErrs(); + } +} + class InvalidActionException : public Exception { public: InvalidActionException(const H5std_string func_name, const H5std_string message = DEFAULT_MSG); @@ -75,4 +92,31 @@ class InvalidActionException : public Exception { virtual ~InvalidActionException(); }; +/* Prototypes for the test routines */ +void test_attr(void); +void test_compound(void); +void test_file(void); +void test_h5s(void); +void test_reference(void); +void test_types(void); +void test_vlstrings(void); + +/* Prototypes for the cleanup routines */ +void cleanup_attr(void); +void cleanup_compound(void); +void cleanup_file(void); +void cleanup_h5s(void); +void cleanup_reference(void); +void cleanup_types(void); +void cleanup_vlstrings(void); +/* not yet +void cleanup_select(void); +void cleanup_time(void); +void cleanup_vltypes(void); +void cleanup_iterate(void); +void cleanup_array(void); +void cleanup_genprop(void); +void cleanup_misc(void); +*/ + #endif diff --git a/c++/test/tcompound.cpp b/c++/test/tcompound.cpp new file mode 100644 index 0000000..27c759b --- /dev/null +++ b/c++/test/tcompound.cpp @@ -0,0 +1,762 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group (THG). * + * 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://www.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 + tcompound.cpp - HDF5 C++ testing the compound data type functionality + + ***************************************************************************/ + +#ifdef OLD_HEADER_FILENAME +#include <iostream.h> +#else +#include <iostream> +#endif +#include <string> + +#ifndef H5_NO_NAMESPACE +#ifndef H5_NO_STD + using std::cerr; + using std::endl; +#endif // H5_NO_STD +#endif + +#include "testhdf5.h" // C test header file +#include "H5Cpp.h" // C++ API header file + +#ifndef H5_NO_NAMESPACE + using namespace H5; +#endif + +#include "h5cpputil.h" // C++ utilility header file + +/* Number of elements in each test */ +#define NTESTELEM 100000 + +typedef struct complex_t { + double re; + double im; +} complex_t; + + +/*------------------------------------------------------------------------- + * Function: test_compound_1 + * + * Purpose: Tests various things about compound data types. + * + * Return: None + * + * Programmer: Binh-Minh Ribler (using C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_compound_1(void) +{ + // Output message about test being performed + SUBTEST("Compound Data Types"); + try + { + // Create an empty compound datatype + CompType complex_type(sizeof(complex_t)); + + // Add a couple of fields + complex_type.insertMember("real", HOFFSET(complex_t, re), PredType::NATIVE_DOUBLE); + complex_type.insertMember("imaginary", HOFFSET(complex_t, im), PredType::NATIVE_DOUBLE); + + PASSED(); + } // end of try block + + catch (Exception E) { + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_compound_1() + + +/*------------------------------------------------------------------------- + * Function: test_compound_2 + * + * Purpose: Tests a compound type conversion where the source and + * destination are the same except for the order of the + * elements. + * + * Return: None + * + * Programmer: Binh-Minh Ribler (use C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_compound_2(void) +{ + typedef struct { + int a, b, c[4], d, e; + } src_typ_t; + typedef struct { + int e, d, c[4], b, a; + } dst_typ_t; + + src_typ_t *s_ptr; + dst_typ_t *d_ptr; + const int nelmts = NTESTELEM; + const hsize_t four = 4; + int i; + unsigned char *buf=NULL, *orig=NULL, *bkg=NULL; + + // Output message about test being performed + SUBTEST("Compound Element Reordering"); + try + { + /* Sizes should be the same, but be careful just in case */ + buf = (unsigned char*)malloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t))); + bkg = (unsigned char*)malloc(nelmts * sizeof(dst_typ_t)); + orig = (unsigned char*)malloc(nelmts * sizeof(src_typ_t)); + for (i=0; i<nelmts; i++) { + s_ptr = ((src_typ_t*)orig) + i; + s_ptr->a = i*8+0; + s_ptr->b = i*8+1; + s_ptr->c[0] = i*8+2; + s_ptr->c[1] = i*8+3; + s_ptr->c[2] = i*8+4; + s_ptr->c[3] = i*8+5; + s_ptr->d = i*8+6; + s_ptr->e = i*8+7; + } + memcpy(buf, orig, nelmts*sizeof(src_typ_t)); + + /* Build hdf5 datatypes */ + ArrayType* array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four); + + // Create an empty compound datatype + CompType st(sizeof(src_typ_t)); + st.insertMember("a", HOFFSET(src_typ_t, a), PredType::NATIVE_INT); + st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_INT); + st.insertMember("c", HOFFSET(src_typ_t, c), *array_dt); + st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_INT); + st.insertMember("e", HOFFSET(src_typ_t, e), PredType::NATIVE_INT); + array_dt->close(); + + array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four); + + // Create an empty compound datatype + CompType dt(sizeof(dst_typ_t)); + dt.insertMember("a", HOFFSET(dst_typ_t, a), PredType::NATIVE_INT); + dt.insertMember("b", HOFFSET(dst_typ_t, b), PredType::NATIVE_INT); + dt.insertMember("c", HOFFSET(dst_typ_t, c), *array_dt); + dt.insertMember("d", HOFFSET(dst_typ_t, d), PredType::NATIVE_INT); + dt.insertMember("e", HOFFSET(dst_typ_t, e), PredType::NATIVE_INT); + array_dt->close(); + + /* Perform the conversion */ + st.convert(dt, (size_t)nelmts, buf, bkg); + + /* Compare results */ + for (i=0; i<nelmts; i++) { + s_ptr = ((src_typ_t*)orig) + i; + d_ptr = ((dst_typ_t*)buf) + i; + if (s_ptr->a != d_ptr->a || + s_ptr->b != d_ptr->b || + s_ptr->c[0] != d_ptr->c[0] || + s_ptr->c[1] != d_ptr->c[1] || + s_ptr->c[2] != d_ptr->c[2] || + s_ptr->c[3] != d_ptr->c[3] || + s_ptr->d != d_ptr->d || + s_ptr->e != d_ptr->e) { + H5_FAILED(); + cerr << " i=" << i << endl; + cerr << " src={a=" << s_ptr->a << ", b=" << s_ptr->b + << "c=[" << s_ptr->c[0] << "," << s_ptr->c[1] << "," + << s_ptr->c[2] << "," << s_ptr->c[3] << ", d=" + << s_ptr->d << ", e=" << s_ptr->e << "}" << endl; + cerr << " dst={a=" << s_ptr->a << ", b=" << s_ptr->b + << "c=[" << s_ptr->c[0] << "," << s_ptr->c[1] << "," + << s_ptr->c[2] << "," << s_ptr->c[3] << ", d=" + << s_ptr->d << ", e=" << s_ptr->e << "}" << endl; + } + } + + /* Release resources */ + free(buf); + free(bkg); + free(orig); + s_ptr = NULL; + d_ptr = NULL; + st.close(); + dt.close(); + + PASSED(); + } // end of try block + + catch (Exception E) { + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_compound_2() + + +/*------------------------------------------------------------------------- + * Function: test_compound_3 + * + * Purpose: Tests compound conversions where the source and destination + * are the same except the destination is missing a couple + * members which appear in the source. + * + * Return: None + * + * Programmer: Binh-Minh Ribler (use C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_compound_3(void) +{ + typedef struct { + int a, b, c[4], d, e; + } src_typ_t; + typedef struct { + int a, c[4], e; + } dst_typ_t; + + src_typ_t *s_ptr; + dst_typ_t *d_ptr; + int i; + const int nelmts = NTESTELEM; + const hsize_t four = 4; + unsigned char *buf=NULL, *orig=NULL, *bkg=NULL; + + // Output message about test being performed + SUBTEST("Compound Datatype Subset Conversions"); + try + { + /* Initialize */ + buf = (unsigned char*)malloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t))); + bkg = (unsigned char*)malloc(nelmts * sizeof(dst_typ_t)); + orig = (unsigned char*)malloc(nelmts * sizeof(src_typ_t)); + for (i=0; i<nelmts; i++) { + s_ptr = ((src_typ_t*)orig) + i; + s_ptr->a = i*8+0; + s_ptr->b = i*8+1; + s_ptr->c[0] = i*8+2; + s_ptr->c[1] = i*8+3; + s_ptr->c[2] = i*8+4; + s_ptr->c[3] = i*8+5; + s_ptr->d = i*8+6; + s_ptr->e = i*8+7; + } + memcpy(buf, orig, nelmts*sizeof(src_typ_t)); + + /* Build hdf5 datatypes */ + ArrayType* array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four); + + // Create an empty compound datatype + CompType st(sizeof(src_typ_t)); + st.insertMember("a", HOFFSET(src_typ_t, a), PredType::NATIVE_INT); + st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_INT); + st.insertMember("c", HOFFSET(src_typ_t, c), *array_dt); + st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_INT); + st.insertMember("e", HOFFSET(src_typ_t, e), PredType::NATIVE_INT); + array_dt->close(); + + array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four); + + // Create an empty compound datatype + CompType dt(sizeof(dst_typ_t)); + dt.insertMember("a", HOFFSET(dst_typ_t, a), PredType::NATIVE_INT); + dt.insertMember("c", HOFFSET(dst_typ_t, c), *array_dt); + dt.insertMember("e", HOFFSET(dst_typ_t, e), PredType::NATIVE_INT); + array_dt->close(); + + /* Perform the conversion */ + st.convert(dt, (size_t)nelmts, buf, bkg); + + /* Compare results */ + for (i=0; i<nelmts; i++) { + s_ptr = ((src_typ_t*)orig) + i; + d_ptr = ((dst_typ_t*)buf) + i; + if (s_ptr->a != d_ptr->a || + s_ptr->c[0] != d_ptr->c[0] || + s_ptr->c[1] != d_ptr->c[1] || + s_ptr->c[2] != d_ptr->c[2] || + s_ptr->c[3] != d_ptr->c[3] || + s_ptr->e != d_ptr->e) { + H5_FAILED(); + cerr << " i=" << i << endl; + cerr << " src={a=" << s_ptr->a << ", b=" << s_ptr->b + << ", c=[" << s_ptr->c[0] << "," << s_ptr->c[1] << "," + << s_ptr->c[2] << "," << s_ptr->c[3] << "], d=" + << s_ptr->d << ", e=" << s_ptr->e << "}" << endl; + cerr << " dst={a=" << d_ptr->a + << ", c=[" << d_ptr->c[0] << "," << d_ptr->c[1] << "," + << d_ptr->c[2] << "," << d_ptr->c[3] << "], e=" + << d_ptr->e << "}" << endl; + } // if + } // for + + /* Release resources */ + free(buf); + free(bkg); + free(orig); + s_ptr = NULL; + d_ptr = NULL; + st.close(); + dt.close(); + + PASSED(); + } // end of try block + + catch (Exception E) { + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_compound_3() + + +/*------------------------------------------------------------------------- + * Function: test_compound_4 + * + * Purpose: Tests compound conversions when the destination has the same + * fields as the source but one or more of the fields are + * smaller. + * + * Return: None + * + * Programmer: Binh-Minh Ribler (use C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_compound_4(void) +{ + + typedef struct { + int a, b, c[4], d, e; + } src_typ_t; + + typedef struct { + short b; + int a, c[4]; + short d; + int e; + } dst_typ_t; + + src_typ_t *s_ptr; + dst_typ_t *d_ptr; + int i; + const int nelmts = NTESTELEM; + const hsize_t four = 4; + unsigned char *buf=NULL, *orig=NULL, *bkg=NULL; + + // Output message about test being performed + SUBTEST("Compound Element Shrinking & Reordering"); + try + { + /* Sizes should be the same, but be careful just in case */ + buf = (unsigned char*)malloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t))); + bkg = (unsigned char*)malloc(nelmts * sizeof(dst_typ_t)); + orig = (unsigned char*)malloc(nelmts * sizeof(src_typ_t)); + for (i=0; i<nelmts; i++) { + s_ptr = ((src_typ_t*)orig) + i; + s_ptr->a = i*8+0; + s_ptr->b = (i*8+1) & 0x7fff; + s_ptr->c[0] = i*8+2; + s_ptr->c[1] = i*8+3; + s_ptr->c[2] = i*8+4; + s_ptr->c[3] = i*8+5; + s_ptr->d = (i*8+6) & 0x7fff; + s_ptr->e = i*8+7; + } + memcpy(buf, orig, nelmts*sizeof(src_typ_t)); + + /* Build hdf5 datatypes */ + ArrayType* array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four); + + // Create an empty compound datatype + CompType st(sizeof(src_typ_t)); + st.insertMember("a", HOFFSET(src_typ_t, a), PredType::NATIVE_INT); + st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_INT); + st.insertMember("c", HOFFSET(src_typ_t, c), *array_dt); + st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_INT); + st.insertMember("e", HOFFSET(src_typ_t, e), PredType::NATIVE_INT); + array_dt->close(); + + array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four); + + // Create an empty compound datatype + CompType dt(sizeof(dst_typ_t)); + dt.insertMember("a", HOFFSET(dst_typ_t, a), PredType::NATIVE_INT); + dt.insertMember("b", HOFFSET(dst_typ_t, b), PredType::NATIVE_SHORT); + dt.insertMember("c", HOFFSET(dst_typ_t, c), *array_dt); + dt.insertMember("d", HOFFSET(dst_typ_t, d), PredType::NATIVE_SHORT); + dt.insertMember("e", HOFFSET(dst_typ_t, e), PredType::NATIVE_INT); + array_dt->close(); + + /* Perform the conversion */ + st.convert(dt, (size_t)nelmts, buf, bkg); + + /* Compare results */ + for (i=0; i<nelmts; i++) { + s_ptr = ((src_typ_t*)orig) + i; + d_ptr = ((dst_typ_t*)buf) + i; + if (s_ptr->a != d_ptr->a || + s_ptr->b != d_ptr->b || + s_ptr->c[0] != d_ptr->c[0] || + s_ptr->c[1] != d_ptr->c[1] || + s_ptr->c[2] != d_ptr->c[2] || + s_ptr->c[3] != d_ptr->c[3] || + s_ptr->d != d_ptr->d || + s_ptr->e != d_ptr->e) + { + H5_FAILED(); + cerr << " i=" << i << endl; + cerr << " src={a=" << s_ptr->a << ", b=" << s_ptr->b + << "c=[" << s_ptr->c[0] << "," << s_ptr->c[1] << "," + << s_ptr->c[2] << "," << s_ptr->c[3] << ", d=" + << s_ptr->d << ", e=" << s_ptr->e << "}" << endl; + cerr << " dst={a=" << d_ptr->a << ", b=" << d_ptr->b + << "c=[" << d_ptr->c[0] << "," << d_ptr->c[1] << "," + << d_ptr->c[2] << "," << d_ptr->c[3] << ", d=" + << d_ptr->d << ", e=" << d_ptr->e << "}" << endl; + } // if + } // for + + /* Release resources */ + free(buf); + free(bkg); + free(orig); + s_ptr = NULL; + d_ptr = NULL; + st.close(); + dt.close(); + + PASSED(); + } // end of try block + + catch (Exception E) { + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_compound_4() + + +/*------------------------------------------------------------------------- + * Function: test_compound_5 + * + * Purpose: Many versions of HDF5 have a bug in the optimized compound + * datatype conversion function, H5T_conv_struct_opt(), which + * is triggered when the top-level type contains a struct + * which must undergo a conversion. + * + * Return: None + * + * Programmer: Binh-Minh Ribler (use C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_compound_5(void) +{ + typedef struct { + char name[16]; + short tdim; + short coll_ids[4]; + } src_typ_t; + + typedef struct { + char name[16]; + short tdim; + int coll_ids[4]; + } dst_typ_t; + + hsize_t dims[1] = {4}; + src_typ_t src[2] = {{"one", 102, {104, 105, 106, 107}}, + {"two", 202, {204, 205, 206, 207}}}; + dst_typ_t *dst; + void *buf = calloc(2, sizeof(dst_typ_t)); + void *bkg = calloc(2, sizeof(dst_typ_t)); + + // Output message about test being performed + SUBTEST("Optimized Struct Converter"); + try + { + + /* Build datatypes */ + ArrayType* array_dt = new ArrayType(PredType::NATIVE_SHORT, 1, dims); + CompType short_array(4*sizeof(short)); + short_array.insertMember("_", 0, *array_dt); + array_dt->close(); + + CompType int_array(4*sizeof(int)); + array_dt = new ArrayType(PredType::NATIVE_INT, 1, dims); + int_array.insertMember("_", 0, *array_dt); + array_dt->close(); + + StrType strg(PredType::C_S1, 16); + CompType src_type(sizeof(src_typ_t)); + src_type.insertMember("name", HOFFSET(src_typ_t, name), strg); + src_type.insertMember("tdim", HOFFSET(src_typ_t, tdim), PredType::NATIVE_SHORT); + src_type.insertMember("coll_ids", HOFFSET(src_typ_t, coll_ids), short_array); + + CompType dst_type(sizeof(dst_typ_t)); + dst_type.insertMember("name", HOFFSET(dst_typ_t, name), strg); + dst_type.insertMember("tdim", HOFFSET(dst_typ_t, tdim), PredType::NATIVE_SHORT); + dst_type.insertMember("coll_ids", HOFFSET(dst_typ_t, coll_ids), int_array); + + /* Convert data */ + memcpy(buf, src, sizeof(src)); + src_type.convert(dst_type, (size_t)2, buf, bkg); + dst = (dst_typ_t*)buf; + + /* Cleanup */ + src_type.close(); + dst_type.close(); + strg.close(); + short_array.close(); + int_array.close(); + + /* Check results */ + if (memcmp(src[1].name, dst[1].name, sizeof(src[1].name)) || + src[1].tdim!=dst[1].tdim || + src[1].coll_ids[0]!=dst[1].coll_ids[0] || + src[1].coll_ids[1]!=dst[1].coll_ids[1] || + src[1].coll_ids[2]!=dst[1].coll_ids[2] || + src[1].coll_ids[3]!=dst[1].coll_ids[3]) + { H5_FAILED(); } + + /* Free memory buffers */ + free(buf); + free(bkg); + dst = NULL; + PASSED(); + } // end of try block + + catch (Exception E) { + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_compound_5() + + +/*------------------------------------------------------------------------- + * Function: test_compound_6 + * + * Purpose: Tests compound conversions when the destination has the same + * fields as the source but one or more of the fields are + * larger. + * + * Return: None + * + * Programmer: Binh-Minh Ribler (use C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_compound_6(void) +{ + typedef struct { + short b; + short d; + } src_typ_t; + + typedef struct { + long b; + long d; + } dst_typ_t; + + src_typ_t *s_ptr; + dst_typ_t *d_ptr; + int i; + const int nelmts = NTESTELEM; + unsigned char *buf=NULL, *orig=NULL, *bkg=NULL; + + // Output message about test being performed + SUBTEST("Compound Element Growing"); + try + { + /* Sizes should be the same, but be careful just in case */ + buf = (unsigned char*)malloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t))); + bkg = (unsigned char*)malloc(nelmts * sizeof(dst_typ_t)); + orig = (unsigned char*)malloc(nelmts * sizeof(src_typ_t)); + for (int i=0; i<nelmts; i++) { + s_ptr = ((src_typ_t*)orig) + i; + s_ptr->b = (i*8+1) & 0x7fff; + s_ptr->d = (i*8+6) & 0x7fff; + } + memcpy(buf, orig, nelmts*sizeof(src_typ_t)); + + /* Build hdf5 datatypes */ + CompType st(sizeof(src_typ_t)); + st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_SHORT); + st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_SHORT); + + CompType dt(sizeof(dst_typ_t)); + dt.insertMember("b", HOFFSET(dst_typ_t, b), PredType::NATIVE_LONG); + dt.insertMember("d", HOFFSET(dst_typ_t, d), PredType::NATIVE_LONG); + + /* Perform the conversion */ + st.convert(dt, (size_t)nelmts, buf, bkg); + + /* Compare results */ + for (i=0; i<nelmts; i++) { + s_ptr = ((src_typ_t*)orig) + i; + d_ptr = ((dst_typ_t*)buf) + i; + if (s_ptr->b != d_ptr->b || + s_ptr->d != d_ptr->d) + { + H5_FAILED(); + cerr << " i=" << i << endl; + cerr << " src={b=" << s_ptr->b << ", d=" << s_ptr->d + << "}" << endl; + cerr << " dst={b=" << d_ptr->b << ", d=" << d_ptr->d + << "}" << endl; + } // if + } // for + + /* Release resources */ + free(buf); + free(bkg); + free(orig); + s_ptr = NULL; + d_ptr = NULL; + st.close(); + dt.close(); + + PASSED(); + } // end of try block + + catch (Exception E) { + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_compound_6() + +/*------------------------------------------------------------------------- + * Function: test_compound_7 + * + * Purpose: Tests inserting fields into compound datatypes when the field + * overlaps the end of the compound datatype. + * + * Return: None + * + * Programmer: Binh-Minh Ribler (use C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_compound_7(void) +{ + typedef struct { + int a; + float b; + long c; + } s1_typ_t; + + typedef struct { + int a; + float b; + long c; + double d; + } s2_typ_t; + + // Output message about test being performed + SUBTEST("Compound Element Insertion"); + try + { + CompType tid1(sizeof(s1_typ_t)); + + tid1.insertMember("a", HOFFSET(s1_typ_t,a),PredType::NATIVE_INT); + tid1.insertMember("b", HOFFSET(s1_typ_t,b),PredType::NATIVE_FLOAT); + tid1.insertMember("c", HOFFSET(s1_typ_t,c),PredType::NATIVE_LONG); + + size_t type_size = tid1.getSize(); + verify_val(type_size, sizeof(s1_typ_t), "DataType::getSize", __LINE__, __FILE__); + + CompType tid2; + tid2.copy(tid1); + + type_size = tid2.getSize(); + verify_val_noteq(type_size, sizeof(s2_typ_t), "DataType::getSize", __LINE__, __FILE__); + + /* Should not be able to insert field past end of compound datatype */ + try { + tid2.insertMember("d", HOFFSET(s2_typ_t, d), PredType::NATIVE_DOUBLE); + // Should FAIL but didn't, so throw an invalid action exception + throw InvalidActionException("CompType::insertMember", "Attempted to insert field past end of compound data type."); + } catch (DataTypeIException err) {} + + /* Release resources */ + tid1.close(); + tid2.close(); + + PASSED(); + } // end of try block + + catch (Exception E) { + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_compound_7() + + +/*------------------------------------------------------------------------- + * Function: test_compound + * + * Purpose: Main compound datatype testing routine + * + * Return: None + * + * Programmer: Binh-Minh Ribler + * January 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void test_compound(void) +{ + // Output message about test being performed + MESSAGE(5, ("Testing Compound Data Type operations\n")); + + test_compound_1(); // various things about compound data types + test_compound_2(); // compound element reordering + test_compound_3(); // compound datatype subset conversions + test_compound_4(); // compound element shrinking & reordering + test_compound_5(); // optimized struct converter + test_compound_6(); // compound element growing + test_compound_7(); // compound element insertion +} // test_compound() + + +/*------------------------------------------------------------------------- + * Function: cleanup_compound + * + * Purpose: Cleanup temporary test files - nothing at this time. + * + * Return: none + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +cleanup_compound(void) +{ +} // cleanup_file diff --git a/c++/test/testhdf5.cpp b/c++/test/testhdf5.cpp index f157000..22d14b1 100644 --- a/c++/test/testhdf5.cpp +++ b/c++/test/testhdf5.cpp @@ -60,9 +60,11 @@ #include "H5Cpp.h" // C++ API header file #ifndef H5_NO_NAMESPACE -using namespace H5; + using namespace H5; #endif /* !H5_NO_NAMESPACE */ +#include "h5cpputil.h" // C++ utilility header file + int main(int argc, char *argv[]) { @@ -79,6 +81,8 @@ main(int argc, char *argv[]) AddTest("reference", test_reference, cleanup_reference, "References", NULL); // testing variable-length strings in tvlstr.cpp AddTest("vlstrings", test_vlstrings, cleanup_vlstrings, "Variable-Length Strings", NULL); + AddTest("types", test_types, cleanup_types, "Generic Data Types", NULL); + AddTest("compound", test_compound, cleanup_compound, "Compound Data Types", NULL); /* Comment out tests that are not done yet. - BMR, Feb 2001 AddTest("select", test_select, cleanup_select, "Selections", NULL); AddTest("time", test_time, cleanup_time, "Time Datatypes", NULL); @@ -86,8 +90,14 @@ main(int argc, char *argv[]) AddTest("iterate", test_iterate, cleanup_iterate, "Group & Attribute Iteration", NULL); AddTest("array", test_array, cleanup_array, "Array Datatypes", NULL); AddTest("genprop", test_genprop, cleanup_genprop, "Generic Properties", NULL); + AddTest("id", test_ids, NULL, "User-Created Identifiers", NULL); + Comment out tests that are not done yet */ +/* Tentative - BMR 2007/1/12 + AddTest("datatypes", test_dtypes, cleanup_dtypes, "Data Types", NULL); + AddTest("enum", test_enum, cleanup_enum, "Enum Data Types", NULL); +*/ /* Display testing information */ TestInfo(argv[0]); diff --git a/c++/test/trefer.cpp b/c++/test/trefer.cpp index 9ef6240..19a8a6b 100644 --- a/c++/test/trefer.cpp +++ b/c++/test/trefer.cpp @@ -12,13 +12,12 @@ * access to either file, you may request a copy from help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/*********************************************************** -* -* Test program: trefer -* -* Test the Reference functionality -* -*************************************************************/ +/***************************************************************************** + FILE + trefer.cpp - HDF5 C++ testing the functionalities associated with the C + Reference interface (H5R) + + ***************************************************************************/ #ifdef OLD_HEADER_FILENAME #include <iostream.h> @@ -38,7 +37,7 @@ #include "H5Cpp.h" // C++ API header file #ifndef H5_NO_NAMESPACE -using namespace H5; + using namespace H5; #endif #include "h5cpputil.h" // C++ utilility header file @@ -230,7 +229,7 @@ test_reference_obj(void) // Dereference group object by ctor and using dataset to specify // location Group new_group(dataset, &rbuf[2]); - H5std_string read_comment3 = group.getComment(".", 10); + H5std_string read_comment3 = new_group.getComment(".", 10); verify_val(read_comment3, write_comment, "Group::getComment", __LINE__, __FILE__); group.close(); diff --git a/c++/test/ttypes.cpp b/c++/test/ttypes.cpp new file mode 100644 index 0000000..906ed23 --- /dev/null +++ b/c++/test/ttypes.cpp @@ -0,0 +1,810 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group (THG). * + * 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://www.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 + ttypes.cpp - HDF5 C++ testing the general data type functionality + + ***************************************************************************/ + +#ifdef OLD_HEADER_FILENAME +#include <iostream.h> +#else +#include <iostream> +#endif +#include <string> + +#ifndef H5_NO_NAMESPACE +#ifndef H5_NO_STD + using std::cerr; + using std::endl; +#endif // H5_NO_STD +#endif + +#include "testhdf5.h" // C test header file +#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 DATAFILE("ttypes.h5"); + +#define NTESTS 1 + +/* Number of elements in each test */ +#define NTESTELEM 100000 + +/* Define if you want to see a count of overflows */ +#undef SHOW_OVERFLOWS + +/* + * Offset from alinged memory returned by malloc(). This can be used to test + * that type conversions handle non-aligned buffers correctly. + */ +#define ALIGNMENT 1 + +/* + * Define if you want to test alignment code on a machine that doesn't + * normally require alignment. When set, all native data types must be aligned + * on a byte boundary equal to the data size. + */ +#define TEST_ALIGNMENT + +/* Alignment test stuff */ +#ifdef TEST_ALIGNMENT +#define H5T_PACKAGE +#include "H5Tpkg.h" +#endif +#define SET_ALIGNMENT(TYPE,VAL) \ + H5T_NATIVE_##TYPE##_ALIGN_g=MAX(H5T_NATIVE_##TYPE##_ALIGN_g, VAL) + +const char *FILENAME[] = { + "dtypes1.h5", + "dtypes2.h5", + "dtypes3.h5", + NULL +}; + +/* + * Count up or down depending on whether the machine is big endian or little + * endian. If local variable `endian' is H5T_ORDER_BE then the result will + * be I, otherwise the result will be Z-(I+1). + */ +#define ENDIAN(Z,I) (H5T_ORDER_BE==endian?(I):(Z)-((I)+1)) + + +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; + +/* Count the number of overflows */ +#ifdef SHOW_OVERFLOWS +static int noverflows_g = 0; +#endif + +/* Skip overflow tests if non-zero */ +static int skip_overflow_tests_g = 0; + +/* Don't use hardware conversions if set */ +static int without_hardware_g = 0; + +/* Count opaque conversions */ +static int num_opaque_conversions_g = 0; + +/* + * Although we check whether a floating point overflow generates a SIGFPE and + * turn off overflow tests in that case, it might still be possible for an + * overflow condition to occur. Once a SIGFPE is raised the program cannot + * be allowed to continue (cf. Posix signals) so in order to recover from a + * SIGFPE we run tests that might generate one in a child process. + */ +#if defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID) +# define HANDLE_SIGFPE +#endif + +/* Allocates memory aligned on a certain boundary. */ +#define aligned_malloc(Z) ((void*)((char*)malloc(ALIGNMENT+Z)+ALIGNMENT)) +#define aligned_free(M) free((char*)(M)-ALIGNMENT) + + +/*------------------------------------------------------------------------- + * Function: fpe_handler + * + * Purpose: Exit with 255 + * + * Return: void + * + * Programmer: Robb Matzke + * Monday, July 6, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +fpe_handler(int UNUSED signo) +{ + SKIPPED(); + puts(" Test skipped due to SIGFPE."); +#ifndef HANDLE_SIGFPE + puts(" Remaining tests could not be run."); + puts(" Please turn off SIGFPE on overflows and try again."); +#endif + exit(255); +} + + +/*------------------------------------------------------------------------- + * Function: overflow_handler + * + * Purpose: Gets called for all data type conversion overflows. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * Tuesday, July 7, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifdef SHOW_OVERFLOWS +static herr_t +overflow_handler(hid_t UNUSED src_id, hid_t UNUSED dst_id, + void UNUSED *src_buf, void UNUSED *dst_buf) +{ + noverflows_g++; + return -1; +} +#endif + + +/*------------------------------------------------------------------------- + * Function: test_classes + * + * Purpose: Test type classes + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Binh-Minh Ribler (using C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_classes(void) +{ + SUBTEST("PredType::getClass()"); + try { + // PredType::NATIVE_INT should be in H5T_INTEGER class + H5T_class_t tcls = PredType::NATIVE_INT.getClass(); + if (H5T_INTEGER!=tcls) { + H5_FAILED(); + puts(" Invalid type class for H5T_NATIVE_INT"); + } + + // PredType::NATIVE_DOUBLE should be in H5T_FLOAT class + tcls = PredType::NATIVE_DOUBLE.getClass(); + if (H5T_FLOAT!=tcls) { + H5_FAILED(); + puts(" Invalid type class for H5T_NATIVE_DOUBLE"); + } + PASSED(); + } // end of try block + catch (DataTypeIException E) { + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} + +/*------------------------------------------------------------------------- + * Function: test_copy + * + * Purpose: Test datatype copy functionality + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Binh-Minh Ribler (using C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_copy(void) +{ + hid_t a_copy; + herr_t status; + + //MESSAGE(5, ("DataType::copy() and DataType::operator=")); + SUBTEST("DataType::copy() and DataType::operator="); + try { + // Test copying from a predefined datatype using DataType::operator= + DataType assigned_type; + assigned_type = PredType::NATIVE_SHORT; + + // Test copying a predefined type using DataType::copy + DataType copied_type; + copied_type.copy (PredType::STD_B8LE); + + // Test copying a user-defined type using DataType::operator= + DataType assigned_usertype; + assigned_usertype = copied_type; + + // Test copying from a user-defined datatype using DataType::copy + DataType copied_usertype; + copied_usertype.copy(copied_type); + + // Test copying a user-defined int type using DataType::operator= + IntType orig_int(PredType::STD_B8LE); + DataType generic_type; + generic_type = orig_int; + + // Test copying an integer predefined type + IntType new_int_type(PredType::STD_B8LE); + + // Test copying an int predefined type using DataType::operator= + IntType another_int_type; + another_int_type = new_int_type; + + PASSED(); + } + catch (DataTypeIException E) { + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} + + +/*------------------------------------------------------------------------- + * Function: test_query + * + * Purpose: Tests query functions of compound and enumeration types. + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Binh-Minh Ribler (use C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +const H5std_string CompT_NAME("Compound_type"); +const H5std_string EnumT_NAME("Enum_type"); + +static void test_query(void) +{ + typedef struct { + int a; + float b; + long c; + double d; + } s_type_t; + char filename[1024]; + short enum_val; + + // Output message about test being performed + SUBTEST("Query functions of compound and enumeration types"); + try + { + /* Create File */ + H5File file(FILENAME[2], H5F_ACC_TRUNC); + + /* Create a compound datatype */ + CompType tid1(sizeof(s_type_t)); + + tid1.insertMember("a", HOFFSET(s_type_t, a), PredType::NATIVE_INT); + tid1.insertMember("b", HOFFSET(s_type_t, b), PredType::NATIVE_FLOAT); + tid1.insertMember("c", HOFFSET(s_type_t, c), PredType::NATIVE_LONG); + tid1.insertMember("d", HOFFSET(s_type_t, d), PredType::NATIVE_DOUBLE); + + /* Create a enumerate datatype */ + EnumType tid2(sizeof(short)); + + tid2.insert("RED", (enum_val=0,&enum_val)); + tid2.insert("GREEN", (enum_val=1,&enum_val)); + tid2.insert("BLUE", (enum_val=2,&enum_val)); + tid2.insert("ORANGE", (enum_val=3,&enum_val)); + tid2.insert("YELLOW", (enum_val=4,&enum_val)); + + /* Query member number and member index by name, for compound type */ + int nmembs = tid1.getNmembers(); + verify_val(nmembs, 4, "CompType::getNmembers()", __LINE__, __FILE__); + + int index = tid1.getMemberIndex("c"); + verify_val(index, 2, "CompType::getMemberIndex()", __LINE__, __FILE__); + + /* Query member number and member index by name, for enumeration type. */ + nmembs = tid2.getNmembers(); + verify_val(nmembs, 5, "EnumType::getNmembers()", __LINE__, __FILE__); + + index = tid2.getMemberIndex("ORANGE"); + verify_val(index, 3, "EnumType::getMemberIndex()", __LINE__, __FILE__); + + /* Commit compound datatype and close it */ + tid1.commit(file, CompT_NAME); + tid1.close(); + + /* Commit enumeration datatype and close it */ + tid2.commit(file, EnumT_NAME); + tid2.close(); + + /* Open the datatype for query */ + tid1 = file.openCompType(CompT_NAME); + + tid2 = file.openEnumType(EnumT_NAME); + + /* Query member number and member index by name, for compound type */ + nmembs = tid1.getNmembers(); + verify_val(nmembs, 4, "CompType::getNmembers()", __LINE__, __FILE__); + + index = tid1.getMemberIndex("c"); + verify_val(index, 2, "CompType::getMemberIndex()", __LINE__, __FILE__); + + /* Query member number and member index by name, for enumeration type */ + nmembs = tid2.getNmembers(); + verify_val(nmembs, 5, "EnumType::getNmembers()", __LINE__, __FILE__); + + index = tid2.getMemberIndex("ORANGE"); + verify_val(index, 3, "EnumType::getMemberIndex()", __LINE__, __FILE__); + + /* Close data types and file */ + tid1.close(); + tid2.close(); + file.close(); + + PASSED(); + } // end of try block + catch (Exception E) { + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_query + + +/*------------------------------------------------------------------------- + * Function: test_transient + * + * Purpose: Tests transient data types. + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Binh-Minh Ribler (use C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +const char* filename1("dtypes1.h5"); +static void test_transient () +{ + static hsize_t ds_size[2] = {10, 20}; + + //MESSAGE(5, ("transient data types")); + SUBTEST("Transient data types"); + try { + + H5File file(filename1, H5F_ACC_TRUNC); + DataSpace space(2, ds_size, ds_size); + + /* Predefined types cannot be modified or closed */ +// PredType::NATIVE_INT is a constant and cannot make a call, don't need these tests + + /* Copying a predefined type results in a modifiable copy */ + IntType type(PredType::NATIVE_INT); + type.setPrecision(256); + + /* It should not be possible to create an attribute for a transient type */ + try { + Attribute attr(type.createAttribute("attr1", PredType::NATIVE_INT, space)); + // Should FAIL but didn't, so throw an invalid action exception + throw InvalidActionException("H5Object::createAttribute", "Attempted to commit a predefined datatype."); + } catch (AttributeIException err) {} + + /* Create a dataset from a transient data type */ +// type.close(); - put printf in H5Tclose to make sure it's closed + type.copy(PredType::NATIVE_INT); + DataSet dset(file.createDataSet("dset1", type, space)); + + /* The type returned from a dataset should not be modifiable */ + IntType itype(dset); + try { + itype.setPrecision(256); + + // Should FAIL but didn't, so throw an invalid action exception + throw InvalidActionException("PredType::setPrecision", "Dataset data types should not be modifiable!"); + } catch (DataTypeIException err) {} + + itype.close(); + + /* + * Get the dataset data type by applying H5Tcopy() to the dataset. The + * result should be modifiable. + */ + itype.copy(dset); + itype.setPrecision(256); + + /* + * Close the dataset and reopen it, testing that its type is still + * read-only. <--- how come modifiable below? + */ + dset.close(); + //if (H5Dclose (dset)<0) printf("goto error in C\n"); + dset = file.openDataSet("dset1"); + //if ((dset=H5Dopen (file, "dset1"))<0) printf("goto error in C\n"); + + /* + * Get the dataset data type by applying H5Tcopy() to the dataset. The + * result should be modifiable. + */ + itype.copy(dset); + itype.setPrecision(256); + itype.close(); + + // Close objects and file. + dset.close(); + file.close(); + type.close(); + space.close(); + PASSED(); + } // end of try block + catch (Exception E) { + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_transient + + +/*------------------------------------------------------------------------- + * Function: test_named + * + * Purpose: Tests named data types. + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Binh-Minh Ribler (use C version) + * January, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +const H5std_string filename2("dtypes2.h5"); +static void test_named () +{ + herr_t status; + static hsize_t ds_size[2] = {10, 20}; + hsize_t i; + unsigned attr_data[10][20]; + char filename[1024]; + + //MESSAGE(5, ("named data types")); + SUBTEST("Named data types"); + try { + +// h5_fixname(FILENAME[1], fapl_id, filename, sizeof filename); + H5File file(filename2, H5F_ACC_TRUNC); + + DataSpace space(2, ds_size, ds_size); + + /* Predefined types cannot be committed */ + try { +PredType nativeint(PredType::NATIVE_INT); +nativeint.commit(file, "test_named_1 (should not exist)"); + //PredType::NATIVE_INT.commit(file, "test_named_1 (should not exist)"); + // Should FAIL but didn't, so throw an invalid action exception + throw InvalidActionException("PredType::commit", "Attempted to commit a predefined datatype."); + } catch (DataTypeIException err) {} + +/* + H5E_BEGIN_TRY { + status = H5Tcommit (file, "test_named_1 (should not exist)", + H5T_NATIVE_INT); + } H5E_END_TRY; + if (status>=0) { + H5_FAILED(); + puts (" Predefined types should not be committable!"); + printf("goto error in C\n"); + } +*/ + + /* Copy a predefined data type and commit the copy */ + IntType itype(PredType::NATIVE_INT); + //if ((type = H5Tcopy (H5T_NATIVE_INT))<0) printf("goto error in C\n"); + + itype.commit(file, "native-int"); + //if (H5Tcommit (file, "native-int", type)<0) printf("goto error in C\n");0, + + if (itype.committed() <= 0) + cerr << "IntType::committed() returned false" << endl; + +/* + if ((status=H5Tcommitted (type))<0) printf("goto error in C\n"); + if (0==status) { + H5_FAILED(); + puts (" H5Tcommitted() returned false!"); + printf("goto error in C\n"); + } +*/ + + /* We should not be able to modify a type after it has been committed. */ + try { + itype.setPrecision(256); + + // Should FAIL but didn't, so throw an invalid action exception + throw InvalidActionException("IntType::setPrecision", "Attempted to modify a committed datatype."); + } catch (DataTypeIException err) {} + +/* + H5E_BEGIN_TRY { + status = H5Tset_precision (type, 256); + } H5E_END_TRY; + if (status>=0) { + H5_FAILED(); + puts (" Committed type is not constant!"); + printf("goto error in C\n"); + } +*/ + /* We should not be able to re-commit a committed type */ + try { + itype.commit(file, "test_named_2 (should not exist)"); + + // Should FAIL but didn't, so throw an invalid action exception + throw InvalidActionException("IntType::commit", "Attempted to re-commit a committed data type."); + } catch (DataTypeIException err) {} + +/* + H5E_BEGIN_TRY { + status = H5Tcommit(file, "test_named_2 (should not exist)", type); + } H5E_END_TRY; + if (status>=0) { + H5_FAILED(); + puts (" Committed types should not be recommitted!"); + printf("goto error in C\n"); + } +*/ + + /* It should be possible to define an attribute for the named type */ + Attribute attr1 = itype.createAttribute("attr1", PredType::NATIVE_UCHAR, space); + //if ((attr1=H5Acreate (type, "attr1", H5T_NATIVE_UCHAR, space, +// H5P_DEFAULT))<0) printf("goto error in C\n"); + + + for (i=0; i<ds_size[0]*ds_size[1]; i++) attr_data[0][i] = (int)i;/*tricky*/ + + attr1.write(PredType::NATIVE_UINT, attr_data); + attr1.close(); + //if (H5Awrite(attr1, H5T_NATIVE_UINT, attr_data)<0) printf("goto error in C\n"); + //if (H5Aclose (attr1)<0) printf("goto error in C\n"); + + /* + * Copying a committed type should result in a transient type which is + * not locked. + */ + IntType trans_type; + trans_type.copy(itype); + bool iscommitted = trans_type.committed(); + verify_val(iscommitted, 0, "DataType::committed() - Copying a named type should result in a transient type!", __LINE__, __FILE__); +/* + if ((t2 = H5Tcopy (type))<0) printf("goto error in C\n"); + if ((status=H5Tcommitted (t2))<0) printf("goto error in C\n"); + if (status) { + H5_FAILED(); + puts (" Copying a named type should result in a transient type!"); + printf("goto error in C\n"); + } +*/ + trans_type.setPrecision(256); + trans_type.close(); + //if (H5Tset_precision (t2, 256)<0) printf("goto error in C\n"); + //if (H5Tclose (t2)<0) printf("goto error in C\n"); + + /* + * Close the committed type and reopen it. It should return a named type. + */ +/* This had something to do with the way IntType was returned and assigned +and caused itype.committed not working correctly. So, use another_type for +now. + itype = file.openIntType("native-int"); + iscommitted = itype.committed(); +*/ + IntType another_type = file.openIntType("native-int"); + iscommitted = another_type.committed(); + if (!iscommitted) + throw InvalidActionException("IntType::committed()", "Opened named types should be named types!"); + +/* + if (H5Tclose (type)<0) printf("goto error in C\n"); + if ((type=H5Topen (file, "native-int"))<0) printf("goto error in C\n"); + if ((status=H5Tcommitted (type))<0) printf("goto error in C\n"); + if (!status) { + H5_FAILED(); + puts (" Opened named types should be named types!"); + printf("goto error in C\n"); + } + */ + /* Create a dataset that uses the named type */ + DataSet dset = file.createDataSet("dset1", itype, space); + //if ((dset = H5Dcreate (file, "dset1", type, space, H5P_DEFAULT))<0) + + /* Get the dataset's data type and make sure it's a named type */ + DataType *ds_type = new DataType(dset.getDataType()); + iscommitted = ds_type->committed(); + if (!iscommitted) + throw InvalidActionException("IntType::committed()", "1 Dataset type should be named type!"); + +/* + if ((t2 = H5Dget_type (dset))<0) printf("goto error in C\n"); + if ((status=H5Tcommitted (t2))<0) printf("goto error in C\n"); + if (!status) { + H5_FAILED(); + puts (" Dataset type should be a named type!"); + printf("goto error in C\n"); + } +*/ + + /* Close the dataset, then close its type, then reopen the dataset */ + dset.close(); + ds_type->close(); + //if (H5Dclose (dset)<0) printf("goto error in C\n"); + //if (H5Tclose (t2)<0) printf("goto error in C\n"); + + dset = file.openDataSet("dset1"); + //if ((dset = H5Dopen (file, "dset1"))<0) printf("goto error in C\n"); + + /* Get the dataset's type and make sure it's named */ + /* Get the dataset's data type and make sure it's a named type */ + ds_type = new DataType(dset.getDataType()); + iscommitted = ds_type->committed(); + if (!iscommitted) + throw InvalidActionException("IntType::committed()", "Dataset type should be named type!"); +/* + if ((t2 = H5Dget_type (dset))<0) printf("goto error in C\n"); + if ((status=H5Tcommitted (t2))<0) printf("goto error in C\n"); + if (!status) { + H5_FAILED(); + puts (" Dataset type should be a named type!"); + printf("goto error in C\n"); + } +*/ + + /* + * Close the dataset and create another with the type returned from the + * first dataset. + */ + dset.close(); + //if (H5Dclose (dset)<0) printf("goto error in C\n"); + dset = file.createDataSet("dset2", *ds_type, space); + //if ((dset=H5Dcreate (file, "dset2", t2, space, H5P_DEFAULT))<0) + + /* Reopen the second dataset and make sure the type is shared */ + ds_type->close(); + dset.close(); + dset = file.openDataSet("dset2"); + ds_type = new DataType(dset.getDataType()); + iscommitted = ds_type->committed(); + if (!iscommitted) + throw InvalidActionException("IntType::committed()", "Dataset type should be named type!"); + +/* + if (H5Tclose (t2)<0) printf("goto error in C\n"); + if (H5Dclose (dset)<0) printf("goto error in C\n"); + if ((dset = H5Dopen (file, "dset2"))<0) printf("goto error in C\n"); + if ((t2 = H5Dget_type (dset))<0) printf("goto error in C\n"); + if ((status=H5Tcommitted (t2))<0) printf("goto error in C\n"); + if (!status) { + H5_FAILED(); + puts (" Dataset type should be a named type!"); + printf("goto error in C\n"); + } +*/ + ds_type->close(); + //if (H5Tclose (t2)<0) printf("goto error in C\n"); + + /* + * Get the dataset data type by applying H5Tcopy() to the dataset. The + * result should be modifiable. + */ + //DataType copied_type = dset.copyType(); + IntType copied_type; + copied_type.copy(dset); + //if ((t2=H5Tcopy (dset))<0) printf("goto error in C\n"); + +// find another function that can be in DataType + copied_type.setPrecision(256); +// if (H5Tset_precision (t2, 256)<0) printf("goto error in C\n"); + //copied_type.close(); + copied_type.close(); + //if (H5Tclose (t2)<0) printf("goto error in C\n"); + + /* Clean up */ + dset.close(); + itype.close(); + space.close(); + file.close(); +/* + if (H5Dclose (dset)<0) printf("goto error in C\n"); + if (H5Tclose (type)<0) printf("goto error in C\n"); + if (H5Sclose (space)<0) printf("goto error in C\n"); + if (H5Fclose (file)<0) printf("goto error in C\n"); +*/ + PASSED(); + } // end of try block + catch (Exception E) { +cerr << "all the way here?" << endl; + issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_named + + +/**************************************************************** +** +** test_types(): Main data types testing routine. +** +****************************************************************/ +void test_types(void) +{ + // Output message about test being performed + MESSAGE(5, ("Testing Generic Data Types\n")); + + // Test basic datatypes + test_classes(); + test_copy(); + test_query(); + test_transient(); + test_named(); + +} // test_types() + + +/*------------------------------------------------------------------------- + * Function: cleanup_types + * + * Purpose: Cleanup temporary test files + * + * Return: none + * + * Programmer: Quincey Koziol + * September 10, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +cleanup_types(void) +{ + for (int i = 0; i < 3; i++) + HDremove(FILENAME[i]); +} |