diff options
author | Binh-Minh Ribler <bmribler@hdfgroup.org> | 2007-01-26 05:40:17 (GMT) |
---|---|---|
committer | Binh-Minh Ribler <bmribler@hdfgroup.org> | 2007-01-26 05:40:17 (GMT) |
commit | fd318bcf1fe96ff30ae83a4a1441d2600f0cf825 (patch) | |
tree | c74c83e7815461c4ce8dce5de46c5a60c01d0943 | |
parent | 134352c456b2952f192e74ed3e87fb72a2d9bbd8 (diff) | |
download | hdf5-fd318bcf1fe96ff30ae83a4a1441d2600f0cf825.zip hdf5-fd318bcf1fe96ff30ae83a4a1441d2600f0cf825.tar.gz hdf5-fd318bcf1fe96ff30ae83a4a1441d2600f0cf825.tar.bz2 |
[svn-r13201] Purpose: Adding test
Description:
Added
* tests for some generic datatype operations
* tests for compound datatype operations
These tests are checked in now to make sure they're safe! They can
use some more comments and minor cleanups. Will do very soon.
Fixed few minor typos.
Platforms tested
AIX 5.1 (copper)
SunOS 5.8 64-bit (sol)
HPUX 11.00 (kelgia)
-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]); +} |