From fa406155ab6ab2903d856f8e20502caef2df0996 Mon Sep 17 00:00:00 2001 From: Binh-Minh Ribler Date: Tue, 20 Oct 2009 13:14:34 -0500 Subject: [svn-r17690] Purpose: Code improvement Description: Fixed CommonFG::getComment and CommonFG::getLinkval to provide default values for buffer size to improve usability. Added test file tlinks.cpp, which only contains test for getLinkval and will expand when C++ wrappers for H5L functions are implemented. Platforms tested: Linux/32 2.6 (jam) FreeBSD/64 6.3 (liberty) SunOS 5.10 (linew) --- c++/src/H5CommonFG.cpp | 106 ++++---- c++/src/H5CommonFG.h | 11 +- c++/test/Makefile.am | 2 +- c++/test/Makefile.in | 7 +- c++/test/h5cpputil.h | 36 +-- c++/test/testhdf5.cpp | 1 + c++/test/tlinks.cpp | 722 +++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 800 insertions(+), 85 deletions(-) create mode 100644 c++/test/tlinks.cpp diff --git a/c++/src/H5CommonFG.cpp b/c++/src/H5CommonFG.cpp index 80efc5d..f9311c6 100644 --- a/c++/src/H5CommonFG.cpp +++ b/c++/src/H5CommonFG.cpp @@ -15,11 +15,6 @@ #include -// remove when done -#include - using std::cerr; - using std::endl; - #include "H5Include.h" #include "H5Exception.h" #include "H5IdComponent.h" @@ -430,16 +425,37 @@ void CommonFG::getObjinfo( const H5std_string& name, H5G_stat_t& statbuf ) const //-------------------------------------------------------------------------- H5std_string CommonFG::getLinkval( const char* name, size_t size ) const { - char* value_C = new char[size+1]; // temporary C-string for C API + H5L_info_t linkinfo; + char *value_C; // value in C string + size_t val_size = size; + H5std_string value = ""; + herr_t ret_value; - herr_t ret_value = H5Lget_val( getLocId(), name, value_C, size, H5P_DEFAULT ); - if( ret_value < 0 ) - { - throwException("getLinkval", "H5Lget_val failed"); - } - H5std_string value = H5std_string( value_C ); - delete []value_C; - return( value ); + // if user doesn't provide buffer size, determine it + if (size == 0) + { + ret_value = H5Lget_info(getLocId(), name, &linkinfo, H5P_DEFAULT); + if( ret_value < 0 ) + { + throwException("getLinkval", "H5Lget_info to find buffer size failed"); + } + val_size = linkinfo.u.val_size; + } + + // if link has value, retrieve the value, otherwise, return null string + if (val_size > 0) + { + value_C = new char[val_size+1]; // temporary C-string for C API + + ret_value = H5Lget_val(getLocId(), name, value_C, val_size, H5P_DEFAULT); + if( ret_value < 0 ) + { + throwException("getLinkval", "H5Lget_val failed"); + } + value = H5std_string(value_C); + delete []value_C; + } + return(value); } //-------------------------------------------------------------------------- @@ -529,33 +545,38 @@ void CommonFG::removeComment(const H5std_string& name) const //-------------------------------------------------------------------------- // Function: CommonFG::getComment -///\brief Retrieves comment for the specified object. +///\brief Retrieves comment for the specified object and its comment's +/// length. ///\param name - IN: Name of the object +///\param bufsize - IN: Length of the comment to retrieve ///\return Comment string ///\exception H5::FileIException or H5::GroupIException -// Programmer Binh-Minh Ribler - May 2005 +// Programmer Binh-Minh Ribler - 2000 // 2007: QAK modified to use H5O APIs; however the first parameter is // no longer just file or group, this function should be moved // to another class to accommodate attribute, dataset, and named // datatype. - BMR //-------------------------------------------------------------------------- -H5std_string CommonFG::getComment (const H5std_string& name) const +H5std_string CommonFG::getComment( const char* name, size_t bufsize ) const { - size_t bufsize = 256; // anticipating the comment's length + // bufsize is default to 256 + // temporary variable hid_t loc_id = getLocId(); // temporary variable - // temporary C-string for the object's comment - char* comment_C = new char[bufsize+1]; - ssize_t ret_value = H5Oget_comment_by_name(loc_id, name.c_str(), comment_C, bufsize, H5P_DEFAULT); + // temporary C-string for the object's comment; bufsize already including + // null character + char* comment_C = new char[bufsize]; + ssize_t ret_value = H5Oget_comment_by_name(loc_id, name, comment_C, bufsize, H5P_DEFAULT); - // if the actual length of the comment is longer than the anticipated - // value, then call H5Oget_comment_by_name again with the correct value - if ((size_t)ret_value > bufsize) + // if the actual length of the comment is longer than bufsize and bufsize + // was the default value, i.e., not given by the user, then call + // H5Oget_comment_by_name again with the correct value + if ((size_t)ret_value > bufsize && bufsize == 256) { - bufsize = ret_value; + size_t new_size = ret_value; delete []comment_C; - comment_C = new char[bufsize+1]; - ret_value = H5Oget_comment_by_name(loc_id, name.c_str(), comment_C, bufsize, H5P_DEFAULT); + comment_C = new char[new_size]; // new_size including null terminator + ret_value = H5Oget_comment_by_name(loc_id, name, comment_C, new_size, H5P_DEFAULT); } // if H5Oget_comment_by_name returns SUCCEED, return the string comment, @@ -571,37 +592,6 @@ H5std_string CommonFG::getComment (const H5std_string& name) const //-------------------------------------------------------------------------- // Function: CommonFG::getComment -///\brief Retrieves comment for the specified object and its comment's -/// length. -///\param name - IN: Name of the object -///\param bufsize - IN: Length of the comment to retrieve -///\return Comment string -///\exception H5::FileIException or H5::GroupIException -// Programmer Binh-Minh Ribler - 2000 -// 2007: QAK modified to use H5O APIs; however the first parameter is -// no longer just file or group, this function should be moved -// to another class to accommodate attribute, dataset, and named -// datatype. - BMR -//-------------------------------------------------------------------------- -H5std_string CommonFG::getComment( const char* name, size_t bufsize ) const -{ - // temporary C-string for the object's comment - char* comment_C = new char[bufsize+1]; - - herr_t ret_value = H5Oget_comment_by_name( getLocId(), name, comment_C, bufsize, H5P_DEFAULT ); - - // if H5Oget_comment_by_name returns SUCCEED, return the string comment - if( ret_value < 0 ) - { - throwException("getComment", "H5Oget_comment_by_name failed"); - } - H5std_string comment = H5std_string(comment_C); - delete []comment_C; - return( comment ); -} - -//-------------------------------------------------------------------------- -// Function: CommonFG::getComment ///\brief This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes an /// \c std::string for \a name. diff --git a/c++/src/H5CommonFG.h b/c++/src/H5CommonFG.h index 87c0615..d472d42 100644 --- a/c++/src/H5CommonFG.h +++ b/c++/src/H5CommonFG.h @@ -50,9 +50,8 @@ class H5_DLLCPP CommonFG { DataSet openDataSet(const H5std_string& name) const; // Retrieves comment for the HDF5 object specified by its name. - H5std_string getComment(const H5std_string& name) const; - H5std_string getComment(const char* name, size_t bufsize) const; - H5std_string getComment(const H5std_string& name, size_t bufsize) const; + H5std_string getComment(const char* name, size_t bufsize=256) const; + H5std_string getComment(const H5std_string& name, size_t bufsize=256) const; // Removes the comment for the HDF5 object specified by its name. void removeComment(const char* name) const; @@ -62,9 +61,9 @@ class H5_DLLCPP CommonFG { void setComment(const char* name, const char* comment) const; void setComment(const H5std_string& name, const H5std_string& comment) const; - // Returns the name of the HDF5 object that the symbolic link points to. - H5std_string getLinkval(const char* name, size_t size) const; - H5std_string getLinkval(const H5std_string& name, size_t size) const; + // Returns the value of a symbolic link. + H5std_string getLinkval(const char* link_name, size_t size=0) const; + H5std_string getLinkval(const H5std_string& link_name, size_t size=0) const; // Returns the number of objects in this group. hsize_t getNumObjs() const; diff --git a/c++/test/Makefile.am b/c++/test/Makefile.am index 7799fd6..fdfdd61 100644 --- a/c++/test/Makefile.am +++ b/c++/test/Makefile.am @@ -39,7 +39,7 @@ LDADD=$(LIBH5TEST) $(LIBH5CPP) $(LIBHDF5) dsets_SOURCES=dsets.cpp h5cpputil.cpp testhdf5_SOURCES=testhdf5.cpp tattr.cpp tcompound.cpp tfile.cpp tfilter.cpp \ - th5s.cpp trefer.cpp ttypes.cpp tvlstr.cpp h5cpputil.cpp + th5s.cpp tlinks.cpp trefer.cpp ttypes.cpp tvlstr.cpp h5cpputil.cpp # Tell conclude.am that these are C++ tests. CXX_API=yes diff --git a/c++/test/Makefile.in b/c++/test/Makefile.in index 909abb8..6384eec 100644 --- a/c++/test/Makefile.in +++ b/c++/test/Makefile.in @@ -74,8 +74,8 @@ dsets_LDADD = $(LDADD) dsets_DEPENDENCIES = $(LIBH5TEST) $(LIBH5CPP) $(LIBHDF5) am_testhdf5_OBJECTS = testhdf5.$(OBJEXT) tattr.$(OBJEXT) \ tcompound.$(OBJEXT) tfile.$(OBJEXT) tfilter.$(OBJEXT) \ - th5s.$(OBJEXT) trefer.$(OBJEXT) ttypes.$(OBJEXT) \ - tvlstr.$(OBJEXT) h5cpputil.$(OBJEXT) + th5s.$(OBJEXT) tlinks.$(OBJEXT) trefer.$(OBJEXT) \ + ttypes.$(OBJEXT) tvlstr.$(OBJEXT) h5cpputil.$(OBJEXT) testhdf5_OBJECTS = $(am_testhdf5_OBJECTS) testhdf5_LDADD = $(LDADD) testhdf5_DEPENDENCIES = $(LIBH5TEST) $(LIBH5CPP) $(LIBHDF5) @@ -368,7 +368,7 @@ TEST_PROG = dsets testhdf5 LDADD = $(LIBH5TEST) $(LIBH5CPP) $(LIBHDF5) dsets_SOURCES = dsets.cpp h5cpputil.cpp testhdf5_SOURCES = testhdf5.cpp tattr.cpp tcompound.cpp tfile.cpp tfilter.cpp \ - th5s.cpp trefer.cpp ttypes.cpp tvlstr.cpp h5cpputil.cpp + th5s.cpp tlinks.cpp trefer.cpp ttypes.cpp tvlstr.cpp h5cpputil.cpp # Tell conclude.am that these are C++ tests. @@ -453,6 +453,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/th5s.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tlinks.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@ diff --git a/c++/test/h5cpputil.h b/c++/test/h5cpputil.h index d22a4d3..c547070 100644 --- a/c++/test/h5cpputil.h +++ b/c++/test/h5cpputil.h @@ -113,25 +113,27 @@ template #ifdef __cplusplus extern "C" { #endif -void test_attr(void); -void test_compound(void); -void test_file(void); -void test_filters(void); -void test_h5s(void); -void test_reference(void); -void test_types(void); -void test_vlstrings(void); +void test_attr(); +void test_compound(); +void test_file(); +void test_filters(); +void test_links(); +void test_h5s(); +void test_reference(); +void test_types(); +void test_vlstrings(); /* Prototypes for the cleanup routines */ -void cleanup_attr(void); -void cleanup_compound(void); -void cleanup_dsets(void); -void cleanup_file(void); -void cleanup_filters(void); -void cleanup_h5s(void); -void cleanup_reference(void); -void cleanup_types(void); -void cleanup_vlstrings(void); +void cleanup_attr(); +void cleanup_compound(); +void cleanup_dsets(); +void cleanup_file(); +void cleanup_filters(); +void cleanup_links(); +void cleanup_h5s(); +void cleanup_reference(); +void cleanup_types(); +void cleanup_vlstrings(); #ifdef __cplusplus } diff --git a/c++/test/testhdf5.cpp b/c++/test/testhdf5.cpp index 02b427e..d61babf 100644 --- a/c++/test/testhdf5.cpp +++ b/c++/test/testhdf5.cpp @@ -85,6 +85,7 @@ main(int argc, char *argv[]) AddTest("types", test_types, cleanup_types, "Generic Data Types", NULL); AddTest("compound", test_compound, cleanup_compound, "Compound Data Types", NULL); AddTest("filter", test_filters, cleanup_filters, "Various Filters", NULL); + AddTest("links", test_links, cleanup_links, "Various Links", 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); diff --git a/c++/test/tlinks.cpp b/c++/test/tlinks.cpp new file mode 100644 index 0000000..83e33e1 --- /dev/null +++ b/c++/test/tlinks.cpp @@ -0,0 +1,722 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/***************************************************************************** + FILE + tlinks.cpp - HDF5 C++ testing functionalities associated with the + C attribute interface (H5L) + + ***************************************************************************/ + +#ifdef OLD_HEADER_FILENAME +#include +#else +#include +#endif +#include + +#ifndef H5_NO_NAMESPACE +#ifndef H5_NO_STD + using std::cerr; + using std::endl; +#endif // H5_NO_STD +#endif + +#include "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++ test utilility header file + +// A lot of the definition inherited from C test links.c is left here until +// the H5L API is implemented and tests are completed - BMR 10/19/2009 +/* + * This file needs to access private information from the H5G package. + * This file also needs to access the group testing code. + */ +//#define H5G_PACKAGE +//#define H5G_TESTING + +//#include "h5test.h" +//#include "H5Gpkg.h" /* Groups */ +//#include "H5Iprivate.h" /* IDs */ +//#include "H5Lprivate.h" /* Links */ + +/* File for external link test. Created with gen_udlinks.c */ +#define LINKED_FILE "be_extlink2.h5" + +#ifdef H5_VMS +#if 0 +const char *FILENAME[] = { + "links0", + "links1", + "links2", + "links3", + "links4a", /* 4 */ + "links4b", /* 5 */ + "links4c", /* 6 */ + "links4d", /* 7 */ + "links5", /* 8 */ + "links6", /* 9 */ + "links7", /* 10 */ + "links8", /* 11 */ + "extlinks0", /* 12: main files */ + "[.tmp]extlinks0", /* 13: */ + "extlinks1", /* 14: target files */ + "[.tmp]extlinks1", /* 15: */ + "extlinks2", /* 16: */ + "[.tmp]extlinks2", /* 17: */ + "extlinks3", /* 18: */ + "[.tmp]extlinks3", /* 19: */ + "extlinks4", /* 20: */ + "[.tmp]extlinks4", /* 21: */ + "extlinks5", /* 22: */ + "[.tmp]extlinks6", /* 23: */ + "extlinks7", /* 24: */ + "[.tmp]extlinks7", /* 25: */ + "[.tmp]extlinks8", /* 26: */ + "extlinks9", /* 27: */ + "[.tmp]extlinks9", /* 28: */ + "extlinks10", /* 29: */ /* TESTS for windows */ + "[.tmp]extlinks10", /* 30: */ + "[.tmp]extlinks11", /* 31: */ + "[.tmp]extlinks12", /* 32: */ + "extlinks13", /* 33: */ + "[.tmp]extlinks13", /* 34: */ + "[.tmp]extlinks14", /* 35: */ + "[.tmp]extlinks15", /* 36: */ + "extlinks16A", /* 37: */ /* TESTS for H5P_set_elink_fapl */ + "extlinks16B", /* 38: */ + "extlinks17", /* 39: */ + "extlinks18A", /* 40: */ + "extlinks18B", /* 41: */ + "extlinks19A", /* 42: */ + "extlinks19B", /* 43: */ + "extlinks20", /* 44: */ + NULL +}; +#endif // 0 + +#define TMPDIR "[.tmp]" +#else +#if 0 +const char *FILENAME[] = { + "links0", + "links1", + "links2", + "links3", + "links4a", /* 4 */ + "links4b", /* 5 */ + "links4c", /* 6 */ + "links4d", /* 7 */ + "links5", /* 8 */ + "links6", /* 9 */ + "links7", /* 10 */ + "links8", /* 11 */ + "extlinks0", /* 12: main files */ + "tmp/extlinks0", /* 13: */ + "extlinks1", /* 14: target files */ + "tmp/extlinks1", /* 15: */ + "extlinks2", /* 16: */ + "tmp/extlinks2", /* 17: */ + "extlinks3", /* 18: */ + "tmp/extlinks3", /* 19: */ + "extlinks4", /* 20: */ + "tmp/extlinks4", /* 21: */ + "extlinks5", /* 22: */ + "tmp/extlinks6", /* 23: */ + "extlinks7", /* 24: */ + "tmp/extlinks7", /* 25: */ + "tmp/extlinks8", /* 26: */ + "extlinks9", /* 27: */ + "tmp/extlinks9", /* 28: */ + "extlinks10", /* 29: */ /* TESTS for windows */ + "tmp/extlinks10", /* 30: */ + "tmp/extlinks11", /* 31: */ + "tmp/extlinks12", /* 32: */ + "extlinks13", /* 33: */ + "tmp/extlinks13", /* 34: */ + "tmp/extlinks14", /* 35: */ + "tmp/extlinks15", /* 36: */ + "extlinks16A", /* 37: */ /* TESTS for H5P_set_elink_fapl */ + "extlinks16B", /* 38: */ + "extlinks17", /* 39: */ + "extlinks18A", /* 40: */ + "extlinks18B", /* 41: */ + "extlinks19A", /* 42: */ + "extlinks19B", /* 43: */ + "extlinks20", /* 44: */ + NULL +}; + +#endif // 0 + +#define TMPDIR "tmp" +#endif + +#define FAMILY_SIZE 1024 +#define CORE_INCREMENT 1024 +#define NUM400 400 + +/* do not do check_all_closed() for "ext*" files and "tmp/ext*" */ +#define EXTSTOP 12 + +#define LINK_BUF_SIZE 1024 +#define NAME_BUF_SIZE 1024 +#define MAX_NAME_LEN ((64*1024)+1024) + +/* Link type IDs */ +#define UD_HARD_TYPE 201 +#define UD_CB_TYPE H5L_TYPE_MAX +#define UD_PLIST_TYPE 128 +#define UD_CBFAIL_TYPE UD_PLIST_TYPE +#define UD_ERROR_TYPE 189 +#define UD_BAD_TYPE1 H5L_TYPE_HARD +#define UD_BAD_TYPE2 (H5L_TYPE_UD_MIN - 5) +#define UD_BAD_VERS (H5L_LINK_CLASS_T_VERS + 1) + +#define DEST_PROP_NAME "destination_group" +#define REREG_TARGET_NAME "rereg_target" + +#define UD_CB_LINK_NAME "ud_callback_link" +#define NEW_UD_CB_LINK_NAME "ud_callback_link2" +#define UD_CB_TARGET "ud_target" +#define UD_CB_TARGET_LEN 10 + +#define LE_FILENAME "le_extlink1.h5" +#define BE_FILENAME "be_extlink1.h5" + +#define ELINK_CB_FAM_SIZE (hsize_t) 100 + +#define H5L_DIM1 100 +#define H5L_DIM2 100 + +/* Creation order macros */ +#define CORDER_GROUP_NAME "corder_group" +#define CORDER_SOFT_GROUP_NAME "corder_soft_group" +#define CORDER_NLINKS 18 +#define CORDER_ITER_STOP 3 +#define CORDER_EST_ENTRY_LEN 9 + +/* Timestamp macros */ +#define TIMESTAMP_GROUP_1 "timestamp1" +#define TIMESTAMP_GROUP_2 "timestamp2" + +/* Link iteration struct */ +typedef struct { + H5_iter_order_t order; /* Direction of iteration */ + unsigned ncalled; /* # of times callback is entered */ + unsigned nskipped; /* # of links skipped */ + int stop; /* # of iterations to stop after */ + int64_t curr; /* Current creation order value */ + size_t max_visit; /* Size of "visited link" flag array */ + hbool_t *visited; /* Pointer to array of "visited link" flags */ +} link_iter_info_t; + +/* Link visit structs */ +typedef struct { + const char *path; /* Path to link */ + H5L_type_t type; /* Type of link */ +} link_visit_t; +static const link_visit_t lvisit0[] = { + {"Dataset_zero", H5L_TYPE_HARD}, + {"Group1", H5L_TYPE_HARD}, + {"Group1/Dataset_one", H5L_TYPE_HARD}, + {"Group1/Group2", H5L_TYPE_HARD}, + {"Group1/Group2/Dataset_two", H5L_TYPE_HARD}, + {"Group1/Group2/Type_two", H5L_TYPE_HARD}, + {"Group1/Group2/hard_zero", H5L_TYPE_HARD}, + {"Group1/Type_one", H5L_TYPE_HARD}, + {"Group1/hard_one", H5L_TYPE_HARD}, + {"Type_zero", H5L_TYPE_HARD}, + {"ext_dangle", H5L_TYPE_EXTERNAL}, + {"ext_one", H5L_TYPE_EXTERNAL}, + {"hard_one", H5L_TYPE_HARD}, + {"hard_two", H5L_TYPE_HARD}, + {"hard_zero", H5L_TYPE_HARD}, + {"soft_dangle", H5L_TYPE_SOFT}, + {"soft_one", H5L_TYPE_SOFT}, + {"soft_two", H5L_TYPE_SOFT} +}; +static const link_visit_t lvisit1[] = { + {"Dataset_one", H5L_TYPE_HARD}, + {"Group2", H5L_TYPE_HARD}, + {"Group2/Dataset_two", H5L_TYPE_HARD}, + {"Group2/Type_two", H5L_TYPE_HARD}, + {"Group2/hard_zero", H5L_TYPE_HARD}, + {"Group2/hard_zero/Dataset_zero", H5L_TYPE_HARD}, + {"Group2/hard_zero/Group1", H5L_TYPE_HARD}, + {"Group2/hard_zero/Type_zero", H5L_TYPE_HARD}, + {"Group2/hard_zero/ext_dangle", H5L_TYPE_EXTERNAL}, + {"Group2/hard_zero/ext_one", H5L_TYPE_EXTERNAL}, + {"Group2/hard_zero/hard_one", H5L_TYPE_HARD}, + {"Group2/hard_zero/hard_two", H5L_TYPE_HARD}, + {"Group2/hard_zero/hard_zero", H5L_TYPE_HARD}, + {"Group2/hard_zero/soft_dangle", H5L_TYPE_SOFT}, + {"Group2/hard_zero/soft_one", H5L_TYPE_SOFT}, + {"Group2/hard_zero/soft_two", H5L_TYPE_SOFT}, + {"Type_one", H5L_TYPE_HARD}, + {"hard_one", H5L_TYPE_HARD} +}; +static const link_visit_t lvisit2[] = { + {"Dataset_two", H5L_TYPE_HARD}, + {"Type_two", H5L_TYPE_HARD}, + {"hard_zero", H5L_TYPE_HARD}, + {"hard_zero/Dataset_zero", H5L_TYPE_HARD}, + {"hard_zero/Group1", H5L_TYPE_HARD}, + {"hard_zero/Group1/Dataset_one", H5L_TYPE_HARD}, + {"hard_zero/Group1/Group2", H5L_TYPE_HARD}, + {"hard_zero/Group1/Type_one", H5L_TYPE_HARD}, + {"hard_zero/Group1/hard_one", H5L_TYPE_HARD}, + {"hard_zero/Type_zero", H5L_TYPE_HARD}, + {"hard_zero/ext_dangle", H5L_TYPE_EXTERNAL}, + {"hard_zero/ext_one", H5L_TYPE_EXTERNAL}, + {"hard_zero/hard_one", H5L_TYPE_HARD}, + {"hard_zero/hard_two", H5L_TYPE_HARD}, + {"hard_zero/hard_zero", H5L_TYPE_HARD}, + {"hard_zero/soft_dangle", H5L_TYPE_SOFT}, + {"hard_zero/soft_one", H5L_TYPE_SOFT}, + {"hard_zero/soft_two", H5L_TYPE_SOFT} +}; + +typedef struct { + unsigned idx; /* Index in link visit structure */ + const link_visit_t *info; /* Pointer to the link visit structure to use */ +} lvisit_ud_t; + + +/* Object visit structs */ +typedef struct { + const char *path; /* Path to object */ + H5O_type_t type; /* Type of object */ +} obj_visit_t; +static const obj_visit_t ovisit0_old[] = { + {".", H5O_TYPE_GROUP}, + {"Dataset_zero", H5O_TYPE_DATASET}, + {"Group1", H5O_TYPE_GROUP}, + {"Group1/Dataset_one", H5O_TYPE_DATASET}, + {"Group1/Group2", H5O_TYPE_GROUP}, + {"Group1/Group2/Dataset_two", H5O_TYPE_DATASET}, + {"Group1/Group2/Type_two", H5O_TYPE_NAMED_DATATYPE}, + {"Group1/Type_one", H5O_TYPE_NAMED_DATATYPE}, + {"Type_zero", H5O_TYPE_NAMED_DATATYPE} +}; +static const obj_visit_t ovisit0_new[] = { + {".", H5O_TYPE_GROUP}, + {"Dataset_zero", H5O_TYPE_DATASET}, + {"Group1", H5O_TYPE_GROUP}, + {"Group1/Dataset_one", H5O_TYPE_DATASET}, + {"Group1/Group2", H5O_TYPE_GROUP}, + {"Group1/Group2/Dataset_two", H5O_TYPE_DATASET}, + {"Group1/Group2/Type_two", H5O_TYPE_NAMED_DATATYPE}, + {"Group1/Type_one", H5O_TYPE_NAMED_DATATYPE}, + {"Type_zero", H5O_TYPE_NAMED_DATATYPE} +}; +static const obj_visit_t ovisit1_old[] = { + {".", H5O_TYPE_GROUP}, + {"Dataset_one", H5O_TYPE_DATASET}, + {"Group2", H5O_TYPE_GROUP}, + {"Group2/Dataset_two", H5O_TYPE_DATASET}, + {"Group2/Type_two", H5O_TYPE_NAMED_DATATYPE}, + {"Group2/hard_zero", H5O_TYPE_GROUP}, + {"Group2/hard_zero/Dataset_zero", H5O_TYPE_DATASET}, + {"Group2/hard_zero/Type_zero", H5O_TYPE_NAMED_DATATYPE}, + {"Type_one", H5O_TYPE_NAMED_DATATYPE} +}; +static const obj_visit_t ovisit1_new[] = { + {".", H5O_TYPE_GROUP}, + {"Dataset_one", H5O_TYPE_DATASET}, + {"Group2", H5O_TYPE_GROUP}, + {"Group2/Dataset_two", H5O_TYPE_DATASET}, + {"Group2/Type_two", H5O_TYPE_NAMED_DATATYPE}, + {"Group2/hard_zero", H5O_TYPE_GROUP}, + {"Group2/hard_zero/Dataset_zero", H5O_TYPE_DATASET}, + {"Group2/hard_zero/Type_zero", H5O_TYPE_NAMED_DATATYPE}, + {"Type_one", H5O_TYPE_NAMED_DATATYPE} +}; +static const obj_visit_t ovisit2_old[] = { + {".", H5O_TYPE_GROUP}, + {"Dataset_two", H5O_TYPE_DATASET}, + {"Type_two", H5O_TYPE_NAMED_DATATYPE}, + {"hard_zero", H5O_TYPE_GROUP}, + {"hard_zero/Dataset_zero", H5O_TYPE_DATASET}, + {"hard_zero/Group1", H5O_TYPE_GROUP}, + {"hard_zero/Group1/Dataset_one", H5O_TYPE_DATASET}, + {"hard_zero/Group1/Type_one", H5O_TYPE_NAMED_DATATYPE}, + {"hard_zero/Type_zero", H5O_TYPE_NAMED_DATATYPE} +}; +static const obj_visit_t ovisit2_new[] = { + {".", H5O_TYPE_GROUP}, + {"Dataset_two", H5O_TYPE_DATASET}, + {"Type_two", H5O_TYPE_NAMED_DATATYPE}, + {"hard_zero", H5O_TYPE_GROUP}, + {"hard_zero/Dataset_zero", H5O_TYPE_DATASET}, + {"hard_zero/Group1", H5O_TYPE_GROUP}, + {"hard_zero/Group1/Dataset_one", H5O_TYPE_DATASET}, + {"hard_zero/Group1/Type_one", H5O_TYPE_NAMED_DATATYPE}, + {"hard_zero/Type_zero", H5O_TYPE_NAMED_DATATYPE} +}; + +typedef struct { + unsigned idx; /* Index in object visit structure */ + const obj_visit_t *info; /* Pointer to the object visit structure to use */ +} ovisit_ud_t; + +static const char *FILENAME[] = { + "link0", + "link1.h5", + "link2.h5", + NULL +}; + + +/*------------------------------------------------------------------------- + * Function: test_basic_links + * + * Purpose: Test building a file with assorted links. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Binh-Minh Ribler + * October 16, 2009 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_basic_links(hid_t fapl_id, hbool_t new_format) +{ + hsize_t size[1] = {1}; + char filename[NAME_BUF_SIZE]; + char* tconv_buf = new char [1000]; + + // Use the file access template id to create a file access prop. list. + FileAccPropList fapl(fapl_id); + + try + { + if(new_format) + SUBTEST("Link creation (w/new group format)") + else + SUBTEST("Link creation") + + h5_fixname(FILENAME[0], fapl_id, filename, sizeof filename); + H5File file(filename, H5F_ACC_TRUNC, FileCreatPropList::DEFAULT, fapl); + + // Create simple dataspace + DataSpace scalar (1, size, size); + + // Create a group then close it by letting the object go out of scope + { + Group group(file.createGroup("grp1", 0)); + } + + // Create a dataset then close it by letting the object go out of scope + { + DataSet dset1(file.createDataSet("dset1", PredType::NATIVE_INT, scalar)); + } + + hid_t file_id = file.getId(); + + // Because these are not implemented in the C++ API yet, they are + // used so CommonFG::getLinkval can be tested. + // Create a hard link + if(H5Lcreate_hard( + file_id, "dset1", H5L_SAME_LOC, "grp1/hard1", + H5P_DEFAULT, H5P_DEFAULT) < 0) + throw Exception("test_basic_links", "H5Lcreate_hard failed"); + + // Create a symbolic link + if(H5Lcreate_soft( + "/dset1", file_id, "grp1/soft", H5P_DEFAULT, H5P_DEFAULT) < 0) + throw Exception("test_basic_links", "H5Lcreate_soft failed"); + + // Create a symbolic link to something that doesn't exist + if(H5Lcreate_soft( + "foobar", file_id, "grp1/dangle", H5P_DEFAULT, H5P_DEFAULT) < 0) + throw Exception("test_basic_links", "H5Lcreate_soft failed"); + + // Create a recursive symbolic link + if(H5Lcreate_soft( + "/grp1/recursive", file_id, "/grp1/recursive", + H5P_DEFAULT, H5P_DEFAULT) < 0) + throw Exception("test_basic_links", "H5Lcreate_soft failed"); + + // Verify link values before closing the file + + H5std_string softlink_val = file.getLinkval("grp1/soft"); + verify_val(softlink_val, "/dset1", "H5File::getLinkval grp1/soft", __LINE__, __FILE__); + + H5std_string dngllink_val = file.getLinkval("grp1/dangle"); + verify_val(dngllink_val, "foobar", "H5File::getLinkval grp1/dangle", __LINE__, __FILE__); + + H5std_string reclink_val = file.getLinkval("grp1/recursive"); + verify_val(reclink_val, "/grp1/recursive", "H5File::getLinkval grp1/recursive", __LINE__, __FILE__); + + } // end of try block + catch (Exception E) + { + issue_fail_msg("test_basic_links()", __LINE__, __FILE__, E.getCDetailMsg()); + } + + // Open the file and check on the links in it + try + { + // Open the file above + H5File file(filename, H5F_ACC_RDWR, FileCreatPropList::DEFAULT, fapl); + + // Verify link existence + if(H5Lexists(file.getId(), "dset1", H5P_DEFAULT) != TRUE) + throw InvalidActionException("H5Lexists", "dset1 doesn't exist"); + if(H5Lexists(file.getId(), "grp1/soft", H5P_DEFAULT) != TRUE) + throw InvalidActionException("H5Lexists", "grp1/soft doesn't exist"); + + // Verify link values + H5std_string softlink_val = file.getLinkval("grp1/soft"); + verify_val(softlink_val, "/dset1", "H5File::getLinkval grp1/soft", __LINE__, __FILE__); + + H5std_string reclink_val = file.getLinkval("grp1/recursive"); + verify_val(reclink_val, "/grp1/recursive", "H5File::getLinkval grp1/recursive", __LINE__, __FILE__); + + PASSED(); + } // end of try block + catch (Exception E) + { + issue_fail_msg("test_basic_links()", __LINE__, __FILE__, E.getCDetailMsg()); + } +} + + +/*------------------------------------------------------------------------- + * Function: test_links + * + * Purpose: Test links + * + * Return: None + * + * Programmer: Binh-Minh Ribler + * October 16, 2009 + * + *------------------------------------------------------------------------- + */ +#ifdef __cplusplus +extern "C" +#endif +void test_links() +{ + hid_t fapl_id, fapl2_id; /* File access property lists */ + hbool_t new_format; /* Whether to use the new format or not */ + const char *envval; + + envval = HDgetenv("HDF5_DRIVER"); + if(envval == NULL) + envval = "nomatch"; + + fapl_id = h5_fileaccess(); + + // Output message about test being performed + MESSAGE(5, ("Testing Various Links\n")); + try + { + /* Copy the file access property list */ + if((fapl2_id = H5Pcopy(fapl_id)) < 0) + throw Exception("test_links", "H5Pcopy failed"); + + /* Set the "use the latest version of the format" bounds for creating objects in the file */ + if(H5Pset_libver_bounds(fapl2_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) + throw Exception("test_links", "H5Pset_libver_bounds failed"); + + /* Loop over using new group format */ + for(new_format = FALSE; new_format <= TRUE; new_format++) + { + hid_t my_fapl_id; + + /* Check for FAPL to use */ + if(new_format) + my_fapl_id = fapl2_id; + else + my_fapl_id = fapl_id; + + /* General tests... (on both old & new format groups */ + // FileAccPropList may be passed in instead of fapl id + test_basic_links(my_fapl_id, new_format); +#if 0 +// these tests are from the C test links.c and left here for future +// implementation of H5L API + nerrors += test_basic_links(fapl_id, new_format) < 0 ? 1 : 0; + nerrors += cklinks(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += new_links(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += ck_new_links(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += long_links(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += toomany(my_fapl, new_format) < 0 ? 1 : 0; + + /* Test new H5L link creation routine */ + nerrors += test_lcpl(my_fapl, new_format); + nerrors += test_move(my_fapl, new_format); + nerrors += test_copy(my_fapl, new_format); + nerrors += test_move_preserves(my_fapl, new_format); +#ifndef H5_NO_DEPRECATED_SYMBOLS + nerrors += test_deprec(my_fapl, new_format); +#endif /* H5_NO_DEPRECATED_SYMBOLS */ +#ifndef H5_CANNOT_OPEN_TWICE + nerrors += external_link_root(my_fapl, new_format) < 0 ? 1 : 0; +#endif /* H5_CANNOT_OPEN_TWICE */ + nerrors += external_link_path(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_mult(my_fapl, new_format) < 0 ? 1 : 0; +#ifndef H5_CANNOT_OPEN_TWICE + nerrors += external_link_self(envval, my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_pingpong(envval, my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_toomany(my_fapl, new_format) < 0 ? 1 : 0; +#endif /* H5_CANNOT_OPEN_TWICE */ + nerrors += external_link_dangling(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_recursive(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_query(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_unlink_compact(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_unlink_dense(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_move(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_ride(my_fapl, new_format) < 0 ? 1 : 0; +#ifndef H5_CANNOT_OPEN_TWICE + nerrors += external_link_closing(envval, my_fapl, new_format) < 0 ? 1 : 0; +#endif /* H5_CANNOT_OPEN_TWICE */ + nerrors += external_link_endian(new_format) < 0 ? 1 : 0; + nerrors += external_link_strong(my_fapl, new_format) < 0 ? 1 : 0; + + /* tests for external link */ + nerrors += external_link_env(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_prefix(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_abs_mainpath(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_rel_mainpath(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_cwd(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_abstar(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_abstar_cur(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_reltar(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_chdir(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_set_elink_fapl1(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_set_elink_fapl2(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_set_elink_fapl3(new_format) < 0 ? 1 : 0; + nerrors += external_set_elink_acc_flags(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_set_elink_cb(my_fapl, new_format) < 0 ? 1 : 0; + +#ifdef H5_HAVE_WINDOW_PATH + nerrors += external_link_win1(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_win2(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_win3(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_win4(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_win5(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_win6(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_win7(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_win8(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += external_link_win9(my_fapl, new_format) < 0 ? 1 : 0; +#endif + /* These tests assume that external links are a form of UD links, + * so assume that everything that passed for external links + * above has already been tested for UD links. + */ + if(new_format == TRUE) { + nerrors += ud_hard_links(fapl2) < 0 ? 1 : 0; /* requires new format groups */ + nerrors += ud_link_reregister(fapl2) < 0 ? 1 : 0; /* requires new format groups */ + } /* end if */ + + nerrors += ud_callbacks(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += ud_link_errors(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += lapl_udata(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += lapl_nlinks(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += linkinfo(my_fapl, new_format) < 0 ? 1 : 0; + + /* Misc. extra tests, useful for both new & old format files */ + nerrors += link_visit(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += link_visit_by_name(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += obj_visit(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += obj_visit_by_name(my_fapl, new_format) < 0 ? 1 : 0; + nerrors += obj_visit_stop(my_fapl, new_format) < 0 ? 1 : 0; + + /* Keep this test last, it's testing files that are used above */ + /* do not do this for files used by external link tests */ + nerrors += check_all_closed(my_fapl, new_format, EXTSTOP) < 0 ? 1 : 0; +#endif // 0 + } /* end for */ + +#if 0 + /* New group revision feature tests */ + nerrors += corder_create_empty(fapl2) < 0 ? 1 : 0; +/* XXX: when creation order indexing is fully working, go back and add checks +* to these tests to make certain that the creation order values are +* correct. +*/ + nerrors += corder_create_compact(fapl2) < 0 ? 1 : 0; + nerrors += corder_create_dense(fapl2) < 0 ? 1 : 0; + nerrors += corder_transition(fapl2) < 0 ? 1 : 0; + nerrors += corder_delete(fapl2) < 0 ? 1 : 0; + nerrors += link_info_by_idx(fapl2) < 0 ? 1 : 0; + nerrors += delete_by_idx(fapl2) < 0 ? 1 : 0; + nerrors += link_iterate(fapl2) < 0 ? 1 : 0; + nerrors += open_by_idx(fapl2) < 0 ? 1 : 0; + nerrors += object_info(fapl2) < 0 ? 1 : 0; + nerrors += group_info(fapl2) < 0 ? 1 : 0; + nerrors += timestamps(fapl2) < 0 ? 1 : 0; + + /* Test new API calls on old-style groups */ + nerrors += link_info_by_idx_old(fapl) < 0 ? 1 : 0; + nerrors += delete_by_idx_old(fapl) < 0 ? 1 : 0; + nerrors += link_iterate_old(fapl) < 0 ? 1 : 0; + nerrors += open_by_idx_old(fapl) < 0 ? 1 : 0; + nerrors += object_info_old(fapl) < 0 ? 1 : 0; + nerrors += group_info_old(fapl) < 0 ? 1 : 0; + +#endif + /* Close 2nd FAPL */ + H5Pclose(fapl2_id); + + h5_cleanup(FILENAME, fapl_id); + + /* Test that external links can be used after a library reset. MUST be + * called last so the reset doesn't interfere with the property lists. This + * routine will delete its own file. */ + /* nerrors += external_reset_register() < 0 ? 1 : 0; + */ + } + catch (Exception E) + { + issue_fail_msg("test_links()", __LINE__, __FILE__, E.getCDetailMsg()); + } + +} + +/*------------------------------------------------------------------------- + * Function: cleanup_links + * + * Purpose: Cleanup temporary test files + * + * Return: none + * + * Programmer: Binh-Minh Ribler + * October 16, 2009 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifdef __cplusplus +extern "C" +#endif +void cleanup_links() +{ + HDremove(FILENAME[0]); +} + -- cgit v0.12