Regarding [NCF-331], the issues appears to have been in nc4file.c:get_type_info2(). The call to H5Tget_order() was only happening for H5T_Float. According to the documentation, this works for all datatypes as of hdf5 1.8.6. This tentatively fixes the bug reported, but additional testing (and cleanup from debugging) is needed.

This commit is contained in:
Ward Fisher 2015-05-15 14:24:27 -06:00
parent de29c4d0a8
commit 99ef1624bc
3 changed files with 189 additions and 80 deletions

View File

@ -1375,6 +1375,7 @@ IF(ENABLE_TESTS)
ENDIF()
ADD_SUBDIRECTORY(nc_test)
IF(USE_NETCDF4)
INCLUDE_DIRECTORIES(h5_test)
ADD_SUBDIRECTORY(nc_test4)
ADD_SUBDIRECTORY(h5_test)
ENDIF()

View File

@ -895,31 +895,51 @@ get_type_info2(NC_HDF5_FILE_INFO_T *h5, hid_t datasetid,
break;
}
/* Find out about endianness. */
if (class == H5T_INTEGER)
{
if ((order = H5Tget_order(hdf_typeid)) < 0)
return NC_EHDFERR;
/* Find out about endianness.
* As of HDF 1.8.6, this works with all data types
* Not just H5T_INTEGER.
*
* See https://www.hdfgroup.org/HDF5/doc/RM/RM_H5T.html#Datatype-GetOrder
*/
if((order = H5Tget_order(hdf_typeid)) < 0)
return NC_EHDFERR;
if(order == H5T_ORDER_LE)
(*type_info)->endianness = NC_ENDIAN_LITTLE;
else if(order == H5T_ORDER_BE)
(*type_info)->endianness = NC_ENDIAN_BIG;
else
return NC_EBADTYPE;
if(class == H5T_INTEGER)
(*type_info)->nc_type_class = NC_INT;
else
(*type_info)->nc_type_class = NC_FLOAT;
// if (class == H5T_INTEGER)
// {
// if ((order = H5Tget_order(hdf_typeid)) < 0)
// return NC_EHDFERR;
/* Copy this into the type_info struct. */
if (order == H5T_ORDER_LE)
(*type_info)->endianness = NC_ENDIAN_LITTLE;
else if (order == H5T_ORDER_BE)
(*type_info)->endianness = NC_ENDIAN_BIG;
else /* don't support H5T_ORDER_VAX, H5T_ORDER_MIXED, H5T_ORDER_NONE */
return NC_EBADTYPE;
// if (order == H5T_ORDER_LE)
// (*type_info)->endianness = NC_ENDIAN_LITTLE;
// else if (order == H5T_ORDER_BE)
// (*type_info)->endianness = NC_ENDIAN_BIG;
// else /* don't support H5T_ORDER_VAX, H5T_ORDER_MIXED, H5T_ORDER_NONE */
// return NC_EBADTYPE;
/* Set a class for the type */
/* (Note use of 'NC_INT' for all integer types) */
(*type_info)->nc_type_class = NC_INT;
}
else
{
// /* Set a class for the type */
// /* (Note use of 'NC_INT' for all integer types) */
// (*type_info)->nc_type_class = NC_INT;
// } else
// {
/* Set a class for the type */
/* (Note use of 'NC_FLOAT' for all floating-point types) */
(*type_info)->nc_type_class = NC_FLOAT;
}
}
// (*type_info)->nc_type_class = NC_FLOAT;
// }
}
(*type_info)->nc_typeid = nc_type_constant_g[t];
(*type_info)->size = nc_type_size_g[t];
if (!((*type_info)->name = strdup(nc_type_name_g[t])))

View File

