mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-12-09 07:32:32 +08:00
734aebc395
HDopen() calls. Also fixed a minor const warning in the core VFD.
1634 lines
55 KiB
C
1634 lines
55 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
* Copyright by The HDF Group. *
|
||
* Copyright by the Board of Trustees of the University of Illinois. *
|
||
* 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 COPYING file, which can be found at the root of the source code *
|
||
* distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
|
||
* If you do not have access to either file, you may request a copy from *
|
||
* help@hdfgroup.org. *
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
||
/*
|
||
* Programmer: Robb Matzke <matzke@llnl.gov>
|
||
* Tuesday, March 3, 1998
|
||
*
|
||
* Purpose: Tests datasets stored in external raw files.
|
||
*/
|
||
#include "h5test.h"
|
||
|
||
const char *FILENAME[] = {
|
||
"extern_1",
|
||
"extern_2",
|
||
"extern_3",
|
||
"extern_4",
|
||
"extern_dir/file_1",
|
||
"extern_5",
|
||
NULL
|
||
};
|
||
|
||
/* A similar collection of files is used for the tests that
|
||
* perform file I/O.
|
||
*/
|
||
#define N_EXT_FILES 4
|
||
#define PART_SIZE 25
|
||
#define TOTAL_SIZE 100
|
||
#define GARBAGE_PER_FILE 10
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: files_have_same_contents
|
||
*
|
||
* Purpose: Determines whether two files contain the same data.
|
||
*
|
||
* Return: Success: nonzero if same, zero if different.
|
||
* Failure: zero
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Wednesday, March 4, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static hbool_t
|
||
files_have_same_contents(const char *name1, const char *name2)
|
||
{
|
||
int fd1 = 0, fd2 = 0;
|
||
ssize_t n1, n2;
|
||
char buf1[1024], buf2[1024];
|
||
hbool_t ret = FALSE; /* not equal until proven otherwise */
|
||
|
||
if((fd1 = HDopen(name1, O_RDONLY)) < 0)
|
||
goto out;
|
||
if((fd2 = HDopen(name2, O_RDONLY)) < 0)
|
||
goto out;
|
||
|
||
/* Loop until files are empty or we encounter a problem */
|
||
while(1) {
|
||
HDmemset(buf1, 0, sizeof(buf1));
|
||
HDmemset(buf2, 0, sizeof(buf2));
|
||
|
||
n1 = HDread(fd1, buf1, sizeof(buf1));
|
||
if(n1 < 0 || (size_t)n1 > sizeof(buf1))
|
||
break;
|
||
n2 = HDread(fd2, buf2, sizeof(buf2));
|
||
if(n2 < 0 || (size_t)n2 > sizeof(buf2))
|
||
break;
|
||
|
||
if(n1 != n2)
|
||
break;
|
||
|
||
if(n1 == 0 && n2 == 0) {
|
||
ret = TRUE;
|
||
break;
|
||
}
|
||
|
||
if(HDmemcmp(buf1, buf2, (size_t)n1))
|
||
break;
|
||
|
||
} /* end while */
|
||
|
||
out:
|
||
if(fd1)
|
||
HDclose(fd1);
|
||
if(fd2)
|
||
HDclose(fd2);
|
||
return ret;
|
||
} /* end files_have_same_contents() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: reset_raw_data_files
|
||
*
|
||
* Purpose: Resets the data in the raw data files for tests that
|
||
* perform dataset I/O on a set of files.
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Dana Robinson
|
||
* February 2016
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
reset_raw_data_files(void)
|
||
{
|
||
int fd = 0; /* external file descriptor */
|
||
size_t i, j; /* iterators */
|
||
hssize_t n; /* bytes of I/O */
|
||
char filename[1024]; /* file name */
|
||
int data[PART_SIZE]; /* raw data buffer */
|
||
uint8_t *garbage = NULL; /* buffer of garbage data */
|
||
size_t garbage_count; /* size of garbage buffer */
|
||
size_t garbage_bytes; /* # of garbage bytes written to file */
|
||
|
||
/* Set up garbage buffer */
|
||
garbage_count = N_EXT_FILES * GARBAGE_PER_FILE;
|
||
if(NULL == (garbage = (uint8_t *)HDcalloc(garbage_count, sizeof(uint8_t))))
|
||
goto error;
|
||
for(i = 0; i < garbage_count; i++)
|
||
garbage[i] = 0xFF;
|
||
|
||
/* The *r files are pre-filled with data and are used to
|
||
* verify that read operations work correctly.
|
||
*/
|
||
for(i = 0; i < N_EXT_FILES; i++) {
|
||
|
||
/* Open file */
|
||
HDsprintf(filename, "extern_%lur.raw", (unsigned long)i + 1);
|
||
if((fd = HDopen(filename, O_RDWR|O_CREAT|O_TRUNC, H5_POSIX_CREATE_MODE_RW)) < 0)
|
||
goto error;
|
||
|
||
/* Write garbage data to the file. This allows us to test the
|
||
* the ability to set an offset in the raw data file.
|
||
*/
|
||
garbage_bytes = i * 10;
|
||
n = HDwrite(fd, garbage, garbage_bytes);
|
||
if(n < 0 || (size_t)n != garbage_bytes)
|
||
goto error;
|
||
|
||
/* Fill array with data */
|
||
for(j = 0; j < PART_SIZE; j++) {
|
||
data[j] = (int)(i * 25 + j);
|
||
} /* end for */
|
||
|
||
/* Write raw data to the file. */
|
||
n = HDwrite(fd, data, sizeof(data));
|
||
if(n != sizeof(data))
|
||
goto error;
|
||
|
||
/* Close this file */
|
||
HDclose(fd);
|
||
|
||
} /* end for */
|
||
|
||
/* The *w files are only pre-filled with the garbage data and are
|
||
* used to verify that write operations work correctly. The individual
|
||
* tests fill in the actual data.
|
||
*/
|
||
for(i = 0; i < N_EXT_FILES; i++) {
|
||
|
||
/* Open file */
|
||
HDsprintf(filename, "extern_%luw.raw", (unsigned long)i + 1);
|
||
if((fd = HDopen(filename, O_RDWR|O_CREAT|O_TRUNC, H5_POSIX_CREATE_MODE_RW)) < 0)
|
||
goto error;
|
||
|
||
/* Write garbage data to the file. This allows us to test the
|
||
* the ability to set an offset in the raw data file.
|
||
*/
|
||
garbage_bytes = i * 10;
|
||
n = HDwrite(fd, garbage, garbage_bytes);
|
||
if(n < 0 || (size_t)n != garbage_bytes)
|
||
goto error;
|
||
|
||
/* Close this file */
|
||
HDclose(fd);
|
||
|
||
} /* end for */
|
||
HDfree(garbage);
|
||
return SUCCEED;
|
||
|
||
error:
|
||
if(fd)
|
||
HDclose(fd);
|
||
if(garbage)
|
||
HDfree(garbage);
|
||
return FAIL;
|
||
} /* end reset_raw_data_files() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_non_extendible
|
||
*
|
||
* Purpose: Tests a non-extendible dataset with a single external file.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Monday, November 23, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_non_extendible(hid_t file)
|
||
{
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t space = -1; /* data space */
|
||
hid_t dset = -1; /* dataset */
|
||
hsize_t cur_size[1]; /* data space current size */
|
||
hsize_t max_size[1]; /* data space maximum size */
|
||
int n; /* number of external files */
|
||
char name[256]; /* external file name */
|
||
off_t file_offset; /* external file offset */
|
||
hsize_t file_size; /* sizeof external file segment */
|
||
haddr_t dset_addr; /* address of dataset */
|
||
|
||
TESTING("fixed-size data space, exact storage");
|
||
|
||
/* Create the dataset */
|
||
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
cur_size[0] = max_size[0] = 100;
|
||
if(H5Pset_external(dcpl, "ext1.data", (off_t)0, (hsize_t)(max_size[0] * sizeof(int))) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((space = H5Screate_simple(1, cur_size, max_size)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((dset = H5Dcreate2(file, "dset1", H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Dclose(dset) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Sclose(space) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Read dataset creation information */
|
||
if((dset = H5Dopen2(file, "dset1", H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Test dataset address. Should be undefined. */
|
||
H5E_BEGIN_TRY {
|
||
dset_addr = H5Dget_offset(dset);
|
||
} H5E_END_TRY;
|
||
if(dset_addr != HADDR_UNDEF)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Check external count */
|
||
if((dcpl = H5Dget_create_plist(dset)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((n = H5Pget_external_count(dcpl)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(1 != n) {
|
||
H5_FAILED();
|
||
HDputs(" Returned external count is wrong.");
|
||
printf(" got: %d\n ans: 1\n", n);
|
||
goto error;
|
||
} /* end if */
|
||
|
||
HDstrcpy(name + sizeof(name) - 4, "...");
|
||
if(H5Pget_external(dcpl, 0, sizeof(name) - 4, name, &file_offset, &file_size) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Check file offset */
|
||
if(file_offset != 0) {
|
||
H5_FAILED();
|
||
HDputs(" Wrong file offset.");
|
||
printf(" got: %lu\n ans: 0\n", (unsigned long)file_offset);
|
||
goto error;
|
||
} /* end if */
|
||
|
||
/* Check file size */
|
||
if(file_size != (max_size[0] * sizeof(int))) {
|
||
H5_FAILED();
|
||
HDputs(" Wrong file size.");
|
||
printf(" got: %lu\n ans: %lu\n", (unsigned long)file_size, (unsigned long)max_size[0]*sizeof(int));
|
||
goto error;
|
||
} /* end if */
|
||
|
||
/* Done (dataspace was previously closed) */
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Pclose(dcpl);
|
||
H5Sclose(space);
|
||
H5Dclose(dset);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_non_extendible() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_too_small
|
||
*
|
||
* Purpose: Test a single external file which is too small to represent
|
||
* all the data.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Monday, November 23, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_too_small(hid_t file)
|
||
{
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t space = -1; /* data space */
|
||
hid_t dset = -1; /* dataset */
|
||
hsize_t cur_size[1]; /* current data space size */
|
||
hsize_t max_size[1]; /* maximum data space size */
|
||
|
||
TESTING("external storage is too small");
|
||
|
||
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
cur_size[0] = max_size[0] = 100;
|
||
if(H5Pset_external(dcpl, "ext1.data", (off_t)0, (hsize_t)(max_size[0] * sizeof(int) - 1)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((space = H5Screate_simple(1, cur_size, max_size)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
H5E_BEGIN_TRY {
|
||
dset = H5Dcreate2(file, "dset2", H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, H5P_DEFAULT);
|
||
} H5E_END_TRY;
|
||
if(dset >= 0)
|
||
FAIL_PUTS_ERROR(" Small external file succeeded instead of failing.");
|
||
if(H5Sclose(space) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Sclose(space);
|
||
H5Pclose(dcpl);
|
||
H5Dclose(dset);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_too_small() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_large_enough_current_eventual
|
||
*
|
||
* Purpose: Test a single external file which is large enough to
|
||
* represent the current data and large enough to represent the
|
||
* eventual size of the data.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Monday, November 23, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_large_enough_current_eventual(hid_t file)
|
||
{
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t space = -1; /* data space */
|
||
hid_t dset = -1; /* dataset */
|
||
hsize_t cur_size[1]; /* current data space size */
|
||
hsize_t max_size[1]; /* maximum data space size */
|
||
|
||
TESTING("extendible dataspace, exact external size");
|
||
|
||
if((dcpl = H5Pcreate (H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
cur_size[0] = 100;
|
||
max_size[0] = 200;
|
||
if(H5Pset_external(dcpl, "ext1.data", (off_t)0, (hsize_t)(max_size[0] * sizeof(int))) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((space = H5Screate_simple(1, cur_size, max_size)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((dset = H5Dcreate2(file, "dset3", H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
if(H5Sclose(space) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Dclose(dset);
|
||
H5Pclose(dcpl);
|
||
H5Sclose(space);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_large_enough_current_eventual() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_large_enough_current_not_eventual
|
||
*
|
||
* Purpose: Test a single external file which is large enough for the
|
||
* current data size but not large enough for the eventual size.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Monday, November 23, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_large_enough_current_not_eventual(hid_t file)
|
||
{
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t space = -1; /* data space */
|
||
hid_t dset = -1; /* dataset */
|
||
hsize_t cur_size[1]; /* current data space size */
|
||
hsize_t max_size[1]; /* maximum data space size */
|
||
|
||
TESTING("extendible dataspace, external storage is too small");
|
||
|
||
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
cur_size[0] = 100;
|
||
max_size[0] = 200;
|
||
if(H5Pset_external(dcpl, "ext1.data", (off_t)0, (hsize_t)(max_size[0] * sizeof(int) - 1)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((space = H5Screate_simple(1, cur_size, max_size)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
H5E_BEGIN_TRY {
|
||
dset = H5Dcreate2(file, "dset4", H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, H5P_DEFAULT);
|
||
} H5E_END_TRY;
|
||
if(dset >= 0)
|
||
FAIL_PUTS_ERROR(" Small external file succeeded instead of failing.");
|
||
|
||
if(H5Sclose(space) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Dclose(dset);
|
||
H5Pclose(dcpl);
|
||
H5Sclose(space);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_large_enough_current_not_eventual() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_unlimited
|
||
*
|
||
* Purpose: Test a single external file of unlimited size and an
|
||
* unlimited data space.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Monday, November 23, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_unlimited(hid_t file)
|
||
{
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t space = -1; /* data space */
|
||
hid_t dset = -1; /* dataset */
|
||
hsize_t cur_size[1]; /* data space current size */
|
||
hsize_t max_size[1]; /* data space maximum size */
|
||
int n; /* number of external files */
|
||
char name[256]; /* external file name */
|
||
off_t file_offset; /* external file offset */
|
||
hsize_t file_size; /* sizeof external file segment */
|
||
|
||
TESTING("unlimited dataspace, unlimited external storage");
|
||
|
||
/* Create dataset */
|
||
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pset_external(dcpl, "ext1.data", (off_t)0, H5F_UNLIMITED) < 0)
|
||
FAIL_STACK_ERROR
|
||
cur_size[0] = 100;
|
||
max_size[0] = H5S_UNLIMITED;
|
||
if((space = H5Screate_simple(1, cur_size, max_size)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((dset = H5Dcreate2(file, "dset5", H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
if(H5Sclose(space) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
|
||
/* Read dataset creation information */
|
||
if((dset = H5Dopen2(file, "dset5", H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((dcpl = H5Dget_create_plist(dset)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((n = H5Pget_external_count(dcpl)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(1 != n) {
|
||
H5_FAILED();
|
||
HDputs(" Returned external count is wrong.");
|
||
printf(" got: %d\n ans: 1\n", n);
|
||
goto error;
|
||
} /* end if */
|
||
|
||
HDstrcpy(name + sizeof(name) - 4, "...");
|
||
if(H5Pget_external(dcpl, 0, sizeof(name) - 4, name, &file_offset, &file_size) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(file_offset != 0) {
|
||
H5_FAILED();
|
||
HDputs(" Wrong file offset.");
|
||
printf(" got: %lu\n ans: 0\n", (unsigned long)file_offset);
|
||
goto error;
|
||
} /* end if */
|
||
|
||
if(H5F_UNLIMITED != file_size) {
|
||
H5_FAILED();
|
||
HDputs(" Wrong file size.");
|
||
printf(" got: %lu\n ans: INF\n", (unsigned long)file_size);
|
||
goto error;
|
||
} /* end if */
|
||
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Dclose(dset);
|
||
H5Pclose(dcpl);
|
||
H5Sclose(space);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_unlimited() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_multiple_files
|
||
*
|
||
* Purpose: Test multiple external files for a dataset.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Monday, November 23, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_multiple_files(hid_t file)
|
||
{
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t space = -1; /* dataspace */
|
||
hid_t dset = -1; /* dataset */
|
||
hsize_t cur_size[1]; /* data space current size */
|
||
hsize_t max_size[1]; /* data space maximum size */
|
||
|
||
TESTING("multiple external files");
|
||
|
||
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
cur_size[0] = max_size[0] = 100;
|
||
|
||
if(H5Pset_external(dcpl, "ext1.data", (off_t)0, (hsize_t)(max_size[0]*sizeof(int)/4)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pset_external(dcpl, "ext2.data", (off_t)0, (hsize_t)(max_size[0]*sizeof(int)/4)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pset_external(dcpl, "ext3.data", (off_t)0, (hsize_t)(max_size[0]*sizeof(int)/4)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pset_external(dcpl, "ext4.data", (off_t)0, (hsize_t)(max_size[0]*sizeof(int)/4)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((space = H5Screate_simple(1, cur_size, max_size)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((dset = H5Dcreate2(file, "dset6", H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
if(H5Sclose(space) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Dclose(dset);
|
||
H5Pclose(dcpl);
|
||
H5Sclose(space);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_multiple_files() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_add_to_unlimited
|
||
*
|
||
* Purpose: It should be impossible to define an unlimited external file
|
||
* and then follow it with another external file.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Monday, November 23, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_add_to_unlimited(void)
|
||
{
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
herr_t status; /* function return status */
|
||
int n; /* number of external files */
|
||
|
||
TESTING("external file following unlimited file");
|
||
|
||
if((dcpl = H5Pcreate (H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pset_external(dcpl, "ext1.data", (off_t)0, H5F_UNLIMITED) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
H5E_BEGIN_TRY {
|
||
status = H5Pset_external(dcpl, "ext2.data", (off_t)0, (hsize_t)100);
|
||
} H5E_END_TRY;
|
||
if(status >= 0)
|
||
FAIL_PUTS_ERROR(" H5Pset_external() succeeded when it should have failed.");
|
||
|
||
if((n = H5Pget_external_count(dcpl)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(1 != n)
|
||
FAIL_PUTS_ERROR(" Wrong external file count returned.");
|
||
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Pclose(dcpl);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_add_to_unlimited() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_overflow
|
||
*
|
||
* Purpose: It should be impossible to create a set of external files
|
||
* whose total size overflows a size_t integer.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Monday, November 23, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_overflow(void)
|
||
{
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
herr_t status; /* return status */
|
||
|
||
TESTING("address overflow in external files");
|
||
|
||
if((dcpl=H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pset_external(dcpl, "ext1.data", (off_t)0, H5F_UNLIMITED-1) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
H5E_BEGIN_TRY {
|
||
status = H5Pset_external(dcpl, "ext2.data", (off_t)0, (hsize_t)100);
|
||
} H5E_END_TRY;
|
||
if(status >= 0)
|
||
FAIL_PUTS_ERROR(" H5Pset_external() succeeded when it should have failed.");
|
||
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Pclose(dcpl);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_overflow() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_read_file_set
|
||
*
|
||
* Purpose: Tests reading from an external file set.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Wednesday, March 4, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_read_file_set(hid_t fapl)
|
||
{
|
||
hid_t file = -1; /* file to write to */
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t space = -1; /* data space */
|
||
hid_t dset = -1; /* dataset */
|
||
hid_t grp = -1; /* group to emit diagnostics */
|
||
size_t i; /* miscellaneous counter */
|
||
char filename[1024]; /* file names */
|
||
int part[PART_SIZE]; /* raw data buffer (partial) */
|
||
int whole[TOTAL_SIZE]; /* raw data buffer (total) */
|
||
hsize_t cur_size; /* current data space size */
|
||
hid_t hs_space = -1; /* hyperslab data space */
|
||
hsize_t hs_start = 30; /* hyperslab starting offset */
|
||
hsize_t hs_count = 25; /* hyperslab size */
|
||
|
||
TESTING("read external dataset");
|
||
|
||
if(HDsetenv("HDF5_EXTFILE_PREFIX", "", 1) < 0)
|
||
TEST_ERROR
|
||
|
||
/* Reset the raw data files */
|
||
if(reset_raw_data_files() < 0)
|
||
TEST_ERROR
|
||
|
||
/* Create the file and an initial group. This causes messages about
|
||
* debugging to be emitted before we start playing games with what the
|
||
* output looks like.
|
||
*/
|
||
h5_fixname(FILENAME[1], fapl, filename, sizeof(filename));
|
||
if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((grp = H5Gcreate2(file, "emit-diagnostics", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Gclose(grp) < 0) FAIL_STACK_ERROR
|
||
|
||
/* Create the dcpl */
|
||
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
for(i = 0; i < N_EXT_FILES; i++) {
|
||
HDsnprintf(filename, sizeof(filename), "extern_%dr.raw", (int) i + 1);
|
||
if(H5Pset_external(dcpl, filename, (off_t)(i * GARBAGE_PER_FILE), (hsize_t)sizeof(part)) < 0)
|
||
FAIL_STACK_ERROR
|
||
} /* end for */
|
||
|
||
/* Create the dataspace */
|
||
cur_size = TOTAL_SIZE;
|
||
if((space = H5Screate_simple(1, &cur_size, NULL)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Create the dataset */
|
||
if((dset = H5Dcreate2(file, "dset1", H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Read the entire dataset */
|
||
HDmemset(whole, 0, sizeof(whole));
|
||
if(H5Dread(dset, H5T_NATIVE_INT, space, space, H5P_DEFAULT, whole) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Compare data */
|
||
for(i = 0; i < TOTAL_SIZE; i++)
|
||
if(whole[i] != (signed)i)
|
||
FAIL_PUTS_ERROR("Incorrect value(s) read.");
|
||
|
||
/* Read via a hypserslab in the middle of the dataset */
|
||
|
||
/* Set up dataspace */
|
||
if((hs_space = H5Scopy(space)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Sselect_hyperslab(hs_space, H5S_SELECT_SET, &hs_start, NULL, &hs_count, NULL) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Read */
|
||
HDmemset(whole, 0, sizeof(whole));
|
||
if(H5Dread(dset, H5T_NATIVE_INT, hs_space, hs_space, H5P_DEFAULT, whole) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Verify data */
|
||
for(i = (size_t)hs_start; i < (size_t)(hs_start + hs_count); i++) {
|
||
if(whole[i] != (signed)i)
|
||
FAIL_PUTS_ERROR("Incorrect value(s) read (hyperslab).");
|
||
} /* end for */
|
||
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
if(H5Sclose(space) < 0) FAIL_STACK_ERROR
|
||
if(H5Sclose(hs_space) < 0) FAIL_STACK_ERROR
|
||
if(H5Fclose(file) < 0) FAIL_STACK_ERROR
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Gclose(grp);
|
||
H5Dclose(dset);
|
||
H5Pclose(dcpl);
|
||
H5Sclose(space);
|
||
H5Sclose(hs_space);
|
||
H5Fclose(file);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_read_file_set() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_write_file_set
|
||
*
|
||
* Purpose: Tests writing to an external file set.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Wednesday, March 4, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_write_file_set(hid_t fapl)
|
||
{
|
||
hid_t file = -1; /* file to which to write */
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t mem_space = -1; /* memory data space */
|
||
hid_t file_space = -1; /* file data space */
|
||
hid_t dset = -1; /* dataset */
|
||
unsigned i; /* miscellaneous counter */
|
||
int part[PART_SIZE]; /* raw data buffer (partial) */
|
||
int whole[TOTAL_SIZE]; /* raw data buffer (total) */
|
||
hsize_t cur_size = 100; /* current data space size */
|
||
hsize_t max_size = 200; /* maximum data space size */
|
||
hsize_t hs_start = 100; /* hyperslab starting offset */
|
||
hsize_t hs_count = 100; /* hyperslab size */
|
||
char filename[1024]; /* file name */
|
||
|
||
TESTING("write external dataset");
|
||
|
||
if(HDsetenv("HDF5_EXTFILE_PREFIX", "", 1) < 0)
|
||
TEST_ERROR
|
||
|
||
/* Create another file */
|
||
h5_fixname(FILENAME[2], fapl, filename, sizeof(filename));
|
||
if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Create the dcpl and external file list */
|
||
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
for(i = 0; i < N_EXT_FILES; i++) {
|
||
hsize_t size;
|
||
|
||
HDsnprintf(filename, sizeof(filename), "extern_%dw.raw", (int) i + 1);
|
||
|
||
if(i != N_EXT_FILES -1)
|
||
size = (hsize_t)sizeof(part);
|
||
else
|
||
size = H5F_UNLIMITED;
|
||
|
||
if(H5Pset_external(dcpl, filename, (off_t)(i * GARBAGE_PER_FILE), size) < 0)
|
||
FAIL_STACK_ERROR
|
||
} /* end for */
|
||
|
||
/* Reset the raw data files */
|
||
if(reset_raw_data_files() < 0)
|
||
TEST_ERROR
|
||
|
||
/* Create the dataset */
|
||
if((mem_space = H5Screate_simple(1, &cur_size, &max_size)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((file_space = H5Scopy(mem_space)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((dset = H5Dcreate2(file, "dset1", H5T_NATIVE_INT, file_space, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Write the entire dataset and compare with the original */
|
||
for(i = 0; i < cur_size; i++)
|
||
whole[i] = (int)i;
|
||
if(H5Dwrite(dset, H5T_NATIVE_INT, mem_space, file_space, H5P_DEFAULT, whole) < 0)
|
||
FAIL_STACK_ERROR
|
||
for(i = 0; i < N_EXT_FILES; i++) {
|
||
char name1[64], name2[64];
|
||
|
||
HDsprintf(name1, "extern_%dr.raw", i + 1);
|
||
HDsprintf(name2, "extern_%dw.raw", i + 1);
|
||
if(!files_have_same_contents(name1, name2))
|
||
FAIL_PUTS_ERROR(" Output differs from expected value.")
|
||
} /* end for */
|
||
|
||
/* Extend the dataset by another 100 elements */
|
||
if(H5Dset_extent(dset, &max_size) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Sclose(file_space) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((file_space = H5Dget_space(dset)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Write second half of dataset */
|
||
for(i = 0; i < hs_count; i++)
|
||
whole[i] = 100 + (int)i;
|
||
if(H5Sselect_hyperslab(file_space, H5S_SELECT_SET, &hs_start, NULL, &hs_count, NULL) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Dwrite(dset, H5T_NATIVE_INT, mem_space, file_space, H5P_DEFAULT, whole) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
if(H5Sclose(mem_space) < 0) FAIL_STACK_ERROR
|
||
if(H5Sclose(file_space) < 0) FAIL_STACK_ERROR
|
||
if(H5Fclose(file) < 0) FAIL_STACK_ERROR
|
||
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Dclose(dset);
|
||
H5Pclose(dcpl);
|
||
H5Sclose(mem_space);
|
||
H5Sclose(file_space);
|
||
H5Fclose(file);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_write_file_set() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_path_absolute
|
||
*
|
||
* Purpose: Test absolute filenames for external files.
|
||
* This will create an HDF5 file in a subdirectory which will
|
||
* refer to /full/path/extern_*a.raw on unix and to
|
||
* c:\full\path\extern_*a.raw and \full\path\extern_*a.raw on
|
||
* windows.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Steffen Kiess
|
||
* March 10, 2015
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_path_absolute(hid_t fapl)
|
||
{
|
||
hid_t file = -1; /* file to write to */
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t space = -1; /* data space */
|
||
hid_t dset = -1; /* dataset */
|
||
size_t i; /* miscellaneous counter */
|
||
char cwdpath[1024]; /* working directory */
|
||
char filename[1024]; /* file name */
|
||
int part[PART_SIZE]; /* raw data buffer (partial) */
|
||
int whole[TOTAL_SIZE]; /* raw data buffer (total) */
|
||
hsize_t cur_size; /* current data space size */
|
||
|
||
TESTING("absolute filenames for external file");
|
||
|
||
h5_fixname(FILENAME[3], fapl, filename, sizeof(filename));
|
||
if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Reset the raw data files */
|
||
if(reset_raw_data_files() < 0)
|
||
TEST_ERROR
|
||
|
||
/* Create the dcpl */
|
||
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(NULL == HDgetcwd(cwdpath, sizeof(cwdpath)))
|
||
TEST_ERROR
|
||
for(i = 0; i < N_EXT_FILES; i++) {
|
||
HDsnprintf(filename, sizeof(filename), "%s%sextern_%dr.raw", cwdpath, H5_DIR_SEPS, (int) i + 1);
|
||
#if defined(H5_HAVE_WINDOW_PATH)
|
||
/* For windows, test path-absolute case (\dir\file.raw) for the second file */
|
||
if(i == 1)
|
||
HDsnprintf(filename, sizeof(filename), "%s%sextern_%dr.raw", cwdpath + 2, H5_DIR_SEPS, i + 1);
|
||
#endif
|
||
if(H5Pset_external(dcpl, filename, (off_t)(i * GARBAGE_PER_FILE), (hsize_t)sizeof(part)) < 0)
|
||
FAIL_STACK_ERROR
|
||
} /* end for */
|
||
|
||
/* create the dataspace */
|
||
cur_size = TOTAL_SIZE;
|
||
if((space = H5Screate_simple(1, &cur_size, NULL)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* create the dataset */
|
||
if((dset = H5Dcreate2(file, "dset1", H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Read the entire dataset and compare with the original */
|
||
HDmemset(whole, 0, sizeof(whole));
|
||
if(H5Dread(dset, H5T_NATIVE_INT, space, space, H5P_DEFAULT, whole) < 0)
|
||
FAIL_STACK_ERROR
|
||
for(i = 0; i < TOTAL_SIZE; i++)
|
||
if(whole[i] != (signed)i)
|
||
FAIL_PUTS_ERROR("Incorrect value(s) read.");
|
||
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
if(H5Sclose(space) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
if(H5Fclose(file) < 0) FAIL_STACK_ERROR
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Dclose(dset);
|
||
H5Sclose(space);
|
||
H5Pclose(dcpl);
|
||
H5Fclose(file);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_path_absolute() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_path_relative
|
||
*
|
||
* Purpose: Test external files with filename relative to current directory.
|
||
* This will create an HDF5 file in a subdirectory which will
|
||
* refer to extern_*a.raw
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Steffen Kiess
|
||
* March 10, 2015
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_path_relative(hid_t fapl)
|
||
{
|
||
hid_t file = -1; /* file to write to */
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t space = -1; /* data space */
|
||
hid_t dset = -1; /* dataset */
|
||
size_t i; /* miscellaneous counters */
|
||
char cwdpath[1024]; /* working directory */
|
||
char filename[1024]; /* file name */
|
||
int part[PART_SIZE]; /* raw data buffer (partial) */
|
||
int whole[TOTAL_SIZE]; /* raw data buffer (total) */
|
||
hsize_t cur_size; /* current data space size */
|
||
|
||
TESTING("filenames relative to current directory for external file");
|
||
|
||
if(HDsetenv("HDF5_EXTFILE_PREFIX", "", 1) < 0)
|
||
TEST_ERROR
|
||
|
||
if (HDmkdir("extern_dir", (mode_t)0755) < 0 && errno != EEXIST)
|
||
TEST_ERROR;
|
||
|
||
h5_fixname(FILENAME[4], fapl, filename, sizeof(filename));
|
||
if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
|
||
FAIL_STACK_ERROR;
|
||
|
||
/* Reset the raw data files */
|
||
if(reset_raw_data_files() < 0)
|
||
TEST_ERROR
|
||
|
||
/* Create the dataset */
|
||
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(NULL == HDgetcwd(cwdpath, sizeof(cwdpath)))
|
||
TEST_ERROR
|
||
for (i = 0; i < N_EXT_FILES; i++) {
|
||
HDsnprintf(filename, sizeof(filename), "extern_%dr.raw", (int)i + 1);
|
||
if(H5Pset_external(dcpl, filename, (off_t)(i * GARBAGE_PER_FILE), (hsize_t)sizeof(part)) < 0)
|
||
FAIL_STACK_ERROR
|
||
} /* end for */
|
||
|
||
cur_size = TOTAL_SIZE;
|
||
if((space = H5Screate_simple(1, &cur_size, NULL)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((dset = H5Dcreate2(file, "dset1", H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Read the entire dataset and compare with the original */
|
||
HDmemset(whole, 0, sizeof(whole));
|
||
if(H5Dread(dset, H5T_NATIVE_INT, space, space, H5P_DEFAULT, whole) < 0)
|
||
FAIL_STACK_ERROR
|
||
for(i = 0; i < TOTAL_SIZE; i++)
|
||
if(whole[i] != (signed)i)
|
||
FAIL_PUTS_ERROR("Incorrect value(s) read.");
|
||
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
if(H5Sclose(space) < 0) FAIL_STACK_ERROR
|
||
if(H5Fclose(file) < 0) FAIL_STACK_ERROR
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Dclose(dset);
|
||
H5Pclose(dcpl);
|
||
H5Sclose(space);
|
||
H5Fclose(file);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_path_relative() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_path_relative_cwd
|
||
*
|
||
* Purpose: Test external files with filename relative to current directory.
|
||
* This will create an HDF5 file in a subdirectory which will
|
||
* refer to ../extern_*a.raw
|
||
* The files are then accessed by setting the efile_prefix dataset
|
||
* access property to "${ORIGIN}".
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Steffen Kiess
|
||
* March 10, 2015
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_path_relative_cwd(hid_t fapl)
|
||
{
|
||
hid_t file = -1; /* file to write to */
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t space = -1; /* data space */
|
||
hid_t dapl = -1; /* dataset access property list */
|
||
hid_t dapl2 = -1; /* copy of dapl */
|
||
hid_t dset = -1; /* dataset */
|
||
hid_t dset2 = -1; /* dataset, opened a second time */
|
||
hid_t dset3 = -1; /* dataset, opened with different prefix */
|
||
size_t i; /* miscellaneous counters */
|
||
char cwdpath[1024]; /* working directory */
|
||
char filename[1024]; /* file name */
|
||
int part[PART_SIZE]; /* raw data buffer (partial) */
|
||
int whole[TOTAL_SIZE]; /* raw data buffer (total) */
|
||
hsize_t cur_size; /* current data space size */
|
||
char buffer[1024]; /* buffer to read efile_prefix */
|
||
|
||
TESTING("filenames relative to HDF5 file for external file");
|
||
|
||
if(HDsetenv("HDF5_EXTFILE_PREFIX", "", 1) < 0)
|
||
TEST_ERROR
|
||
|
||
if(HDmkdir("extern_dir", (mode_t)0755) < 0 && errno != EEXIST)
|
||
TEST_ERROR;
|
||
|
||
h5_fixname(FILENAME[4], fapl, filename, sizeof(filename));
|
||
if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
|
||
FAIL_STACK_ERROR;
|
||
|
||
/* Reset the raw data files */
|
||
if(reset_raw_data_files() < 0)
|
||
TEST_ERROR
|
||
|
||
/* Create the dataset */
|
||
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(NULL == HDgetcwd(cwdpath, sizeof(cwdpath)))
|
||
TEST_ERROR
|
||
for(i = 0; i < N_EXT_FILES; i++) {
|
||
HDsnprintf(filename, sizeof(filename), "..%sextern_%dr.raw", H5_DIR_SEPS, (int)i + 1);
|
||
if(H5Pset_external(dcpl, filename, (off_t)(i * GARBAGE_PER_FILE), (hsize_t)sizeof(part)) < 0)
|
||
FAIL_STACK_ERROR
|
||
} /* end for */
|
||
|
||
cur_size = TOTAL_SIZE;
|
||
if((space = H5Screate_simple(1, &cur_size, NULL)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pset_efile_prefix(dapl, "${ORIGIN}") < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pget_efile_prefix(dapl, buffer, sizeof(buffer)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(HDstrcmp(buffer, "${ORIGIN}") != 0)
|
||
FAIL_PUTS_ERROR("efile prefix not set correctly");
|
||
if((dapl2 = H5Pcopy(dapl)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Create dataset */
|
||
if((dset = H5Dcreate2(file, "dset1", H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, dapl2)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Reopen dataset with same efile_prefix property */
|
||
if((dset2 = H5Dopen2(file, "dset1", dapl2)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Reopen dataset with different efile_prefix property */
|
||
if(H5Pset_efile_prefix(dapl, "//") < 0)
|
||
FAIL_STACK_ERROR
|
||
H5E_BEGIN_TRY {
|
||
dset3 = H5Dopen2(file, "dset1", dapl);
|
||
} H5E_END_TRY;
|
||
if(dset3 >= 0)
|
||
FAIL_PUTS_ERROR("reopening the dataset with a different efile_prefix succeded");
|
||
|
||
/* Read the entire dataset and compare with the original */
|
||
HDmemset(whole, 0, sizeof(whole));
|
||
if(H5Dread(dset, H5T_NATIVE_INT, space, space, H5P_DEFAULT, whole) < 0)
|
||
FAIL_STACK_ERROR
|
||
for(i = 0; i < TOTAL_SIZE; i++)
|
||
if(whole[i] != (signed)i)
|
||
FAIL_PUTS_ERROR("Incorrect value(s) read.");
|
||
|
||
/* Close dataset */
|
||
if(H5Dclose(dset2) < 0) FAIL_STACK_ERROR
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
|
||
/* Open dataset (use a differend prefix than for create.
|
||
* This works because the dataset was closed.
|
||
*/
|
||
if(H5Pset_efile_prefix(dapl2, "${ORIGIN}/.") < 0)
|
||
FAIL_STACK_ERROR
|
||
if((dset = H5Dopen2(file, "dset1", dapl2)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Reopen dataset with same efile_prefix property */
|
||
if((dset2 = H5Dopen2(file, "dset1", dapl2)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Reopen dataset with different efile_prefix property */
|
||
if(H5Pset_efile_prefix(dapl, NULL) < 0)
|
||
FAIL_STACK_ERROR
|
||
H5E_BEGIN_TRY {
|
||
dset3 = H5Dopen2(file, "dset1", dapl);
|
||
} H5E_END_TRY;
|
||
if(dset3 >= 0)
|
||
FAIL_PUTS_ERROR("reopening the dataset with a different efile_prefix succeded");
|
||
|
||
/* Read the entire dataset and compare with the original */
|
||
HDmemset(whole, 0, sizeof(whole));
|
||
if(H5Dread(dset, H5T_NATIVE_INT, space, space, H5P_DEFAULT, whole) < 0)
|
||
FAIL_STACK_ERROR
|
||
for(i = 0; i < TOTAL_SIZE; i++)
|
||
if(whole[i] != (signed)i)
|
||
FAIL_PUTS_ERROR("Incorrect value(s) read.");
|
||
|
||
if(H5Dclose(dset2) < 0) FAIL_STACK_ERROR
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dapl2) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dapl) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
if(H5Sclose(space) < 0) FAIL_STACK_ERROR
|
||
if(H5Fclose(file) < 0) FAIL_STACK_ERROR
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Pclose(dapl2);
|
||
H5Pclose(dapl);
|
||
H5Dclose(dset3);
|
||
H5Dclose(dset2);
|
||
H5Dclose(dset);
|
||
H5Pclose(dcpl);
|
||
H5Sclose(space);
|
||
H5Fclose(file);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_path_relative_cwd() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_path_env
|
||
*
|
||
* Purpose: Test whether the value of HDF5_EXTFILE_PREFIX will overwrite
|
||
* the efile_prefix dataset access property.
|
||
* This will create an HDF5 file in a subdirectory which will
|
||
* refer to ../extern_*a.raw
|
||
* The files are then accessed by setting the HDF5_EXTFILE_PREFIX
|
||
* environment variable to "${ORIGIN}".
|
||
* The efile_prefix dataset access property is set to "someprefix",
|
||
* which will cause an error if the value is not overwritten by
|
||
* the environment variable.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Steffen Kiess
|
||
* March 10, 2015
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_path_env(hid_t fapl)
|
||
{
|
||
hid_t file = -1; /* file to write to */
|
||
hid_t dcpl = -1; /* dataset creation properties */
|
||
hid_t space = -1; /* data space */
|
||
hid_t dapl = -1; /* dataset access property list */
|
||
hid_t dset = -1; /* dataset */
|
||
size_t i; /* miscellaneous counters */
|
||
char cwdpath[1024]; /* working directory */
|
||
char filename[1024]; /* file name */
|
||
int part[PART_SIZE]; /* raw data buffer (partial) */
|
||
int whole[TOTAL_SIZE]; /* raw data buffer (total) */
|
||
hsize_t cur_size; /* current data space size */
|
||
char buffer[1024]; /* buffer to read efile_prefix */
|
||
|
||
TESTING("prefix in HDF5_EXTFILE_PREFIX");
|
||
|
||
if(HDsetenv("HDF5_EXTFILE_PREFIX", "${ORIGIN}", 1))
|
||
TEST_ERROR
|
||
|
||
if(HDmkdir("extern_dir", (mode_t)0755) < 0 && errno != EEXIST)
|
||
TEST_ERROR;
|
||
|
||
h5_fixname(FILENAME[4], fapl, filename, sizeof(filename));
|
||
if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Reset the raw data files */
|
||
if(reset_raw_data_files() < 0)
|
||
TEST_ERROR
|
||
|
||
/* Create the dataset */
|
||
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(NULL == HDgetcwd(cwdpath, sizeof(cwdpath)))
|
||
TEST_ERROR
|
||
for(i = 0; i < N_EXT_FILES; i++) {
|
||
HDsnprintf(filename, sizeof(filename), "..%sextern_%dr.raw", H5_DIR_SEPS, (int) i + 1);
|
||
if(H5Pset_external(dcpl, filename, (off_t)(i * GARBAGE_PER_FILE), (hsize_t)sizeof(part)) < 0)
|
||
FAIL_STACK_ERROR
|
||
} /* end for */
|
||
|
||
cur_size = TOTAL_SIZE;
|
||
if((space = H5Screate_simple(1, &cur_size, NULL)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Set prefix to a nonexistent directory, will be overwritten by environment variable */
|
||
if(H5Pset_efile_prefix(dapl, "someprefix") < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pget_efile_prefix(dapl, buffer, sizeof(buffer)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(HDstrcmp(buffer, "someprefix") != 0)
|
||
FAIL_PUTS_ERROR("efile prefix not set correctly");
|
||
|
||
/* Create dataset */
|
||
if((dset = H5Dcreate2(file, "dset1", H5T_NATIVE_INT, space, H5P_DEFAULT, dcpl, dapl)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Read the entire dataset and compare with the original */
|
||
HDmemset(whole, 0, sizeof(whole));
|
||
if(H5Dread(dset, H5T_NATIVE_INT, space, space, H5P_DEFAULT, whole) < 0)
|
||
FAIL_STACK_ERROR
|
||
for(i = 0; i < TOTAL_SIZE; i++)
|
||
if(whole[i] != (signed)i)
|
||
FAIL_PUTS_ERROR("Incorrect value(s) read.");
|
||
|
||
if(H5Dclose(dset) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dapl) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl) < 0) FAIL_STACK_ERROR
|
||
if(H5Sclose(space) < 0) FAIL_STACK_ERROR
|
||
if(H5Fclose(file) < 0) FAIL_STACK_ERROR
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Pclose(dapl);
|
||
H5Dclose(dset);
|
||
H5Pclose(dcpl);
|
||
H5Sclose(space);
|
||
H5Fclose(file);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_path_env() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: test_h5d_get_access_plist
|
||
*
|
||
* Purpose: Ensure that H5Dget_access_plist returns correct values.
|
||
*
|
||
* Return: Success: 0
|
||
* Failure: 1
|
||
*
|
||
* Programmer: Dana Robinson
|
||
* March 2016
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
test_h5d_get_access_plist(hid_t fapl_id)
|
||
{
|
||
hid_t fid = -1; /* file to write to */
|
||
hid_t dcpl_id = -1; /* dataset creation properties */
|
||
hid_t dapl_id = -1; /* dataset access properties */
|
||
hid_t sid = -1; /* data space */
|
||
hid_t did = -1; /* dataset */
|
||
hsize_t dims = 0; /* dataset size */
|
||
char *buffer = NULL; /* saved prefix name from dapl */
|
||
char filename[1024]; /* file names */
|
||
|
||
TESTING("H5Dget_access_plist() returns correct prefix");
|
||
|
||
if(HDsetenv("HDF5_EXTFILE_PREFIX", "", 1) < 0)
|
||
TEST_ERROR
|
||
|
||
/* Reset the raw data files */
|
||
if(reset_raw_data_files() < 0)
|
||
TEST_ERROR
|
||
|
||
/* Create the file */
|
||
h5_fixname(FILENAME[5], fapl_id, filename, sizeof(filename));
|
||
if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Create the dcpl and set external storage */
|
||
if((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pset_external(dcpl_id, "extern_1r.raw", (off_t)0, (hsize_t)0) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Create the dapl and set the prefix */
|
||
if((dapl_id = H5Pcreate(H5P_DATASET_ACCESS)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pset_efile_prefix(dapl_id, "someprefix") < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Create the dataset */
|
||
if((sid = H5Screate_simple(1, &dims, NULL)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if((did = H5Dcreate2(fid, "dset1", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl_id, dapl_id)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Close the dapl */
|
||
if(H5Pclose(dapl_id) < 0)
|
||
FAIL_STACK_ERROR
|
||
dapl_id = -1;
|
||
|
||
/* Get a data access property list from the dataset */
|
||
if((dapl_id = H5Dget_access_plist(did)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Check the value for the external prefix */
|
||
if((buffer = (char *)HDcalloc((size_t)64, sizeof(char))) == NULL)
|
||
TEST_ERROR
|
||
if(H5Pget_efile_prefix(dapl_id, buffer, (size_t)64) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(HDstrcmp(buffer, "someprefix") != 0)
|
||
FAIL_PUTS_ERROR("external file prefix from dapl incorrect");
|
||
|
||
/* Close everything */
|
||
HDfree(buffer);
|
||
if(H5Sclose(sid) < 0) FAIL_STACK_ERROR
|
||
if(H5Dclose(did) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dcpl_id) < 0) FAIL_STACK_ERROR
|
||
if(H5Pclose(dapl_id) < 0) FAIL_STACK_ERROR
|
||
if(H5Fclose(fid) < 0) FAIL_STACK_ERROR
|
||
|
||
PASSED();
|
||
return 0;
|
||
|
||
error:
|
||
if(buffer)
|
||
HDfree(buffer);
|
||
H5E_BEGIN_TRY {
|
||
H5Dclose(did);
|
||
H5Pclose(dcpl_id);
|
||
H5Pclose(dapl_id);
|
||
H5Sclose(sid);
|
||
H5Fclose(fid);
|
||
} H5E_END_TRY;
|
||
return 1;
|
||
} /* end test_h5d_get_access_plist() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: main
|
||
*
|
||
* Purpose: Runs external dataset tests.
|
||
*
|
||
* Return: EXIT_SUCCESS/EXIT_FAILURE
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Tuesday, March 3, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
main(void)
|
||
{
|
||
hid_t fapl_id_old = -1; /* file access properties (old format) */
|
||
hid_t fapl_id_new = -1; /* file access properties (new format) */
|
||
hid_t fid = -1; /* file for test_1* functions */
|
||
hid_t gid = -1; /* group to emit diagnostics */
|
||
char filename[1024]; /* file name for test_1* funcs */
|
||
unsigned latest_format; /* default or latest file format */
|
||
int nerrors = 0; /* number of errors */
|
||
|
||
h5_reset();
|
||
|
||
/* Get a fapl for the old (default) file format */
|
||
fapl_id_old = h5_fileaccess();
|
||
h5_fixname(FILENAME[0], fapl_id_old, filename, sizeof(filename));
|
||
|
||
/* Copy and set up a fapl for the latest file format */
|
||
if((fapl_id_new = H5Pcopy(fapl_id_old)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Pset_libver_bounds(fapl_id_new, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* The file format doesn't matter for this test */
|
||
nerrors += test_h5d_get_access_plist(fapl_id_new);
|
||
HDputs("");
|
||
|
||
/* Test with old & new format groups */
|
||
for(latest_format = FALSE; latest_format <= TRUE; latest_format++) {
|
||
hid_t current_fapl_id = -1;
|
||
|
||
/* Set the fapl for different file formats */
|
||
if(latest_format) {
|
||
HDputs("\nTesting with the latest file format:");
|
||
current_fapl_id = fapl_id_new;
|
||
} /* end if */
|
||
else {
|
||
HDputs("Testing with the default file format:");
|
||
current_fapl_id = fapl_id_old;
|
||
} /* end else */
|
||
|
||
/* Create the common file used by some of the tests */
|
||
if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, current_fapl_id)) < 0)
|
||
FAIL_STACK_ERROR
|
||
|
||
/* Create a group that will be used in the file set read test */
|
||
if((gid = H5Gcreate2(fid, "emit-diagnostics", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
|
||
FAIL_STACK_ERROR
|
||
if(H5Gclose(gid) < 0) FAIL_STACK_ERROR
|
||
|
||
/* These tests use a common file */
|
||
nerrors += test_non_extendible(fid);
|
||
nerrors += test_too_small(fid);
|
||
nerrors += test_large_enough_current_eventual(fid);
|
||
nerrors += test_large_enough_current_not_eventual(fid);
|
||
nerrors += test_unlimited(fid);
|
||
nerrors += test_multiple_files(fid);
|
||
|
||
/* These tests use no file */
|
||
nerrors += test_add_to_unlimited();
|
||
nerrors += test_overflow();
|
||
|
||
/* These file set tests use the VFD-aware fapl */
|
||
nerrors += test_read_file_set(current_fapl_id);
|
||
nerrors += test_write_file_set(current_fapl_id);
|
||
nerrors += test_path_absolute(current_fapl_id);
|
||
nerrors += test_path_relative(current_fapl_id);
|
||
nerrors += test_path_relative_cwd(current_fapl_id);
|
||
nerrors += test_path_env(current_fapl_id);
|
||
|
||
/* Verify symbol table messages are cached */
|
||
nerrors += (h5_verify_cached_stabs(FILENAME, current_fapl_id) < 0 ? 1 : 0);
|
||
|
||
/* Close the common file */
|
||
if(H5Fclose(fid) < 0) FAIL_STACK_ERROR
|
||
|
||
} /* end for */
|
||
|
||
if(nerrors > 0) goto error;
|
||
|
||
/* Close the new ff fapl. h5_cleanup will take care of the old ff fapl */
|
||
if(H5Pclose(fapl_id_new) < 0) FAIL_STACK_ERROR
|
||
|
||
HDputs("All external storage tests passed.");
|
||
|
||
/* Clean up files used by file set tests */
|
||
if(h5_cleanup(FILENAME, fapl_id_old)) {
|
||
HDremove("extern_1r.raw");
|
||
HDremove("extern_2r.raw");
|
||
HDremove("extern_3r.raw");
|
||
HDremove("extern_4r.raw");
|
||
|
||
HDremove("extern_1w.raw");
|
||
HDremove("extern_2w.raw");
|
||
HDremove("extern_3w.raw");
|
||
HDremove("extern_4w.raw");
|
||
|
||
HDrmdir("extern_dir");
|
||
} /* end if */
|
||
|
||
return EXIT_SUCCESS;
|
||
|
||
error:
|
||
H5E_BEGIN_TRY {
|
||
H5Fclose(fid);
|
||
H5Pclose(fapl_id_old);
|
||
H5Pclose(fapl_id_new);
|
||
H5Gclose(gid);
|
||
} H5E_END_TRY;
|
||
nerrors = MAX(1, nerrors);
|
||
printf("%d TEST%s FAILED.\n", nerrors, 1 == nerrors ? "" : "s");
|
||
return EXIT_FAILURE;
|
||
} /* end main() */
|
||
|