Files
hdf5/test/plugin.c
Dana Robinson d4234d0a98 Major rework of H5PL package code before bringing VOL changes
over.

Brings coding standards in line with the rest of the library,
enforces better software engineering principles, and makes
everything more maintainable.
2017-07-14 09:18:33 -07:00

1195 lines
36 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Purpose: Tests the plugin module (H5PL)
*/
#include "h5test.h"
#include "H5srcdir.h"
/*
* This file needs to access private datatypes from the H5Z and H5PL package.
*/
#define H5PL_FRIEND
#include "H5PLpkg.h"
#define H5Z_FRIEND
#include "H5Zpkg.h"
/* Filters for HDF5 internal test */
#define H5Z_FILTER_DYNLIB1 257
#define H5Z_FILTER_DYNLIB2 258
#define H5Z_FILTER_DYNLIB3 259
#define H5Z_FILTER_DYNLIB4 260
const char *FILENAME[] = {
"plugin",
NULL
};
#define FILENAME_BUF_SIZE 1024
/* Dataset names for testing filters */
#define DSET_DEFLATE_NAME "deflate"
#define DSET_DYNLIB1_NAME "dynlib1"
#define DSET_DYNLIB2_NAME "dynlib2"
#define DSET_DYNLIB4_NAME "dynlib4"
/* Parameters for internal filter test */
#define FILTER_CHUNK_DIM1 2
#define FILTER_CHUNK_DIM2 25
#define FILTER_HS_OFFSET1 7
#define FILTER_HS_OFFSET2 30
#define FILTER_HS_SIZE1 4
#define FILTER_HS_SIZE2 50
/* Shared global arrays */
#define DSET_DIM1 100
#define DSET_DIM2 200
/* Limit random number within 20000 */
#define RANDOM_LIMIT 20000
#define GROUP_ITERATION 1000
int points_deflate[DSET_DIM1][DSET_DIM2],
points_dynlib1[DSET_DIM1][DSET_DIM2],
points_dynlib2[DSET_DIM1][DSET_DIM2],
points_dynlib4[DSET_DIM1][DSET_DIM2],
points_bzip2[DSET_DIM1][DSET_DIM2];
/*-------------------------------------------------------------------------
* Function: test_filter_internal
*
* Purpose: Tests writing entire data and partial data with filters
*
* Return: Success: 0
* Failure: -1
*-------------------------------------------------------------------------
*/
static herr_t
test_filter_internal(hid_t fid, const char *name, hid_t dcpl)
{
herr_t ret_value = -1;
hid_t dataset = -1; /* Dataset ID */
hid_t dxpl = -1; /* Dataset xfer property list ID */
hid_t write_dxpl = -1; /* Dataset xfer property list ID for writing */
hid_t sid = -1; /* Dataspace ID */
const hsize_t size[2] = {DSET_DIM1, DSET_DIM2}; /* Dataspace dimensions */
const hsize_t hs_offset[2] = {FILTER_HS_OFFSET1, FILTER_HS_OFFSET2}; /* Hyperslab offset */
const hsize_t hs_size[2] = {FILTER_HS_SIZE1, FILTER_HS_SIZE2}; /* Hyperslab size */
void *tconv_buf = NULL; /* Temporary conversion buffer */
int points[DSET_DIM1][DSET_DIM2], check[DSET_DIM1][DSET_DIM2];
size_t i, j; /* Local index variables */
int n = 0;
/* Create the data space */
if((sid = H5Screate_simple(2, size, NULL)) < 0) TEST_ERROR
/*
* Create a small conversion buffer to test strip mining. We
* might as well test all we can!
*/
if((dxpl = H5Pcreate(H5P_DATASET_XFER)) < 0) TEST_ERROR
tconv_buf = HDmalloc((size_t)1000);
if(H5Pset_buffer(dxpl, (size_t)1000, tconv_buf, NULL) < 0) TEST_ERROR
if((write_dxpl = H5Pcopy(dxpl)) < 0) TEST_ERROR;
TESTING(" filters (setup)");
/* Check if all the filters are available */
if(H5Pall_filters_avail(dcpl) != TRUE) {
H5_FAILED();
HDprintf(" Line %d: Incorrect filter availability\n", __LINE__);
TEST_ERROR
} /* end if */
/* Create the dataset */
if((dataset = H5Dcreate2(fid, name, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) TEST_ERROR
PASSED();
/*----------------------------------------------------------------------
* STEP 1: Read uninitialized data. It should be zero.
*----------------------------------------------------------------------
*/
TESTING(" filters (uninitialized read)");
if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl, check) < 0) TEST_ERROR;
for(i=0; i<(size_t)size[0]; i++)
for(j=0; j<(size_t)size[1]; j++)
if(0 != check[i][j]) {
H5_FAILED();
HDprintf(" Read a non-zero value.\n");
HDprintf(" At index %lu,%lu\n", (unsigned long)i, (unsigned long)j);
TEST_ERROR
} /* end if */
PASSED();
/*----------------------------------------------------------------------
* STEP 2: Test filters by setting up a chunked dataset and writing
* to it.
*----------------------------------------------------------------------
*/
TESTING(" filters (write)");
n = 0;
for(i=0; i<size[0]; i++)
for(j=0; j<size[1]; j++)
points[i][j] = (int)(n++);
if(H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, write_dxpl, points) < 0) TEST_ERROR;
PASSED();
/*----------------------------------------------------------------------
* STEP 3: Try to read the data we just wrote.
*----------------------------------------------------------------------
*/
TESTING(" filters (read)");
/* Read the dataset back */
if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl, check) < 0) TEST_ERROR;
/* Check that the values read are the same as the values written */
for(i=0; i<size[0]; i++)
for(j=0; j<size[1]; j++)
if(points[i][j] != check[i][j]) {
H5_FAILED();
HDfprintf(stderr," Read different values than written.\n");
HDfprintf(stderr," At index %lu,%lu\n", (unsigned long)i, (unsigned long)j);
HDfprintf(stderr," At original: %d\n", (int)points[i][j]);
HDfprintf(stderr," At returned: %d\n", (int)check[i][j]);
TEST_ERROR
} /* end if */
PASSED();
/*----------------------------------------------------------------------
* STEP 4: Write new data over the top of the old data. The new data is
* random thus not very compressible, and will cause the chunks to move
* around as they grow. We only change values for the left half of the
* dataset although we rewrite the whole thing.
*----------------------------------------------------------------------
*/
TESTING(" filters (modify)");
for(i=0; i<size[0]; i++)
for(j=0; j<size[1]/2; j++)
points[i][j] = (int)HDrandom () % RANDOM_LIMIT;
if(H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, write_dxpl, points) < 0) TEST_ERROR;
/* Read the dataset back and check it */
if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl, check) < 0) TEST_ERROR;
/* Check that the values read are the same as the values written */
for(i=0; i<size[0]; i++)
for(j=0; j<size[1]; j++)
if(points[i][j] != check[i][j]) {
H5_FAILED();
HDprintf(" Read different values than written.\n");
HDprintf(" At index %lu,%lu\n", (unsigned long)i, (unsigned long)j);
TEST_ERROR
} /* end if */
PASSED();
/*----------------------------------------------------------------------
* STEP 5: Close the dataset and then open it and read it again. This
* insures that the filters message is picked up properly from the
* object header.
*----------------------------------------------------------------------
*/
TESTING(" filters (re-open)");
if(H5Dclose(dataset) < 0) TEST_ERROR;
if((dataset = H5Dopen2(fid, name, H5P_DEFAULT)) < 0) TEST_ERROR;
if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl, check) < 0) TEST_ERROR;
/* Check that the values read are the same as the values written */
for(i = 0; i < size[0]; i++)
for(j = 0; j < size[1]; j++)
if(points[i][j] != check[i][j]) {
H5_FAILED();
HDprintf(" Read different values than written.\n");
HDprintf(" At index %lu,%lu\n", (unsigned long)i, (unsigned long)j);
TEST_ERROR
} /* end if */
PASSED();
/*----------------------------------------------------------------------
* STEP 6: Test partial I/O by writing to and then reading from a
* hyperslab of the dataset. The hyperslab does not line up on chunk
* boundaries (we know that case already works from above tests).
*----------------------------------------------------------------------
*/
TESTING(" filters (partial I/O)");
for(i=0; i<(size_t)hs_size[0]; i++)
for(j=0; j<(size_t)hs_size[1]; j++)
points[(size_t)hs_offset[0]+i][(size_t)hs_offset[1]+j] = (int)HDrandom() % RANDOM_LIMIT;
if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, hs_offset, NULL, hs_size, NULL) < 0) TEST_ERROR;
/* (Use the "read" DXPL because partial I/O on corrupted data test needs to ignore errors during writing) */
if(H5Dwrite(dataset, H5T_NATIVE_INT, sid, sid, dxpl, points) < 0) TEST_ERROR;
if(H5Dread(dataset, H5T_NATIVE_INT, sid, sid, dxpl, check) < 0) TEST_ERROR;
/* Check that the values read are the same as the values written */
for(i=0; i<(size_t)hs_size[0]; i++)
for(j=0; j<(size_t)hs_size[1]; j++)
if(points[(size_t)hs_offset[0]+i][(size_t)hs_offset[1]+j] != check[(size_t)hs_offset[0]+i][(size_t)hs_offset[1]+j]) {
H5_FAILED();
HDfprintf(stderr," Read different values than written.\n");
HDfprintf(stderr," At index %lu,%lu\n", (unsigned long)((size_t)hs_offset[0]+i), (unsigned long)((size_t)hs_offset[1]+j));
HDfprintf(stderr," At original: %d\n", (int)points[(size_t)hs_offset[0]+i][(size_t)hs_offset[1]+j]);
HDfprintf(stderr," At returned: %d\n", (int)check[(size_t)hs_offset[0]+i][(size_t)hs_offset[1]+j]);
TEST_ERROR
} /* end if */
PASSED();
/* Save the data written to the file for later comparison when the file
* is reopened for read test */
for(i=0; i<size[0]; i++)
for(j=0; j<size[1]; j++)
if(!HDstrcmp(name, DSET_DEFLATE_NAME))
points_deflate[i][j] = points[i][j];
else if(!HDstrcmp(name, DSET_DYNLIB1_NAME))
points_dynlib1[i][j] = points[i][j];
else if(!HDstrcmp(name, DSET_DYNLIB2_NAME))
points_dynlib2[i][j] = points[i][j];
else if(!HDstrcmp(name, DSET_DYNLIB4_NAME))
points_dynlib4[i][j] = points[i][j];
ret_value = 0;
error:
/* Clean up objects used for this test */
H5E_BEGIN_TRY {
H5Dclose(dataset);
H5Sclose(sid);
H5Pclose(dxpl);
} H5E_END_TRY
if(tconv_buf)
HDfree(tconv_buf);
return ret_value;
}
/*-------------------------------------------------------------------------
* Function: test_filters_for_datasets
*
* Purpose: Tests creating datasets and writing data with dynamically loaded filters
*
* Return: Success: 0
* Failure: -1
*-------------------------------------------------------------------------
*/
static herr_t
test_filters_for_datasets(hid_t file)
{
herr_t ret_value = -1;
hid_t dc = -1; /* Dataset creation property list ID */
const hsize_t chunk_size[2] = {FILTER_CHUNK_DIM1, FILTER_CHUNK_DIM2}; /* Chunk dimensions */
unsigned int compress_level = 9;
unsigned int dynlib4_values[4];
/*----------------------------------------------------------
* STEP 1: Test deflation by itself.
*----------------------------------------------------------
*/
HDputs("Testing deflate filter");
#ifdef H5_HAVE_FILTER_DEFLATE
if((dc = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR
if(H5Pset_chunk(dc, 2, chunk_size) < 0) TEST_ERROR
if(H5Pset_deflate(dc, 6) < 0) TEST_ERROR
if(test_filter_internal(file, DSET_DEFLATE_NAME, dc) < 0) TEST_ERROR
/* Clean up objects used for this test */
if(H5Pclose(dc) < 0) TEST_ERROR
#else /* H5_HAVE_FILTER_DEFLATE */
SKIPPED();
HDputs(" Deflate filter not enabled");
#endif /* H5_HAVE_FILTER_DEFLATE */
/*----------------------------------------------------------
* STEP 2: Test DYNLIB1 by itself.
*----------------------------------------------------------
*/
HDputs(" DYNLIB1 filter");
if((dc = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR
if(H5Pset_chunk(dc, 2, chunk_size) < 0) TEST_ERROR
if(H5Pset_filter(dc, H5Z_FILTER_DYNLIB1, H5Z_FLAG_MANDATORY, (size_t)1, &compress_level) < 0) TEST_ERROR
if(test_filter_internal(file, DSET_DYNLIB1_NAME, dc) < 0) TEST_ERROR
/* Clean up objects used for this test */
if(H5Pclose(dc) < 0) TEST_ERROR
/* Unregister the dynamic filter DYNLIB1 for testing purpose. The next time when this test is run for
* the new file format, the library's H5PL code has to search in the table of loaded plugin libraries
* for this filter. */
if(H5Zunregister(H5Z_FILTER_DYNLIB1) < 0) TEST_ERROR
/*----------------------------------------------------------
* STEP 3: Test DYNLIB2 by itself.
*----------------------------------------------------------
*/
HDputs(" DYNLIB2 filter");
if((dc = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR
if(H5Pset_chunk(dc, 2, chunk_size) < 0) TEST_ERROR
if(H5Pset_filter(dc, H5Z_FILTER_DYNLIB2, H5Z_FLAG_MANDATORY, 0, NULL) < 0) TEST_ERROR
if(test_filter_internal(file,DSET_DYNLIB2_NAME,dc) < 0) TEST_ERROR
/* Clean up objects used for this test */
if(H5Pclose(dc) < 0) TEST_ERROR
/* Unregister the dynamic filter DYNLIB2 for testing purpose. The next time when this test is run for
* the new file format, the library's H5PL code has to search in the table of loaded plugin libraries
* for this filter. */
if(H5Zunregister(H5Z_FILTER_DYNLIB2) < 0) TEST_ERROR
/*----------------------------------------------------------
* STEP 4: Test DYNLIB4 by itself.
*----------------------------------------------------------
*/
HDputs(" DYNLIB4 filter");
if((dc = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR
if(H5Pset_chunk(dc, 2, chunk_size) < 0) TEST_ERROR
dynlib4_values[0] = 9;
if(H5get_libversion(&dynlib4_values[1], &dynlib4_values[2], &dynlib4_values[3]) < 0) TEST_ERROR
if(H5Pset_filter(dc, H5Z_FILTER_DYNLIB4, H5Z_FLAG_MANDATORY, (size_t)4, dynlib4_values) < 0) TEST_ERROR
if(test_filter_internal(file, DSET_DYNLIB4_NAME, dc) < 0) TEST_ERROR
/* Clean up objects used for this test */
if(H5Pclose(dc) < 0) TEST_ERROR
/* Unregister the dynamic filter DYNLIB4 for testing purpose. The next time when this test is run for
* the new file format, the library's H5PL code has to search in the table of loaded plugin libraries
* for this filter. */
if(H5Zunregister(H5Z_FILTER_DYNLIB4) < 0) TEST_ERROR
ret_value = 0;
error:
/* Clean up objects used for this test */
H5E_BEGIN_TRY {
H5Pclose(dc);
} H5E_END_TRY
return ret_value;
}
/*-------------------------------------------------------------------------
* Function: test_read_data
*
* Purpose: Tests reading data and compares values
*
* Return: Success: 0
* Failure: -1
*-------------------------------------------------------------------------
*/
static herr_t
test_read_data(hid_t dataset, int *origin_data)
{
herr_t ret_value = -1;
int check[DSET_DIM1][DSET_DIM2];
const hsize_t size[2] = {DSET_DIM1, DSET_DIM2}; /* Dataspace dimensions */
int *data_p = origin_data;
size_t i, j; /* Local index variables */
/* Read the dataset back */
if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, check) < 0) TEST_ERROR;
/* Check that the values read are the same as the values written */
for(i=0; i<size[0]; i++)
for(j=0; j<size[1]; j++) {
if(*data_p != check[i][j]) {
H5_FAILED();
HDfprintf(stderr," Read different values than written.\n");
HDfprintf(stderr," At index %lu,%lu\n", (unsigned long)i, (unsigned long)j);
HDfprintf(stderr," At original: %d\n", *data_p);
HDfprintf(stderr," At returned: %d\n", (int)check[i][j]);
TEST_ERROR
} /* end if */
data_p++;
}
PASSED();
ret_value = 0;
error:
return ret_value;
}
/*-------------------------------------------------------------------------
* Function: test_read_with_filters
*
* Purpose: Tests reading dataset created with dynamically loaded filters
*
* Return: Success: 0
* Failure: -1
*-------------------------------------------------------------------------
*/
static herr_t
test_read_with_filters(hid_t file)
{
herr_t ret_value = -1;
hid_t dset = -1; /* Dataset ID */
/*----------------------------------------------------------
* STEP 1: Test deflation by itself.
*----------------------------------------------------------
*/
TESTING("deflate filter");
#ifdef H5_HAVE_FILTER_DEFLATE
if(H5Zfilter_avail(H5Z_FILTER_DEFLATE) != TRUE) TEST_ERROR
if((dset = H5Dopen2(file,DSET_DEFLATE_NAME,H5P_DEFAULT)) < 0) TEST_ERROR
if(test_read_data(dset, (int *)points_deflate) < 0) TEST_ERROR
if(H5Dclose(dset) < 0) TEST_ERROR
/* Clean up objects used for this test */
#else /* H5_HAVE_FILTER_DEFLATE */
SKIPPED();
HDputs(" Deflate filter not enabled");
#endif /* H5_HAVE_FILTER_DEFLATE */
/*----------------------------------------------------------
* STEP 2: Test DYNLIB1 by itself.
*----------------------------------------------------------
*/
TESTING(" DYNLIB1 filter");
if((dset = H5Dopen2(file, DSET_DYNLIB1_NAME, H5P_DEFAULT)) < 0) TEST_ERROR
if(test_read_data(dset, (int *)points_dynlib1) < 0) TEST_ERROR
if(H5Dclose(dset) < 0) TEST_ERROR
/*----------------------------------------------------------
* STEP 3: Test Bogus2 by itself.
*----------------------------------------------------------
*/
TESTING(" DYNLIB2 filter");
if((dset = H5Dopen2(file, DSET_DYNLIB2_NAME, H5P_DEFAULT)) < 0) TEST_ERROR
if(test_read_data(dset, (int *)points_dynlib2) < 0) TEST_ERROR
if(H5Dclose(dset) < 0) TEST_ERROR
/*----------------------------------------------------------
* STEP 4: Test DYNLIB4 by itself.
*----------------------------------------------------------
*/
TESTING(" DYNLIB4 filter");
if((dset = H5Dopen2(file,DSET_DYNLIB4_NAME,H5P_DEFAULT)) < 0) TEST_ERROR
if(test_read_data(dset, (int *)points_dynlib4) < 0) TEST_ERROR
if(H5Dclose(dset) < 0) TEST_ERROR
ret_value = 0;
error:
/* Clean up objects used for this test */
H5E_BEGIN_TRY {
H5Dclose(dset);
} H5E_END_TRY
return ret_value;
}
/*-------------------------------------------------------------------------
* Function: test_noread_data
*
* Purpose: Tests not reading data
*
* Return: Success: 0
* Failure: -1
*
*-------------------------------------------------------------------------
*/
static herr_t
test_noread_data(hid_t dataset)
{
herr_t ret_value = -1;
int check[DSET_DIM1][DSET_DIM2];
herr_t ret = -1;
/* Read the dataset back */
H5E_BEGIN_TRY {
ret = H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, check);
} H5E_END_TRY
if(ret >= 0)
TEST_ERROR
PASSED();
ret_value = 0;
error:
return ret_value;
}
/*-------------------------------------------------------------------------
* Function: test_noread_with_filters
*
* Purpose: Tests reading dataset created with dynamically loaded filters disabled
*
* Return: Success: 0
* Failure: -1
*-------------------------------------------------------------------------
*/
static herr_t
test_noread_with_filters(hid_t file)
{
herr_t ret_value = -1;
hid_t dset = -1; /* Dataset ID */
unsigned plugin_state; /* status of plugins */
TESTING("DYNLIB1 filter with plugins disabled");
/* disable filter plugin */
if(H5PLget_loading_state(&plugin_state) < 0) TEST_ERROR
plugin_state = plugin_state & (unsigned)(~H5PL_FILTER_PLUGIN);
if(H5PLset_loading_state(plugin_state) < 0) TEST_ERROR
if((dset = H5Dopen2(file, DSET_DYNLIB1_NAME, H5P_DEFAULT)) < 0) TEST_ERROR
if(test_noread_data(dset) < 0) TEST_ERROR
if(H5Dclose(dset) < 0) TEST_ERROR
ret_value = 0;
error:
/* re-enable filter plugin */
plugin_state = plugin_state | H5PL_FILTER_PLUGIN;
H5PLset_loading_state(plugin_state);
/* Clean up objects used for this test */
H5E_BEGIN_TRY {
H5Dclose(dset);
} H5E_END_TRY
return ret_value;
}
/*-------------------------------------------------------------------------
* Function: test_filters_for_groups
*
* Purpose: Tests creating group with dynamically loaded filters
*
* Return: Success: 0
* Failure: -1
*-------------------------------------------------------------------------
*/
static herr_t
test_filters_for_groups(hid_t file)
{
herr_t ret_value = -1;
hid_t gcpl = -1;
hid_t gid = -1;
hid_t group = -1;
int i;
char gname[256];
TESTING("DYNLIB3 filter for group");
if((gcpl = H5Pcreate(H5P_GROUP_CREATE)) < 0) TEST_ERROR
/* Use DYNLIB3 for creating groups */
if(H5Pset_filter (gcpl, H5Z_FILTER_DYNLIB3, H5Z_FLAG_MANDATORY, (size_t)0, NULL) < 0) TEST_ERROR
/* Create a group using this filter */
if((gid = H5Gcreate2(file, "group1", H5P_DEFAULT, gcpl, H5P_DEFAULT)) < 0) TEST_ERROR
/* Create multiple groups under "group1" */
for(i=0; i < GROUP_ITERATION; i++) {
HDsprintf(gname, "group_%d", i);
if((group = H5Gcreate2(gid, gname, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Gclose(group) < 0) TEST_ERROR
}
/* Close the group */
if(H5Gclose(gid) < 0) TEST_ERROR
/* Clean up objects used for this test */
if(H5Pclose(gcpl) < 0) TEST_ERROR
PASSED();
ret_value = 0;
error:
/* Clean up objects used for this test */
H5E_BEGIN_TRY {
H5Gclose(group);
H5Gclose(gid);
H5Pclose(gcpl);
} H5E_END_TRY
return ret_value;
}
/*-------------------------------------------------------------------------
* Function: test_groups_with_filters
*
* Purpose: Tests opening group with dynamically loaded filters
*
* Return: Success: 0
* Failure: -1
*
*-------------------------------------------------------------------------
*/
static herr_t
test_groups_with_filters(hid_t file)
{
herr_t ret_value = -1;
hid_t gid = -1;
hid_t group = -1;
int i;
char gname[256];
TESTING("opening groups with DYNLIB3 filter");
/* Open the top group */
if((gid = H5Gopen2(file, "group1", H5P_DEFAULT)) < 0) TEST_ERROR
/* Create multiple groups under "group1" */
for(i=0; i < GROUP_ITERATION; i++) {
HDsprintf(gname, "group_%d", i);
if((group = H5Gopen2(gid, gname, H5P_DEFAULT)) < 0) TEST_ERROR
if(H5Gclose(group) < 0) TEST_ERROR
}
/* Close the group */
if(H5Gclose(gid) < 0) TEST_ERROR
PASSED();
ret_value = 0;
error:
/* Clean up objects used for this test */
H5E_BEGIN_TRY {
H5Gclose(group);
H5Gclose(gid);
} H5E_END_TRY
return ret_value;
}
/*-------------------------------------------------------------------------
* Function: test_path_api_calls
*
* Purpose: Tests the H5PL API calls that manipulate the plugin search
* paths.
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
test_path_api_calls(void)
{
unsigned int n_starting_paths;
unsigned int u;
unsigned int n_paths;
herr_t ret;
ssize_t path_len = -1;
char path[256];
char temp_name[256];
herr_t ret_value = -1;
HDputs("Testing access to the filter path table");
if(H5Zfilter_avail(H5Z_FILTER_DYNLIB1) != TRUE)
TEST_ERROR
/* Set the number of paths to create for this test.
*
* This should be set high enough to ensure that at least one array
* expansion will take place. See H5PLpath.c for details.
*/
n_starting_paths = 42;
/****************/
/* H5PLremove() */
/****************/
/* Remove all the current paths */
TESTING(" remove");
/* Get the current size */
if(H5PLsize(&n_paths) < 0)
TEST_ERROR
/* Remove all existing paths */
for(u = n_paths; u > 0; u--)
if(H5PLremove(u-1) < 0) {
HDfprintf(stderr," at %u: %s\n", u, path);
TEST_ERROR
}
/* Verify the table is empty */
if(H5PLsize(&n_paths) < 0)
TEST_ERROR
if(n_paths > 0)
TEST_ERROR
PASSED();
TESTING(" remove (index 0 in empty table)");
/* Try to remove index zero in an empty list (SHOULD FAIL) */
H5E_BEGIN_TRY {
ret = H5PLremove(0);
} H5E_END_TRY
if(ret >= 0)
TEST_ERROR
PASSED();
/****************/
/* H5PLappend() */
/****************/
TESTING(" append");
/* Add a bunch of paths to the path table */
for(u = 0; u < n_starting_paths; u++) {
HDsprintf(path, "a_path_%u", u);
if(H5PLappend(path) < 0) {
HDfprintf(stderr," at %u: %s\n", u, path);
TEST_ERROR
}
}
PASSED();
/**********************/
/* H5PLremove() again */
/**********************/
TESTING(" remove (index too high)");
/* Try to remove a path where the index is beyond the table capacity (SHOULD FAIL) */
H5E_BEGIN_TRY {
ret = H5PLremove(n_starting_paths);
} H5E_END_TRY
if(ret >= 0)
TEST_ERROR
PASSED();
/*************/
/* H5PLget() */
/*************/
TESTING(" get (path name)");
/* Get the path length by passing in NULL */
if((path_len = H5PLget(0, NULL, 0)) <= 0) {
HDfprintf(stderr," get path 0 length failed\n");
TEST_ERROR
}
if(path_len != 8)
TEST_ERROR
/* Get the path */
if((path_len = H5PLget(0, path, 256)) <= 0) {
HDfprintf(stderr," get 0 len: %u : %s\n", path_len, path);
TEST_ERROR
}
if(HDstrcmp(path, "a_path_0") != 0) {
HDfprintf(stderr," get 0: %s\n", path);
TEST_ERROR
}
PASSED();
TESTING(" get (high and low indices)");
/* Get path at index 1 */
if((path_len = H5PLget(1, path, 256)) <= 0)
TEST_ERROR
if(HDstrcmp(path, "a_path_1") != 0) {
HDfprintf(stderr," get 1: %s\n", path);
TEST_ERROR
}
/* Get path at the last index */
if((path_len = H5PLget(n_starting_paths - 1, path, 256)) <= 0)
TEST_ERROR
HDsprintf(temp_name, "a_path_%u", n_starting_paths - 1);
if(HDstrcmp(path, temp_name) != 0) {
HDfprintf(stderr," get %u: %s\n", n_starting_paths - 1, path);
TEST_ERROR
}
PASSED();
TESTING(" get (index too high)");
/* Get path at the last + 1 index (SHOULD FAIL) */
H5E_BEGIN_TRY {
path_len = H5PLget(n_starting_paths, NULL, 0);
} H5E_END_TRY
if(path_len > 0)
TEST_ERROR
PASSED();
/*****************/
/* H5PLprepend() */
/*****************/
/* We'll remove a path at an arbitrary index and then
* prepend a new path.
*/
TESTING(" remove (arbitrary index 1)");
/* Remove one path */
if(H5PLremove(8) < 0)
TEST_ERROR
/* Verify that the entries were moved */
if((path_len = H5PLget(8, path, 256)) <= 0)
TEST_ERROR
if(HDstrcmp(path, "a_path_9") != 0) {
HDfprintf(stderr," get 8: %s\n", path);
TEST_ERROR
}
/* Verify the table shrank */
if(H5PLsize(&n_paths) < 0)
TEST_ERROR
if(n_paths != n_starting_paths - 1)
TEST_ERROR
PASSED();
TESTING(" prepend");
/* Prepend one path */
HDsprintf(path, "a_path_%d", n_starting_paths + 1);
if(H5PLprepend(path) < 0) {
HDfprintf(stderr," prepend %u: %s\n", n_starting_paths + 1, path);
TEST_ERROR
}
/* Verify the table increased */
if(H5PLsize(&n_paths) < 0)
TEST_ERROR
if(n_paths != n_starting_paths)
TEST_ERROR
/* Verify that the entries were moved */
if(H5PLget(8, path, 256) <= 0)
TEST_ERROR
if(HDstrcmp(path, "a_path_7") != 0) {
HDfprintf(stderr," get 8: %s\n", path);
TEST_ERROR
}
/* Verify that the path was inserted at index zero */
if(H5PLget(0, path, 256) <= 0)
TEST_ERROR
HDsprintf(temp_name, "a_path_%d", n_starting_paths + 1);
if(HDstrcmp(path, temp_name) != 0) {
HDfprintf(stderr," get 0: %s\n", path);
TEST_ERROR
}
PASSED();
/*****************/
/* H5PLreplace() */
/*****************/
TESTING(" replace");
/* Replace one path at index 1 */
HDsprintf(path, "a_path_%u", n_starting_paths + 4);
if(H5PLreplace(path, 1) < 0) {
HDfprintf(stderr," replace 1: %s\n", path);
TEST_ERROR
}
/* Verify the table size remained the same */
if(H5PLsize(&n_paths) < 0)
TEST_ERROR
if(n_paths != n_starting_paths)
TEST_ERROR
/* Verify that the entries were not moved by
* inspecting the paths at indices +/- 1.
*/
/* Check path at index 0 */
if(H5PLget(0, path, 256) <= 0)
TEST_ERROR
HDsprintf(temp_name, "a_path_%u", n_starting_paths + 1);
if(HDstrcmp(path, temp_name) != 0) {
HDfprintf(stderr," get 0: %s\n", path);
TEST_ERROR
}
/* Check path at index 2 */
if(H5PLget(2, path, 256) <= 0)
TEST_ERROR
if(HDstrcmp(path, "a_path_1") != 0) {
HDfprintf(stderr," get 2: %s\n", path);
TEST_ERROR
}
PASSED();
/****************/
/* H5PLinsert() */
/****************/
/* We'll remove a path at an arbitrary index and then
* insert a new path.
*/
TESTING(" remove (arbitrary index 2)");
/* Remove one path */
if(H5PLremove(4) < 0)
TEST_ERROR
/* Verify that the entries were moved */
if(H5PLget(4, path, 256) <= 0)
TEST_ERROR
if(HDstrcmp(path, "a_path_4") != 0) {
HDfprintf(stderr," get 4: %s\n", path);
TEST_ERROR
}
/* Verify the table size */
if(H5PLsize(&n_paths) < 0)
TEST_ERROR
if(n_paths != n_starting_paths - 1)
TEST_ERROR
PASSED();
TESTING(" insert");
/* Insert one path at index 3*/
HDsprintf(path, "a_path_%d", n_starting_paths + 5);
if(H5PLinsert(path, 3) < 0) {
HDfprintf(stderr," insert 3: %s\n", path);
TEST_ERROR
}
/* Verify that the entries were moved */
if(H5PLget(4, path, 256) <= 0)
TEST_ERROR
if(HDstrcmp(path, "a_path_2") != 0) {
HDfprintf(stderr," get 4: %s\n", path);
TEST_ERROR
}
/* Verify the table size increased */
if(H5PLsize(&n_paths) < 0)
TEST_ERROR
if(n_paths != n_starting_paths)
TEST_ERROR
PASSED();
/****************/
/* H5PLremove() */
/****************/
/* Remove all the current paths */
TESTING(" remove (all)");
/* Get the current size */
if(H5PLsize(&n_paths) < 0)
TEST_ERROR
/* Remove all existing paths */
for(u = n_paths; u > 0; u--)
if(H5PLremove(u-1) < 0) {
HDfprintf(stderr," at %u: %s\n", u, path);
TEST_ERROR
}
/* Verify the table is empty */
if(H5PLsize(&n_paths) < 0)
TEST_ERROR
if(n_paths > 0)
TEST_ERROR
PASSED();
return SUCCEED;
error:
return FAIL;
} /* end test_path_api_calls() */
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Tests the plugin module (H5PL)
*
* Return: EXIT_SUCCESS/EXIT_FAILURE
*
*-------------------------------------------------------------------------
*/
int
main(void)
{
char filename[FILENAME_BUF_SIZE];
hid_t file = -1;
hid_t fapl = -1;
hid_t fapl2 = -1;
unsigned new_format;
int mdc_nelmts;
size_t rdcc_nelmts;
size_t rdcc_nbytes;
double rdcc_w0;
int nerrors = 0;
/* Testing setup */
h5_reset();
fapl = h5_fileaccess();
/* Turn off the chunk cache, so all the chunks are immediately written to disk */
if(H5Pget_cache(fapl, &mdc_nelmts, &rdcc_nelmts, &rdcc_nbytes, &rdcc_w0) < 0) TEST_ERROR
rdcc_nbytes = 0;
if(H5Pset_cache(fapl, mdc_nelmts, rdcc_nelmts, rdcc_nbytes, rdcc_w0) < 0) TEST_ERROR
/* Copy the file access property list */
if((fapl2 = H5Pcopy(fapl)) < 0) TEST_ERROR
/* Set the "use the latest version of the format" bounds for creating objects in the file */
if(H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) TEST_ERROR
h5_fixname(FILENAME[0], fapl, filename, sizeof filename);
/* Test with old & new format groups */
for(new_format = FALSE; new_format <= TRUE; new_format++) {
hid_t my_fapl;
/* Set the FAPL for the type of format */
if(new_format) {
HDputs("\nTesting with new file format:");
my_fapl = fapl2;
} /* end if */
else {
HDputs("Testing with old file format:");
my_fapl = fapl;
} /* end else */
/* Create the file for this test */
if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0) TEST_ERROR
/* Test dynamically loaded filters for chunked dataset */
nerrors += (test_filters_for_datasets(file) < 0 ? 1 : 0);
/* Test dynamically loaded filters for groups */
nerrors += (test_filters_for_groups(file) < 0 ? 1 : 0);
if(H5Fclose(file) < 0) TEST_ERROR
} /* end for */
/* Close FAPL */
if(H5Pclose(fapl2) < 0) TEST_ERROR
if(H5Pclose(fapl) < 0) TEST_ERROR
/* Restore the default error handler (set in h5_reset()) */
h5_restore_err();
HDputs("\nTesting reading data with with dynamic plugin filters:");
/* Close the library so that all loaded plugin libraries are unloaded */
h5_reset();
fapl = h5_fileaccess();
/* Reopen the file for testing data reading */
if((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR
/* Read the data with filters */
nerrors += (test_read_with_filters(file) < 0 ? 1 : 0);
/* Open the groups with filters */
nerrors += (test_groups_with_filters(file) < 0 ? 1 : 0);
/* Restore the default error handler (set in h5_reset()) */
h5_restore_err();
/* Close the library so that all loaded plugin libraries are unloaded */
h5_reset();
fapl = h5_fileaccess();
/* Reopen the file for testing data reading */
if((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR
/* Read the data with disabled filters */
nerrors += (test_noread_with_filters(file) < 0 ? 1 : 0);
if(H5Fclose(file) < 0) TEST_ERROR
/* Test the APIs for access to the filter plugin path table */
nerrors += (test_path_api_calls() < 0 ? 1 : 0);
if(nerrors)
TEST_ERROR
HDprintf("All plugin tests passed.\n");
h5_cleanup(FILENAME, fapl);
HDexit(EXIT_SUCCESS);
error:
nerrors = MAX(1, nerrors);
HDprintf("***** %d PLUGIN TEST%s FAILED! *****\n", nerrors, 1 == nerrors ? "" : "S");
HDexit(EXIT_FAILURE);
} /* end main() */