/* * Copyright (C) 1997 NCSA * All rights reserved. * * Programmer: Robb Matzke * Tuesday, December 9, 1997 * * Purpose: Tests the data type interface (H5T) */ #include #include #include #include #include #include #include #include #include #include #define H5T_PACKAGE #include /*to turn off hardware conversions*/ #include #ifndef HAVE_ATTRIBUTE # undef __attribute__ # define __attribute__(X) /*void*/ # define __unused__ /*void*/ #else # define __unused__ __attribute__((unused)) #endif #if SIZEOF_DOUBLE != SIZEOF_LONG_DOUBLE # define USE_LDOUBLE #endif #ifndef MAX # define MAX(X,Y) ((X)>(Y)?(X):(Y)) # define MIN(X,Y) ((X)<(Y)?(X):(Y)) #endif #define FILE_NAME_1 "dtypes1.h5" #define FILE_NAME_2 "dtypes2.h5" typedef struct complex_t { double re; double im; } complex_t; /* * Count up or down depending on whether the machine is big endian or little * endian. If `E' is H5T_ORDER_BE then the result will be I, otherwise the * result will be Z-(I+1). */ #define ENDIAN(E,Z,I) (H5T_ORDER_BE==(E)?(I):(Z)-((I)+1)) typedef enum flt_t { FLT_FLOAT, FLT_DOUBLE, FLT_LDOUBLE, FLT_OTHER } flt_t; /* Count the number of overflows */ static int noverflows_g = 0; /* Skip overflow tests if non-zero */ static int skip_overflow_tests_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(HAVE_FORK) && defined(HAVE_WAITPID) # define HANDLE_SIGFPE #endif void some_dummy_func(float x); /*------------------------------------------------------------------------- * Function: fpe_handler * * Purpose: Exit with 255 * * Return: void * * Programmer: Robb Matzke * Monday, July 6, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static void fpe_handler(int __unused__ signo) { puts(" -SKIP-"); 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: * *------------------------------------------------------------------------- */ 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; } /*------------------------------------------------------------------------- * Function: some_dummy_func * * Purpose: A dummy function to help check for overflow. * * Note: DO NOT DECLARE THIS FUNCTION STATIC OR THE COMPILER MIGHT * PROMOTE ARGUMENT `x' TO DOUBLE AND DEFEAT THE OVERFLOW * CHECKING. * * Return: void * * Programmer: Robb Matzke * Tuesday, July 21, 1998 * * Modifications: * *------------------------------------------------------------------------- */ void some_dummy_func(float x) { char s[128]; sprintf(s, "%g", x); } /*------------------------------------------------------------------------- * Function: generates_sigfpe * * Purpose: Determines if SIGFPE is generated from overflows. We must be * able to fork() and waitpid() in order for this test to work * properly. Sets skip_overflow_tests_g to non-zero if they * would generate SIGBUS, zero otherwise. * * Programmer: Robb Matzke * Tuesday, July 21, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static void generates_sigfpe(void) { #if defined(HAVE_FORK) && defined(HAVE_WAITPID) pid_t pid; int status; size_t i, j; double d; unsigned char *dp = (unsigned char*)&d; float f; fflush(stdout); fflush(stderr); if ((pid=fork())<0) { perror("fork"); exit(1); } else if (0==pid) { for (i=0; i<2000; i++) { for (j=0; j=0) { puts ("*FAILED*"); puts (" Should not be able to close a predefined type!"); goto error; } } H5E_END_TRY; puts(" PASSED"); return 0; error: return -1; } /*------------------------------------------------------------------------- * Function: test_compound * * Purpose: Tests various things about compound data types. * * Return: Success: 0 * * Failure: -1 * * Programmer: Robb Matzke * Wednesday, January 7, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t test_compound(void) { complex_t tmp; hid_t complex_id; printf("%-70s", "Testing compound data types"); /* Create the empty type */ if ((complex_id = H5Tcreate(H5T_COMPOUND, sizeof tmp))<0) goto error; /* Add a couple fields */ if (H5Tinsert(complex_id, "real", HOFFSET(complex_t, re), H5T_NATIVE_DOUBLE)<0) goto error; if (H5Tinsert(complex_id, "imaginary", HOFFSET(complex_t, im), H5T_NATIVE_DOUBLE)<0) goto error; if (H5Tclose (complex_id)<0) goto error; puts(" PASSED"); return 0; error: return -1; } /*------------------------------------------------------------------------- * Function: test_transient * * Purpose: Tests transient data types. * * Return: Success: 0 * * Failure: -1 * * Programmer: Robb Matzke * Thursday, June 4, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t test_transient (void) { static hsize_t ds_size[2] = {10, 20}; hid_t file=-1, type=-1, space=-1, dset=-1, t2=-1; printf ("%-70s", "Testing transient data types"); if ((file=H5Fcreate (FILE_NAME_1, H5F_ACC_TRUNC|H5F_ACC_DEBUG, H5P_DEFAULT, H5P_DEFAULT))<0) goto error; space = H5Screate_simple (2, ds_size, ds_size); /* Predefined types cannot be modified or closed */ H5E_BEGIN_TRY { if (H5Tset_precision (H5T_NATIVE_INT, 256)>=0) { puts ("*FAILED*"); puts (" Predefined types should not be modifiable!"); goto error; } if (H5Tclose (H5T_NATIVE_INT)>=0) { puts ("*FAILED*"); puts (" Predefined types should not be closable!"); goto error; } } H5E_END_TRY; /* Copying a predefined type results in a modifiable copy */ if ((type=H5Tcopy (H5T_NATIVE_INT))<0) goto error; if (H5Tset_precision (type, 256)<0) goto error; /* It should not be possible to create an attribute for a transient type */ H5E_BEGIN_TRY { if (H5Acreate (type, "attr1", H5T_NATIVE_INT, space, H5P_DEFAULT)>=0) { puts ("*FAILED*"); puts (" Attributes should not be allowed for transient types!"); goto error; } } H5E_END_TRY; /* Create a dataset from a transient data type */ if (H5Tclose (type)<0) goto error; if ((type = H5Tcopy (H5T_NATIVE_INT))<0) goto error; if ((dset=H5Dcreate (file, "dset1", type, space, H5P_DEFAULT))<0) { goto error; } /* The type returned from a dataset should not be modifiable */ if ((t2 = H5Dget_type (dset))<0) goto error; H5E_BEGIN_TRY { if (H5Tset_precision (t2, 256)>=0) { puts ("*FAILED*"); puts (" Dataset data types should not be modifiable!"); goto error; } } H5E_END_TRY; if (H5Tclose (t2)<0) goto error; /* * Close the dataset and reopen it, testing that it's type is still * read-only. */ if (H5Dclose (dset)<0) goto error; if ((dset=H5Dopen (file, "dset1"))<0) goto error; if ((t2 = H5Dget_type (dset))<0) goto error; H5E_BEGIN_TRY { if (H5Tset_precision (t2, 256)>=0) { puts ("*FAILED*"); puts (" Dataset data types should not be modifiable!"); goto error; } } H5E_END_TRY; if (H5Tclose (t2)<0) goto error; /* * Get the dataset data type by applying H5Tcopy() to the dataset. The * result should be modifiable. */ if ((t2=H5Tcopy (dset))<0) goto error; if (H5Tset_precision (t2, 256)<0) goto error; if (H5Tclose (t2)<0) goto error; H5Dclose (dset); H5Fclose (file); H5Tclose (type); H5Sclose (space); puts (" PASSED"); return 0; error: H5E_BEGIN_TRY { H5Tclose (t2); H5Tclose (type); H5Sclose (space); H5Dclose (dset); H5Fclose (file); } H5E_END_TRY; return -1; } /*------------------------------------------------------------------------- * Function: test_named * * Purpose: Tests named data types. * * Return: Success: 0 * * Failure: -1 * * Programmer: Robb Matzke * Monday, June 1, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t test_named (void) { hid_t file=-1, type=-1, space=-1, dset=-1, t2=-1, attr1=-1; herr_t status; static hsize_t ds_size[2] = {10, 20}; printf ("%-70s", "Testing named data types"); if ((file=H5Fcreate (FILE_NAME_2, H5F_ACC_TRUNC|H5F_ACC_DEBUG, H5P_DEFAULT, H5P_DEFAULT))<0) goto error; space = H5Screate_simple (2, ds_size, ds_size); /* Predefined types cannot be committed */ H5E_BEGIN_TRY { if (H5Tcommit (file, "test_named_1 (should not exist)", H5T_NATIVE_INT)>=0) { puts ("*FAILED*"); puts (" Predefined types should not be committable!"); goto error; } } H5E_END_TRY; /* Copy a predefined data type and commit the copy */ if ((type = H5Tcopy (H5T_NATIVE_INT))<0) goto error; if (H5Tcommit (file, "native-int", type)<0) goto error; if ((status=H5Tcommitted (type))<0) goto error; if (0==status) { puts ("*FAILED*"); puts (" H5Tcommitted() returned false!"); goto error; } /* We should not be able to modify a type after it has been committed. */ H5E_BEGIN_TRY { if (H5Tset_precision (type, 256)>=0) { puts ("*FAILED*"); puts (" Committed type is not constant!"); goto error; } } H5E_END_TRY; /* We should not be able to re-commit a committed type */ H5E_BEGIN_TRY { if (H5Tcommit (file, "test_named_2 (should not exist)", type)>=0) { puts ("*FAILED*"); puts (" Committed types should not be recommitted!"); goto error; } } H5E_END_TRY; /* It should be possible to define an attribute for the named type */ if ((attr1=H5Acreate (type, "attr1", H5T_NATIVE_INT, space, H5P_DEFAULT))<0) goto error; if (H5Aclose (attr1)<0) goto error; /* * Copying a committed type should result in a transient type which is * not locked. */ if ((t2 = H5Tcopy (type))<0) goto error; if ((status=H5Tcommitted (t2))<0) goto error; if (status) { puts ("*FAILED*"); puts (" Copying a named type should result in a transient type!"); goto error; } if (H5Tset_precision (t2, 256)<0) goto error; if (H5Tclose (t2)<0) goto error; /* * Close the committed type and reopen it. It should return a named type. */ if (H5Tclose (type)<0) goto error; if ((type=H5Topen (file, "native-int"))<0) goto error; if ((status=H5Tcommitted (type))<0) goto error; if (!status) { puts ("*FAILED*"); puts (" Opened named types should be named types!"); goto error; } /* Create a dataset that uses the named type */ if ((dset = H5Dcreate (file, "dset1", type, space, H5P_DEFAULT))<0) { goto error; } /* Get the dataset's data type and make sure it's a named type */ if ((t2 = H5Dget_type (dset))<0) goto error; if ((status=H5Tcommitted (t2))<0) goto error; if (!status) { puts ("*FAILED*"); puts (" Dataset type should be a named type!"); goto error; } /* Close the dataset, then close its type, then reopen the dataset */ if (H5Dclose (dset)<0) goto error; if (H5Tclose (t2)<0) goto error; if ((dset = H5Dopen (file, "dset1"))<0) goto error; /* Get the dataset's type and make sure it's named */ if ((t2 = H5Dget_type (dset))<0) goto error; if ((status=H5Tcommitted (t2))<0) goto error; if (!status) { puts ("*FAILED*"); puts (" Dataset type should be a named type!"); goto error; } /* * Close the dataset and create another with the type returned from the * first dataset. */ if (H5Dclose (dset)<0) goto error; if ((dset=H5Dcreate (file, "dset2", t2, space, H5P_DEFAULT))<0) { goto error; } /* Reopen the second dataset and make sure the type is shared */ if (H5Tclose (t2)<0) goto error; if (H5Dclose (dset)<0) goto error; if ((dset = H5Dopen (file, "dset2"))<0) goto error; if ((t2 = H5Dget_type (dset))<0) goto error; if ((status=H5Tcommitted (t2))<0) goto error; if (!status) { puts ("*FAILED*"); puts (" Dataset type should be a named type!"); goto error; } if (H5Tclose (t2)<0) goto error; /* * Get the dataset data type by applying H5Tcopy() to the dataset. The * result should be modifiable. */ if ((t2=H5Tcopy (dset))<0) goto error; if (H5Tset_precision (t2, 256)<0) goto error; if (H5Tclose (t2)<0) goto error; /* Clean up */ if (H5Dclose (dset)<0) goto error; if (H5Tclose (type)<0) goto error; if (H5Sclose (space)<0) goto error; if (H5Fclose (file)<0) goto error; puts (" PASSED"); return 0; error: H5E_BEGIN_TRY { H5Tclose (t2); H5Tclose (type); H5Sclose (space); H5Dclose (dset); H5Fclose (file); } H5E_END_TRY; return -1; } /*------------------------------------------------------------------------- * Function: mkstr * * Purpose: Create a new string data type * * Return: Success: New type * * Failure: -1 * * Programmer: Robb Matzke * Monday, August 10, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static hid_t mkstr(size_t len, H5T_str_t strpad) { hid_t t; if ((t=H5Tcopy(H5T_C_S1))<0) return -1; if (H5Tset_size(t, len)<0) return -1; if (H5Tset_strpad(t, strpad)<0) return -1; return t; } /*------------------------------------------------------------------------- * Function: test_conv_str_1 * * Purpose: Test string conversions * * Return: Success: 0 * * Failure: -1 * * Programmer: Robb Matzke * Monday, August 10, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t test_conv_str_1(void) { char *buf=NULL; hid_t src_type, dst_type; printf("%-70s", "Testing string conversions"); fflush(stdout); /* * Convert a null-terminated string to a shorter and longer null * terminated string. */ src_type = mkstr(10, H5T_STR_NULLTERM); dst_type = mkstr(5, H5T_STR_NULLTERM); buf = calloc(2, 10); memcpy(buf, "abcdefghi\0abcdefghi\0", 20); if (H5Tconvert(src_type, dst_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcd\0abcd\0abcdefghi\0", 20)) { puts("*FAILED*"); puts(" Truncated C-string test failed"); goto error; } if (H5Tconvert(dst_type, src_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcd\0\0\0\0\0\0abcd\0\0\0\0\0\0", 20)) { puts("*FAILED*"); puts(" Extended C-string test failed"); goto error; } free(buf); H5Tclose(src_type); H5Tclose(dst_type); /* * Convert a null padded string to a shorter and then longer string. */ src_type = mkstr(10, H5T_STR_NULLPAD); dst_type = mkstr(5, H5T_STR_NULLPAD); buf = calloc(2, 10); memcpy(buf, "abcdefghijabcdefghij", 20); if (H5Tconvert(src_type, dst_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcdeabcdeabcdefghij", 20)) { puts("*FAILED*"); puts(" Truncated C buffer test failed"); goto error; } if (H5Tconvert(dst_type, src_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcde\0\0\0\0\0abcde\0\0\0\0\0", 20)) { puts("*FAILED*"); puts(" Extended C buffer test failed"); goto error; } free(buf); H5Tclose(src_type); H5Tclose(dst_type); /* * Convert a space-padded string to a shorter and then longer string. */ src_type = mkstr(10, H5T_STR_SPACEPAD); dst_type = mkstr(5, H5T_STR_SPACEPAD); buf = calloc(2, 10); memcpy(buf, "abcdefghijabcdefghij", 20); if (H5Tconvert(src_type, dst_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcdeabcdeabcdefghij", 20)) { puts("*FAILED*"); puts(" Truncated Fortran-string test failed"); goto error; } if (H5Tconvert(dst_type, src_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcde abcde ", 20)) { puts("*FAILED*"); puts(" Extended Fortran-string test failed"); goto error; } free(buf); H5Tclose(src_type); H5Tclose(dst_type); /* * What happens if a null-terminated string is not null terminated? If * the conversion is to an identical string then nothing happens but if * the destination is a different size or type of string then the right * thing should happen. */ src_type = mkstr(10, H5T_STR_NULLTERM); dst_type = mkstr(10, H5T_STR_NULLTERM); buf = calloc(2, 10); memcpy(buf, "abcdefghijabcdefghij", 20); if (H5Tconvert(src_type, dst_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcdefghijabcdefghij", 20)) { puts("*FAILED*"); puts(" Non-terminated string test 1"); goto error; } H5Tclose(dst_type); dst_type = mkstr(5, H5T_STR_NULLTERM); memcpy(buf, "abcdefghijabcdefghij", 20); if (H5Tconvert(src_type, dst_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcd\0abcd\0abcdefghij", 20)) { puts("*FAILED*"); puts(" Non-terminated string test 2"); goto error; } memcpy(buf, "abcdeabcdexxxxxxxxxx", 20); if (H5Tconvert(dst_type, src_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcde\0\0\0\0\0abcde\0\0\0\0\0", 20)) { puts("*FAILED*"); puts(" Non-terminated string test 2"); goto error; } free(buf); H5Tclose(src_type); H5Tclose(dst_type); /* * Test C string to Fortran and vice versa. */ src_type = mkstr(10, H5T_STR_NULLTERM); dst_type = mkstr(10, H5T_STR_SPACEPAD); buf = calloc(2, 10); memcpy(buf, "abcdefghi\0abcdefghi\0", 20); if (H5Tconvert(src_type, dst_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcdefghi abcdefghi ", 20)) { puts("*FAILED*"); puts(" C string to Fortran test 1"); goto error; } if (H5Tconvert(dst_type, src_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcdefghi\0abcdefghi\0", 20)) { puts("*FAILED*"); puts(" Fortran to C string test 1"); goto error; } H5Tclose(dst_type); dst_type = mkstr(5, H5T_STR_SPACEPAD); memcpy(buf, "abcdefgh\0\0abcdefgh\0\0", 20); if (H5Tconvert(src_type, dst_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcdeabcdeabcdefgh\0\0", 20)) { puts("*FAILED*"); puts(" C string to Fortran test 2"); goto error; } if (H5Tconvert(dst_type, src_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcde\0\0\0\0\0abcde\0\0\0\0\0", 20)) { puts("*FAILED*"); puts(" Fortran to C string test 2"); goto error; } H5Tclose(src_type); H5Tclose(dst_type); src_type = mkstr(5, H5T_STR_NULLTERM); dst_type = mkstr(10, H5T_STR_SPACEPAD); memcpy(buf, "abcd\0abcd\0xxxxxxxxxx", 20); if (H5Tconvert(src_type, dst_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcd abcd ", 20)) { puts("*FAILED*"); puts(" C string to Fortran test 3"); goto error; } if (H5Tconvert(dst_type, src_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcd\0abcd\0abcd ", 20)) { puts("*FAILED*"); puts(" Fortran to C string test 3"); goto error; } free(buf); H5Tclose(src_type); H5Tclose(dst_type); /* * Test C buffer to Fortran and vice versa. */ src_type = mkstr(10, H5T_STR_NULLPAD); dst_type = mkstr(10, H5T_STR_SPACEPAD); buf = calloc(2, 10); memcpy(buf, "abcdefghijabcdefghij", 20); if (H5Tconvert(src_type, dst_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcdefghijabcdefghij", 20)) { puts("*FAILED*"); puts(" C buffer to Fortran test 1"); goto error; } if (H5Tconvert(dst_type, src_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcdefghijabcdefghij", 20)) { puts("*FAILED*"); puts(" Fortran to C buffer test 1"); goto error; } H5Tclose(dst_type); dst_type = mkstr(5, H5T_STR_SPACEPAD); memcpy(buf, "abcdefgh\0\0abcdefgh\0\0", 20); if (H5Tconvert(src_type, dst_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcdeabcdeabcdefgh\0\0", 20)) { puts("*FAILED*"); puts(" C buffer to Fortran test 2"); goto error; } if (H5Tconvert(dst_type, src_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcde\0\0\0\0\0abcde\0\0\0\0\0", 20)) { puts("*FAILED*"); puts(" Fortran to C buffer test 2"); goto error; } H5Tclose(src_type); H5Tclose(dst_type); src_type = mkstr(5, H5T_STR_NULLPAD); dst_type = mkstr(10, H5T_STR_SPACEPAD); memcpy(buf, "abcd\0abcd\0xxxxxxxxxx", 20); if (H5Tconvert(src_type, dst_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcd abcd ", 20)) { puts("*FAILED*"); puts(" C buffer to Fortran test 3"); goto error; } if (H5Tconvert(dst_type, src_type, 2, buf, NULL)<0) goto error; if (memcmp(buf, "abcd\0abcd\0abcd ", 20)) { puts("*FAILED*"); puts(" Fortran to C buffer test 3"); goto error; } free(buf); H5Tclose(src_type); H5Tclose(dst_type); puts(" PASSED"); return 0; error: return -1; } /*------------------------------------------------------------------------- * Function: test_conv_str_2 * * Purpose: Tests C-to-Fortran and Fortran-to-C string conversion speed. * * Return: Success: 0 * * Failure: -1 * * Programmer: Robb Matzke * Monday, August 10, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t test_conv_str_2(void) { char *buf=NULL, s[80]; hid_t c_type, f_type; const size_t nelmts = 200000, ntests=5; size_t i, j, nchars; herr_t ret_value = -1; /* * Initialize types and buffer. */ c_type = mkstr(8, H5T_STR_NULLPAD); f_type = mkstr(8, H5T_STR_SPACEPAD); buf = calloc(nelmts, 8); for (i=0; i (unsigned)0xffff */ byte[0] = byte[1] = byte[2] = 0; byte[3] = 0x80; if (H5Tconvert (H5T_STD_U32LE, H5T_STD_U16LE, 1, byte, NULL)<0) { goto error; } if (byte[0]!=0xff || byte[1]!=0xff) { puts ("*FAILED*"); puts (" (unsigned)0x80000000 -> (unsigned)0xffff"); goto error; } /* (unsigned)0xffffffff -> (signed)0x7fff */ byte[0] = byte[1] = byte[2] = byte[3] = 0xff; if (H5Tconvert (H5T_STD_U32LE, H5T_STD_I16LE, 1, byte, NULL)<0) { goto error; } if (byte[0]!=0xff || byte[1]!=0x7f) { puts ("*FAILED*"); puts (" (unsigned)0xffffffff -> (signed)0x7f"); goto error; } /* (signed)0xffffffff -> (unsigned)0x0000 */ byte[0] = byte[1] = byte[2] = byte[3] = 0xff; if (H5Tconvert (H5T_STD_I32LE, H5T_STD_U16LE, 1, byte, NULL)<0) { goto error; } if (byte[0]!=0x00 || byte[1]!=0x00) { puts ("*FAILED*"); puts (" (signed)0xffffffff -> (unsigned)0x00"); goto error; } /* (signed)0x7fffffff -> (unsigned)0xffff */ byte[0] = byte[1] = byte[2] = 0xff; byte[3] = 0x7f; if (H5Tconvert (H5T_STD_I32LE, H5T_STD_U16LE, 1, byte, NULL)<0) { goto error; } if (byte[0]!=0xff || byte[1]!=0xff) { puts ("*FAILED*"); puts (" (signed)0x7fffffff -> (unsigned)0xffff"); goto error; } /* (signed)0x7fffffff -> (signed)0x7fff */ byte[0] = byte[1] = byte[2] = 0xff; byte[3] = 0x7f; if (H5Tconvert (H5T_STD_I32LE, H5T_STD_I16LE, 1, byte, NULL)<0) { goto error; } if (byte[0]!=0xff || byte[1]!=0x7f) { puts ("*FAILED*"); puts (" (signed)0x7fffffff -> (signed)0x7fff"); goto error; } /* (signed)0xbfffffff -> (signed)0x8000 */ byte[0] = byte[1] = byte[2] = 0xff; byte[3] = 0xbf; if (H5Tconvert (H5T_STD_I32LE, H5T_STD_I16LE, 1, byte, NULL)<0) { goto error; } if (byte[0]!=0x00 || byte[1]!=0x80) { puts ("*FAILED*"); puts (" (signed)0xbfffffff -> (signed)0x8000"); goto error; } puts (" PASSED"); /*----------------------------------------------------------------------- * Test random cases. *----------------------------------------------------------------------- */ printf ("%-70s", "Testing random integer conversions"); fflush (stdout); /* Allocate buffers */ buf = malloc (nelmts*8); saved = malloc (nelmts*8); for (i=0; i0) { while (child_pid!=waitpid(child_pid, &status, 0)) /*void*/; if (WIFEXITED(status) && 255==WEXITSTATUS(status)) { return 0; /*child exit after catching SIGFPE*/ } else if (WIFEXITED(status)) { return WEXITSTATUS(status); } else { puts(" Child didn't exit normally."); return 1; } } #endif /* * The remainder of this function is executed only by the child if * HANDLE_SIGFPE is defined. */ signal(SIGFPE,fpe_handler); /* What are the names of the source and destination types */ if (H5Tequal(src, H5T_NATIVE_FLOAT)) { src_type_name = "float"; src_type = FLT_FLOAT; } else if (H5Tequal(src, H5T_NATIVE_DOUBLE)) { src_type_name = "double"; src_type = FLT_DOUBLE; #ifdef USE_LDOUBLE } else if (H5Tequal(src, H5T_NATIVE_LDOUBLE)) { src_type_name = "long double"; src_type = FLT_LDOUBLE; #endif } else { src_type_name = "UNKNOWN"; src_type = FLT_OTHER; } if (H5Tequal(dst, H5T_NATIVE_FLOAT)) { dst_type_name = "float"; dst_type = FLT_FLOAT; } else if (H5Tequal(dst, H5T_NATIVE_DOUBLE)) { dst_type_name = "double"; dst_type = FLT_DOUBLE; #ifdef USE_LDOUBLE } else if (H5Tequal(dst, H5T_NATIVE_LDOUBLE)) { dst_type_name = "long double"; dst_type = FLT_LDOUBLE; #endif } else { dst_type_name = "UNKNOWN"; dst_type = FLT_OTHER; } /* Sanity checks */ assert(sizeof(float)!=sizeof(double)); if (FLT_OTHER==src_type || FLT_OTHER==dst_type) { sprintf(str, "Testing random %s %s -> %s conversions", name, src_type_name, dst_type_name); printf ("%-70s", str); puts("*FAILED*"); puts(" Unknown data type."); goto error; } /* Allocate buffers */ endian = H5Tget_order(H5T_NATIVE_FLOAT); src_size = H5Tget_size(src); dst_size = H5Tget_size(dst); buf = malloc(nelmts*MAX(src_size, dst_size)); saved = malloc(nelmts*MAX(src_size, dst_size)); noverflows_g = 0; for (i=0; i %s conversions (test %d/%d)", name, src_type_name, dst_type_name, (int)i+1, (int)ntests); printf ("%-70s", str); fflush(stdout); fails_this_test = 0; /* * Initialize the source buffers to random bits. The `buf' buffer * will be used for the conversion while the `saved' buffer will be * used for the comparison later. */ if (!skip_overflow_tests_g) { for (j=0; j=max_fails) { puts(" maximum failures reached, aborting test..."); goto done; } } puts(" PASSED"); } if (noverflows_g>0) { printf(" %d overflow%s\n", noverflows_g, 1==noverflows_g?"":"s"); } done: if (buf) free (buf); if (saved) free (saved); #ifdef HANDLE_SIGFPE exit(MIN((int)fails_all_tests, 254)); #else return (int)fails_all_tests; #endif error: if (buf) free (buf); if (saved) free (saved); #ifdef HANDLE_SIGFPE exit(MIN(MAX((int)fails_all_tests, 1), 254)); #else return MAX((int)fails_all_tests, 1); #endif } /*------------------------------------------------------------------------- * Function: main * * Purpose: Test the data type interface. * * Return: Success: * * Failure: * * Programmer: Robb Matzke * Tuesday, December 9, 1997 * * Modifications: * *------------------------------------------------------------------------- */ int main(void) { unsigned long nerrors = 0; /* Set the error handler */ H5Eset_auto (display_error_cb, NULL); /* Set the overflow handler */ H5Tset_overflow(overflow_handler); /* Do the tests */ nerrors += test_classes()<0 ? 1 : 0; nerrors += test_copy()<0 ? 1 : 0; nerrors += test_compound()<0 ? 1 : 0; nerrors += test_transient ()<0 ? 1 : 0; nerrors += test_named ()<0 ? 1 : 0; nerrors += test_conv_str_1()<0 ? 1 : 0; nerrors += test_conv_str_2()<0 ? 1 : 0; nerrors += test_conv_int ()<0 ? 1 : 0; /* Does floating point overflow generate a SIGFPE? */ generates_sigfpe(); /* Test degenerate cases */ nerrors += test_conv_flt_1("noop", H5T_NATIVE_FLOAT, H5T_NATIVE_FLOAT); nerrors += test_conv_flt_1("noop", H5T_NATIVE_DOUBLE, H5T_NATIVE_DOUBLE); /* Test hardware conversion functions */ nerrors += test_conv_flt_1("hw", H5T_NATIVE_FLOAT, H5T_NATIVE_DOUBLE); nerrors += test_conv_flt_1("hw", H5T_NATIVE_DOUBLE, H5T_NATIVE_FLOAT); /* Test software conversion functions */ H5Tunregister(H5T_conv_float_double); H5Tunregister(H5T_conv_double_float); nerrors += test_conv_flt_1("sw", H5T_NATIVE_FLOAT, H5T_NATIVE_DOUBLE); nerrors += test_conv_flt_1("sw", H5T_NATIVE_DOUBLE, H5T_NATIVE_FLOAT); #ifdef USE_LDOUBLE nerrors += test_conv_flt_1("sw", H5T_NATIVE_FLOAT, H5T_NATIVE_LDOUBLE); nerrors += test_conv_flt_1("sw", H5T_NATIVE_DOUBLE, H5T_NATIVE_LDOUBLE); nerrors += test_conv_flt_1("sw", H5T_NATIVE_LDOUBLE, H5T_NATIVE_FLOAT); nerrors += test_conv_flt_1("sw", H5T_NATIVE_LDOUBLE, H5T_NATIVE_DOUBLE); #endif if (nerrors) { printf("***** %lu FAILURE%s! *****\n", nerrors, 1==nerrors?"":"S"); exit(1); } printf("All data type tests passed.\n"); cleanup (); return 0; }