@ -11,90 +11,178 @@
#include <netcdf.h>
#include <stdio.h>
#include "nc_logging.h"
#include <hdf5.h>
#include <nc_tests.h>
#define FILE_NAME_NC "tst_endian_float.nc"
#define FILE_NAME_H5 "tst_endian_float.h5"
#define FILE_NAME "tst_endian_float.nc"
#define NDIM 10
#define NLON 20
#define DIM_NAME "x"
#define DIM_LEN 3
#define GRP_NAME "grp"
#define VAR_NAME2 "fv"
#define VAR_NAME3 "iv"
#define VAR_NAME "jv"
int main() {
/*
* 1. Create a file with endianness as desired.
*/
int ncid, dimid, varid, varid2, varid3, retval;
int ed, ed2, ed3;
int failures = 0;
int oldfill = 0;
int ed, ed2, ed3;
int failures = 0;
int oldfill = 0;
#ifdef LOGGING
printf("Setting log level 10\n");
nc_set_log_level(10);
LOG((2,"setting Log_level, logging with level 2."));
#ifdef LOGGING1
printf("Setting log level 10\n");
nc_set_log_level(10);
LOG((2,"setting Log_level, logging with level 2."));
#endif
printf("* Checking that endianness is properly read from file.\n");
printf("** Generating test files.\n");
/*
* 1. Create a netcdf file with endianness as desired.
*/
{
retval = nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid);
printf("*** Creating a file via netcdf API: %s.\n",FILE_NAME_NC);
retval = nc_create(FILE_NAME_NC, NC_NETCDF4 | NC_CLOBBER, &ncid);
retval = nc_def_dim(ncid, DIM_NAME, NDIM, &dimid);
retval = nc_def_dim(ncid, DIM_NAME, NDIM, &dimid);
/* First, Float */
retval = nc_def_var(ncid, VAR_NAME, NC_FLOAT, 1, &dimid, &varid);
/* First, Float */
retval = nc_def_var(ncid, VAR_NAME, NC_FLOAT, 1, &dimid, &varid);
retval = nc_def_var_endian(ncid, varid, NC_ENDIAN_BIG);
/* Second, Double */
//retval = nc_def_var(ncid, VAR_NAME2, NC_DOUBLE, 1, &dimid, &varid2);
//retval = nc_def_var_endian(ncid, varid2, NC_ENDIAN_BIG);
/* Second, Double */
retval = nc_def_var(ncid, VAR_NAME2, NC_DOUBLE, 1, &dimid, &varid2);
retval = nc_def_var_endian(ncid, varid2, NC_ENDIAN_BIG);
/* Third, Int */
retval = nc_def_var(ncid, VAR_NAME3, NC_INT, 1, &dimid, &varid3);
retval = nc_def_var_endian(ncid, varid3, NC_ENDIAN_BIG);
/* Third, Int */
retval = nc_def_var(ncid, VAR_NAME3, NC_INT, 1, &dimid, &varid3);
retval = nc_def_var_endian(ncid, varid3, NC_ENDIAN_BIG);
retval = nc_close(ncid);
}
/*
* Create a file with the hdf5 api
*/
{
hid_t fileid, grpid, spaceid;
hid_t native_did, le_did, be_did;
hsize_t dims[1];
printf("*** Creating a file via hdf5 API: %s\n",FILE_NAME_H5);
if ((fileid = H5Fcreate(FILE_NAME_H5, H5F_ACC_TRUNC, H5P_DEFAULT,
H5P_DEFAULT)) < 0) ERR;
if ((grpid = H5Gcreate1(fileid, GRP_NAME, 0)) < 0) ERR;
/* Create a dataset of native endian. */
dims[0] = DIM_LEN;
if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
if ((native_did = H5Dcreate1(grpid, VAR_NAME3, H5T_STD_I32BE,
spaceid, H5P_DEFAULT)) < 0) ERR;
if ((le_did = H5Dcreate1(grpid, VAR_NAME, H5T_IEEE_F32BE,
spaceid, H5P_DEFAULT)) < 0) ERR;
if ((be_did = H5Dcreate1(grpid, VAR_NAME2, H5T_IEEE_F32BE,
spaceid, H5P_DEFAULT)) < 0) ERR;
if (H5Dclose(native_did) < 0 ||
H5Dclose(le_did) < 0 ||
H5Dclose(be_did) < 0 ||
H5Sclose(spaceid) < 0 ||
H5Gclose(grpid) < 0 ||
H5Fclose(fileid) < 0)
{
printf("Error closing hdf5 file.\n");
failures++;
}
}
/*
* 3. Reopen netcdf-generated file, check to see if the endianness attribute
* exists.
*/
printf("** Checking test files.\n");
{
ncid = 0;
printf("*** %s\n",FILE_NAME_NC);
retval = nc_open(FILE_NAME_NC, NC_NETCDF4 | NC_NOWRITE, &ncid);
retval = nc_set_fill(ncid, NC_NOFILL, &oldfill);
retval = nc_inq_varid(ncid,VAR_NAME,&varid);
retval = nc_inq_varid(ncid,VAR_NAME2,&varid2);
retval = nc_inq_varid(ncid,VAR_NAME3,&varid3);
retval = nc_inq_var_endian(ncid,varid,&ed);
if(ed != NC_ENDIAN_BIG) {
printf("\tTest 1: Error for float variable endianness: [%d] not NC_ENDIAN_BIG\n",ed);
failures++;
} else {
printf("\tTest 1: [%d] is NC_ENDIAN_BIG, Success.\n",ed);
}
retval = nc_inq_var_endian(ncid,varid2,&ed2);
if(ed2 != NC_ENDIAN_BIG) {
printf("\tTest 2: Error for double variable endianness: [%d] not NC_ENDIAN_BIG\n",ed);
failures++;
} else {
printf("\tTest 2: [%d] is NC_ENDIAN_BIG, Success.\n",ed2);
}
retval = nc_inq_var_endian(ncid,varid3,&ed3);
if(ed3 != NC_ENDIAN_BIG) {
printf("\tTest 3: Error for integer variable endianness: [%d] not NC_ENDIAN_BIG\n",ed2);
failures++;
} else {
printf("\tTest 3: [%d] is NC_ENDIAN_BIG, Success.\n",ed3);
}
retval = nc_close(ncid);
return retval;
/*
* 2. Reopen file, check to see if the endianness attribute
* exists.
*/
ncid = 0;
retval = nc_open(FILE_NAME, NC_NETCDF4 | NC_NOWRITE, &ncid);
retval = nc_set_fill(ncid, NC_NOFILL, &oldfill);
retval = nc_inq_varid(ncid,VAR_NAME,&varid);
retval = nc_inq_varid(ncid,VAR_NAME2,&varid2);
retval = nc_inq_varid(ncid,VAR_NAME3,&varid3);
retval = nc_inq_var_endian(ncid,varid,&ed);
if(ed != NC_ENDIAN_BIG) {
printf("Test 1: Error for float variable endianness: [%d] not NC_ENDIAN_BIG\n",ed);
failures++;
} else {
printf("Test 1: [%d] is NC_ENDIAN_BIG, Success.\n",ed);
}
retval = nc_inq_var_endian(ncid,varid2,&ed2);
if(ed2 != NC_ENDIAN_BIG) {
printf("Test 2: Error for double variable endianness: [%d] not NC_ENDIAN_BIG\n",ed);
failures++;
} else {
printf("Test 2: [%d] is NC_ENDIAN_BIG, Success.\n",ed2);
}
retval = nc_inq_var_endian(ncid,varid3,&ed3);
if(ed3 != NC_ENDIAN_LITTLE) {
printf("Test 3: Error for integer variable endianness: [%d] not NC_ENDIAN_BIG\n",ed2);
failures++;
} else {
printf("Test 3: [%d] is NC_ENDIAN_BIG, Success.\n",ed3);
}
/*
* 4. Reopen hdf5-generated file, check to see if the endianness attribute
* exists.
*/
{
ncid = 0;
printf("*** %s\n",FILE_NAME_H5);
retval = nc_open(FILE_NAME_H5, NC_NETCDF4 | NC_NOWRITE, &ncid);
retval = nc_inq_varid(ncid,VAR_NAME,&varid);
retval = nc_inq_varid(ncid,VAR_NAME2,&varid2);
retval = nc_inq_varid(ncid,VAR_NAME3,&varid3);
retval = nc_inq_var_endian(ncid,varid,&ed);
if(ed != NC_ENDIAN_BIG) {
printf("\tTest 1: Error for float variable endianness: [%d] not NC_ENDIAN_BIG\n",ed);
failures++;
} else {
printf("\tTest 1: [%d] is NC_ENDIAN_BIG, Success.\n",ed);
}
retval = nc_inq_var_endian(ncid,varid2,&ed2);
if(ed2 != NC_ENDIAN_BIG) {
printf("\tTest 2: Error for double variable endianness: [%d] not NC_ENDIAN_BIG\n",ed);
failures++;
} else {
printf("\tTest 2: [%d] is NC_ENDIAN_BIG, Success.\n",ed2);
}
retval = nc_inq_var_endian(ncid,varid3,&ed3);
if(ed3 != NC_ENDIAN_BIG) {
printf("\tTest 3: Error for integer variable endianness: [%d] not NC_ENDIAN_BIG\n",ed2);
failures++;
} else {
printf("\tTest 3: [%d] is NC_ENDIAN_BIG, Success.\n",ed3);
}
retval = nc_close(ncid);
/* Force a failure for now, until I can automate the check
programatically that the endianess attribute is properly
stored. */
}
printf("** Failures Returned: [%d]\n",failures);
return failures;
}